ruby_dsp 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/ext/ruby_dsp/ruby_dsp.cpp +78 -10
- data/ext/ruby_dsp/vendor/pocketfft_hdronly.h +3760 -0
- data/lib/ruby_dsp/version.rb +1 -1
- data/stubs/ruby_dsp/audio_track.rb +86 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d044ff97e82f0fdedd8749cfa07573fd350cd793094d9274700e623caf35e098
|
|
4
|
+
data.tar.gz: 2559e81b76c114cfa10dff50aa422bb29a933def9b75a2893c8f53c12a76f619
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 97c853452400908572b918d94460ded68831dbb7d550f648a8291147d6fbdcee5e75e8ba36715622ed0dd90f978b1547a9661523c1d80b93b1f0b8ed2139bd66
|
|
7
|
+
data.tar.gz: 1d6a9728f02760fa579858c83e2a81c28c486cfcd9dc556cf0f8d6106389a373c2f4444364b5a6acacb3821a16cabad396e7e9c9cc30f9c046dc4b91fa06f70d
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# [RubyDSP](https://github.com/cichrrad/rubyDSP) | [Documentation](https://www.rubydoc.info/gems/ruby_dsp/0.0.
|
|
1
|
+
# [RubyDSP](https://github.com/cichrrad/rubyDSP) | [Documentation](https://www.rubydoc.info/gems/ruby_dsp/0.0.9)
|
|
2
2
|
|
|
3
3
|
[](https://github.com/cichrrad/rubyDSP/actions/workflows/test.yml)
|
|
4
4
|
|
|
5
|
-
> 🚧 **Status:** This (***HOBBY***) project is currently in early development. It is
|
|
5
|
+
> 🚧 **Status:** This (***HOBBY***) project is currently in early development. It is functional, but API changes are expected. There is no warranty regarding anything 🗿.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -30,7 +30,7 @@ I made this gem to try hands-on binding these two languages together, as I would
|
|
|
30
30
|
|
|
31
31
|
## Overview of Capabilities
|
|
32
32
|
|
|
33
|
-
* **File Operations:** `save_track`
|
|
33
|
+
* **File Operations:** `save_track`, `dup`
|
|
34
34
|
* **Mutations:** `to_mono!`, `resample!`, `trim_silence!`, `normalize!`, `fade_in!`, `fade_out!`, `pad!`, `pad_to_duration!`, `clip!`
|
|
35
35
|
* **DSP Filters:** `low_pass!`, `high_pass!`, `band_pass!`, `notch!`, `peak_eq!`, `low_shelf!`, `high_shelf!`
|
|
36
36
|
* **Synthesis:** `add_wave!`
|
data/ext/ruby_dsp/ruby_dsp.cpp
CHANGED
|
@@ -34,9 +34,33 @@ struct AudioTrack
|
|
|
34
34
|
std::vector<float> samples;
|
|
35
35
|
unsigned long long sample_count = 0;
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
// static float get_file_duration(std::string filename)
|
|
38
|
+
// {
|
|
39
|
+
// if (filename.empty())
|
|
40
|
+
// return 0.0f;
|
|
41
|
+
|
|
42
|
+
// ma_decoder decoder;
|
|
43
|
+
// // NULL config means it reads the file's native format/rate
|
|
44
|
+
// if (ma_decoder_init_file(filename.c_str(), NULL, &decoder) != MA_SUCCESS)
|
|
45
|
+
// {
|
|
46
|
+
// throw std::runtime_error("RubyDSP: Could not process audio file for duration: " + filename);
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
// ma_uint64 totalFrames;
|
|
50
|
+
// if (ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrames) != MA_SUCCESS)
|
|
51
|
+
// {
|
|
52
|
+
// ma_decoder_uninit(&decoder);
|
|
53
|
+
// throw std::runtime_error("RubyDSP: Could not determine track length.");
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
// int sample_rate = decoder.outputSampleRate;
|
|
57
|
+
// ma_decoder_uninit(&decoder);
|
|
58
|
+
|
|
59
|
+
// return (float)totalFrames / sample_rate;
|
|
60
|
+
// }
|
|
61
|
+
|
|
62
|
+
AudioTrack(std::string f, unsigned int target_channels = 0, unsigned int target_sample_rate = 0, float start_sec = 0.0f, float duration_sec = 0.0f) : filename(f)
|
|
38
63
|
{
|
|
39
|
-
|
|
40
64
|
// empty constructor
|
|
41
65
|
if (filename.empty())
|
|
42
66
|
{
|
|
@@ -70,14 +94,49 @@ struct AudioTrack
|
|
|
70
94
|
throw std::runtime_error("RubyDSP: Could not determine track length.");
|
|
71
95
|
}
|
|
72
96
|
|
|
73
|
-
|
|
97
|
+
ma_uint64 start_frame = (ma_uint64)(start_sec * sample_rate);
|
|
98
|
+
if (start_frame > totalFrames)
|
|
99
|
+
{
|
|
100
|
+
start_frame = totalFrames; // Prevent seeking past EOF
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (start_frame > 0)
|
|
104
|
+
{
|
|
105
|
+
if (ma_decoder_seek_to_pcm_frame(&decoder, start_frame) != MA_SUCCESS)
|
|
106
|
+
{
|
|
107
|
+
ma_decoder_uninit(&decoder);
|
|
108
|
+
throw std::runtime_error("RubyDSP: Could not seek to start frame.");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
ma_uint64 framesToRead = totalFrames - start_frame;
|
|
113
|
+
if (duration_sec > 0.0f)
|
|
114
|
+
{
|
|
115
|
+
ma_uint64 requestedFrames = (ma_uint64)(duration_sec * sample_rate);
|
|
116
|
+
if (requestedFrames < framesToRead)
|
|
117
|
+
{
|
|
118
|
+
framesToRead = requestedFrames;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
sample_count = framesToRead * channels;
|
|
74
123
|
samples.resize(sample_count);
|
|
75
124
|
|
|
76
|
-
|
|
77
|
-
if (ma_decoder_read_pcm_frames(&decoder, samples.data(), totalFrames, &framesRead) != MA_SUCCESS)
|
|
125
|
+
if (framesToRead > 0)
|
|
78
126
|
{
|
|
79
|
-
|
|
80
|
-
|
|
127
|
+
ma_uint64 framesRead;
|
|
128
|
+
if (ma_decoder_read_pcm_frames(&decoder, samples.data(), framesToRead, &framesRead) != MA_SUCCESS)
|
|
129
|
+
{
|
|
130
|
+
ma_decoder_uninit(&decoder);
|
|
131
|
+
throw std::runtime_error("RubyDSP: Failed to read PCM data.");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Shrink vector if we hit EOF earlier than expected
|
|
135
|
+
if (framesRead < framesToRead)
|
|
136
|
+
{
|
|
137
|
+
sample_count = framesRead * channels;
|
|
138
|
+
samples.resize(sample_count);
|
|
139
|
+
}
|
|
81
140
|
}
|
|
82
141
|
|
|
83
142
|
ma_decoder_uninit(&decoder);
|
|
@@ -904,6 +963,11 @@ struct AudioTrack
|
|
|
904
963
|
<< sample_rate << "Hz sample rate]";
|
|
905
964
|
return stream.str();
|
|
906
965
|
}
|
|
966
|
+
|
|
967
|
+
AudioTrack dup()
|
|
968
|
+
{
|
|
969
|
+
return *this;
|
|
970
|
+
}
|
|
907
971
|
};
|
|
908
972
|
|
|
909
973
|
extern "C"
|
|
@@ -916,10 +980,12 @@ extern "C"
|
|
|
916
980
|
{
|
|
917
981
|
Module rb_mRubyDSP = define_module("RubyDSP");
|
|
918
982
|
Data_Type<AudioTrack> rb_cAudioTrack = define_class_under<AudioTrack>(rb_mRubyDSP, "AudioTrack")
|
|
919
|
-
.define_constructor(Constructor<AudioTrack, std::string, unsigned int, unsigned int>(),
|
|
983
|
+
.define_constructor(Constructor<AudioTrack, std::string, unsigned int, unsigned int, float, float>(),
|
|
920
984
|
Arg("file_name") = (std::string) "",
|
|
921
985
|
Arg("target_channels") = (unsigned int)0,
|
|
922
|
-
Arg("target_sample_rate") = (unsigned int)0
|
|
986
|
+
Arg("target_sample_rate") = (unsigned int)0,
|
|
987
|
+
Arg("start_sec") = 0.0f,
|
|
988
|
+
Arg("duration_sec") = 0.0f)
|
|
923
989
|
// attributes
|
|
924
990
|
.define_attr("file_name", &AudioTrack::filename, Rice::AttrAccess::Read)
|
|
925
991
|
.define_attr("channels", &AudioTrack::channels, Rice::AttrAccess::Read)
|
|
@@ -991,5 +1057,7 @@ extern "C"
|
|
|
991
1057
|
Arg("cutoff_freq"),
|
|
992
1058
|
Arg("gain_db"),
|
|
993
1059
|
Arg("q") = 0.707)
|
|
994
|
-
.define_method("to_s", &AudioTrack::to_s)
|
|
1060
|
+
.define_method("to_s", &AudioTrack::to_s)
|
|
1061
|
+
.define_method("dup", &AudioTrack::dup)
|
|
1062
|
+
.define_method("clone", &AudioTrack::dup);
|
|
995
1063
|
}
|