beeps 0.1.32 → 0.1.34

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/beeps/adsr.cpp +139 -0
  3. data/.doc/ext/beeps/analyser.cpp +128 -0
  4. data/.doc/ext/beeps/beeps.cpp +9 -1
  5. data/.doc/ext/beeps/file_in.cpp +55 -9
  6. data/.doc/ext/beeps/gain.cpp +64 -0
  7. data/.doc/ext/beeps/mic_in.cpp +83 -0
  8. data/.doc/ext/beeps/native.cpp +20 -8
  9. data/.doc/ext/beeps/oscillator.cpp +88 -0
  10. data/.doc/ext/beeps/pitch_shift.cpp +64 -0
  11. data/.doc/ext/beeps/processor.cpp +31 -2
  12. data/.doc/ext/beeps/sound.cpp +90 -7
  13. data/.doc/ext/beeps/sound_player.cpp +156 -0
  14. data/.doc/ext/beeps/time_stretch.cpp +64 -0
  15. data/.github/workflows/release-gem.yml +4 -1
  16. data/ChangeLog.md +14 -0
  17. data/Rakefile +26 -4
  18. data/VERSION +1 -1
  19. data/beeps.gemspec +2 -2
  20. data/ext/beeps/adsr.cpp +150 -0
  21. data/ext/beeps/analyser.cpp +134 -0
  22. data/ext/beeps/beeps.cpp +10 -1
  23. data/ext/beeps/extconf.rb +1 -2
  24. data/ext/beeps/file_in.cpp +60 -9
  25. data/ext/beeps/gain.cpp +67 -0
  26. data/ext/beeps/mic_in.cpp +88 -0
  27. data/ext/beeps/native.cpp +20 -8
  28. data/ext/beeps/oscillator.cpp +93 -0
  29. data/ext/beeps/pitch_shift.cpp +67 -0
  30. data/ext/beeps/processor.cpp +34 -2
  31. data/ext/beeps/sound.cpp +99 -7
  32. data/ext/beeps/sound_player.cpp +169 -0
  33. data/ext/beeps/time_stretch.cpp +67 -0
  34. data/include/beeps/beeps.h +2 -1
  35. data/include/beeps/filter.h +179 -0
  36. data/include/beeps/generator.h +120 -0
  37. data/include/beeps/processor.h +37 -68
  38. data/include/beeps/ruby/filter.h +78 -0
  39. data/include/beeps/ruby/generator.h +60 -0
  40. data/include/beeps/ruby/processor.h +5 -45
  41. data/include/beeps/ruby/sound.h +14 -3
  42. data/include/beeps/signals.h +10 -4
  43. data/include/beeps/sound.h +67 -2
  44. data/lib/beeps/beeps.rb +6 -1
  45. data/lib/beeps/processor.rb +95 -15
  46. data/lib/beeps/sound.rb +29 -2
  47. data/src/adsr.cpp +245 -0
  48. data/src/analyser.cpp +254 -0
  49. data/src/beeps.cpp +14 -2
  50. data/src/file_in.cpp +94 -0
  51. data/src/gain.cpp +55 -0
  52. data/src/mic_in.cpp +271 -0
  53. data/src/mic_in.h +22 -0
  54. data/src/openal.cpp +1 -2
  55. data/src/oscillator.cpp +145 -0
  56. data/src/osx/signals.mm +83 -0
  57. data/src/pitch_shift.cpp +82 -0
  58. data/src/processor.cpp +202 -88
  59. data/src/processor.h +98 -0
  60. data/src/signals.cpp +326 -20
  61. data/src/signals.h +192 -2
  62. data/src/sound.cpp +735 -113
  63. data/src/sound.h +6 -1
  64. data/src/time_stretch.cpp +91 -0
  65. data/test/helper.rb +2 -1
  66. data/test/test_beeps.rb +10 -7
  67. data/test/test_beeps_init.rb +18 -0
  68. data/test/test_file_in.rb +15 -0
  69. data/test/test_processor.rb +50 -0
  70. data/test/test_sound.rb +87 -11
  71. data/test/test_sound_player.rb +134 -0
  72. metadata +54 -16
  73. data/.doc/ext/beeps/sawtooth_wave.cpp +0 -61
  74. data/.doc/ext/beeps/sine_wave.cpp +0 -61
  75. data/.doc/ext/beeps/square_wave.cpp +0 -61
  76. data/ext/beeps/sawtooth_wave.cpp +0 -64
  77. data/ext/beeps/sine_wave.cpp +0 -64
  78. data/ext/beeps/square_wave.cpp +0 -64
data/src/signals.cpp CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
 
4
4
  #include <memory>
5
+ #include <algorithm>
6
+ #include <AudioFile.h>
7
+ #include <CDSPResampler.h>
5
8
  #include "beeps/beeps.h"
6
9
  #include "beeps/exception.h"
7
10
 
@@ -13,12 +16,14 @@ namespace Beeps
13
16
  struct Signals::Data
14
17
  {
15
18
 
16
- std::unique_ptr<stk::StkFrames> frames;
19
+ std::unique_ptr<Frames> frames;
20
+
21
+ uint nsamples = 0;
17
22
 
18
23
  };// Signals::Data
19
24
 
20
25
 
21
- stk::StkFrames*
26
+ Frames*
22
27
  Signals_get_frames (Signals* signals)
23
28
  {
24
29
  if (!signals)
@@ -27,19 +32,304 @@ namespace Beeps
27
32
  return signals->self->frames.get();
28
33
  }
29
34
 
30
- const stk::StkFrames*
35
+ const Frames*
31
36
  Signals_get_frames (const Signals* signals)
32
37
  {
33
38
  return Signals_get_frames(const_cast<Signals*>(signals));
34
39
  }
35
40
 
41
+ Signals
42
+ Signals_create (uint capacity, uint nchannels, double sample_rate)
43
+ {
44
+ if (capacity <= 0 || nchannels <= 0)
45
+ argument_error(__FILE__, __LINE__);
46
+
47
+ if (sample_rate <= 0) sample_rate = Beeps::sample_rate();
48
+
49
+ Signals s;
50
+ s.self->frames.reset(new Frames(capacity, nchannels));
51
+ s.self->frames->setDataRate(sample_rate);
52
+ return s;
53
+ }
54
+
55
+ Signals
56
+ Signals_create (
57
+ const float* const* channels,
58
+ uint nsamples, uint nchannels, double sample_rate)
59
+ {
60
+ if (!channels || nsamples <= 0 || nchannels <= 0)
61
+ argument_error(__FILE__, __LINE__);
62
+
63
+ if (sample_rate <= 0) sample_rate = Beeps::sample_rate();
64
+
65
+ Frames* frames = new Frames(nsamples, nchannels);
66
+ frames->setDataRate(sample_rate);
67
+
68
+ for (uint channel = 0; channel < nchannels; ++channel)
69
+ for (uint sample = 0; sample < nsamples; ++sample)
70
+ (*frames)(sample, channel) = channels[channel][sample];
71
+
72
+ Signals s;
73
+ s.self->frames.reset(frames);
74
+ s.self->nsamples = nsamples;
75
+ return s;
76
+ }
77
+
78
+ void
79
+ Signals_resize (Signals* signals, uint capacity)
80
+ {
81
+ if (!signals || !*signals || capacity <= 0)
82
+ argument_error(__FILE__, __LINE__);
83
+
84
+ signals->self->frames->resize(capacity, signals->nchannels());
85
+ Signals_clear(signals);
86
+ }
87
+
88
+ void
89
+ Signals_resize (Signals* signals, uint nsamples, Float value)
90
+ {
91
+ Signals_resize(signals, nsamples);
92
+
93
+ Frames* frames = Signals_get_frames(signals);
94
+ assert(frames);
95
+
96
+ Float* p = &(*frames)(0, 0);
97
+ size_t size = frames->size();
98
+ for (size_t i = 0; i < size; ++i)
99
+ *p++ = value;
100
+
101
+ Signals_set_nsamples(signals, nsamples);
102
+ }
103
+
104
+ void
105
+ Signals_clear (Signals* signals)
106
+ {
107
+ if (!signals)
108
+ argument_error(__FILE__, __LINE__);
109
+
110
+ signals->self->nsamples = 0;
111
+ }
112
+
113
+ static uint
114
+ copy_frames (Signals* to, const Signals& from, uint from_offset)
115
+ {
116
+ assert(to && *to && from);
117
+
118
+ if (from_offset >= from.nsamples())
119
+ return 0;
120
+
121
+ uint to_offset = to->nsamples();
122
+ uint to_nsamples = to->capacity() - to_offset;
123
+ uint from_nsamples = from.nsamples();
124
+ uint copy_nsamples =
125
+ std::min(from_offset + to_nsamples, from_nsamples)
126
+ - from_offset;
127
+
128
+ Frames* to_frames = Signals_get_frames(to);
129
+ const Frames* from_frames = Signals_get_frames(&from);
130
+ assert(to_frames && from_frames);
131
+
132
+ for (uint channel = 0; channel < to_frames->nchannels(); ++channel)
133
+ {
134
+ uint from_channel = channel < from_frames->nchannels() ? channel : 0;
135
+
136
+ for (uint i = 0; i < copy_nsamples; ++i)
137
+ {
138
+ (*to_frames)( to_offset + i, channel) =
139
+ (*from_frames)(from_offset + i, from_channel);
140
+ }
141
+ }
142
+
143
+ to->self->nsamples += copy_nsamples;
144
+ return copy_nsamples;
145
+ }
146
+
147
+ static uint
148
+ resample_frames (Signals* to, const Signals& from, uint from_offset)
149
+ {
150
+ assert(to && *to && from);
151
+
152
+ if (from_offset >= from.nsamples())
153
+ return 0;
36
154
 
37
- Signals::Signals (float seconds, uint channels)
155
+ uint to_offset = to->nsamples();
156
+ float to_sec = (to->capacity() - to_offset) / to->sample_rate();
157
+ float from_offset_sec = from_offset / from.sample_rate();
158
+ float from_sec = from.nsamples() / from.sample_rate();
159
+
160
+ float copy_seconds =
161
+ std::min(from_offset_sec + to_sec, from_sec) - from_offset_sec;
162
+
163
+ uint to_nsamples = 0, from_nsamples = 0;
164
+ if (from_offset_sec + to_sec <= from_sec)
165
+ {
166
+ to_nsamples = to->capacity() - to->nsamples();
167
+ from_nsamples = copy_seconds * from.sample_rate();
168
+ }
169
+ else
170
+ {
171
+ to_nsamples = copy_seconds * to->sample_rate();
172
+ from_nsamples = from.nsamples() - from_offset;
173
+ }
174
+
175
+ r8b::CDSPResampler24 resampler(
176
+ from.sample_rate(), to->sample_rate(), from_nsamples);
177
+ r8b::CFixedBuffer<double> from_buf(from_nsamples), to_buf(to_nsamples);
178
+
179
+ Frames* to_frames = Signals_get_frames(to);
180
+ const Frames* from_frames = Signals_get_frames(&from);
181
+ assert(to_frames && from_frames);
182
+
183
+ for (uint channel = 0; channel < to_frames->nchannels(); ++channel)
184
+ {
185
+ uint from_channel = channel < from_frames->nchannels() ? channel : 0;
186
+
187
+ for (uint i = 0; i < from_nsamples; ++i)
188
+ from_buf[i] = (*from_frames)(from_offset + i, from_channel);
189
+
190
+ resampler.clear();
191
+ resampler.oneshot(
192
+ (const double*) from_buf, from_nsamples,
193
+ (double*) to_buf, to_nsamples);
194
+
195
+ for (uint i = 0; i < to_nsamples; ++i)
196
+ (*to_frames)(to_offset + i, channel) = to_buf[i];
197
+ }
198
+
199
+ to->self->nsamples += to_nsamples;
200
+ return from_nsamples;
201
+ }
202
+
203
+ uint
204
+ Signals_copy (Signals* to, const Signals& from, uint from_offset)
38
205
  {
39
- if (seconds <= 0 || channels <= 0)
40
- return;
206
+ if (!to || !*to || !from)
207
+ argument_error(__FILE__, __LINE__);
208
+
209
+ Signals_clear(to);
41
210
 
42
- self->frames.reset(new stk::StkFrames(seconds * sampling_rate(), channels));
211
+ if (to->sample_rate() == from.sample_rate())
212
+ return copy_frames(to, from, from_offset);
213
+ else
214
+ return resample_frames(to, from, from_offset);
215
+ }
216
+
217
+ void
218
+ Signals_apply (Signals* signals, const Signals& multiplier)
219
+ {
220
+ if (!signals || multiplier.nchannels() != 1)
221
+ argument_error(__FILE__, __LINE__);
222
+
223
+ if (signals->capacity() != multiplier.capacity())
224
+ argument_error(__FILE__, __LINE__);
225
+
226
+ Frames* sigf = Signals_get_frames(signals);
227
+ Frames* mulf = Signals_get_frames(const_cast<Signals*>(&multiplier));
228
+
229
+ for (uint ch = 0; ch < sigf->nchannels(); ++ch)
230
+ {
231
+ Float* sigp = &(*sigf)(0, ch);
232
+ Float* mulp = &(*mulf)(0, 0);
233
+ uint nframes = sigf->nframes();
234
+ uint stride = sigf->nchannels();
235
+ for (uint i = 0; i < nframes; ++i, sigp += stride, ++mulp)
236
+ *sigp *= *mulp;
237
+ }
238
+ }
239
+
240
+ template <typename T>
241
+ void
242
+ write_samples (Signals* signals, const SignalSamples<T>& samples, long nsamples_)
243
+ {
244
+ uint nsamples = nsamples_ < 0 ? samples.nsamples() : (uint) nsamples_;
245
+
246
+ if (
247
+ !signals || !*signals ||
248
+ signals->nchannels() != samples.nchannels() ||
249
+ signals->capacity() < nsamples)
250
+ {
251
+ argument_error(__FILE__, __LINE__);
252
+ }
253
+
254
+ Frames* f = Signals_get_frames(signals);
255
+ assert(f);
256
+
257
+ for (uint channel = 0; channel < signals->nchannels(); ++channel)
258
+ {
259
+ const T* buf = samples.channel(channel);
260
+ for (uint sample = 0; sample < nsamples; ++sample)
261
+ (*f)(sample, channel) = buf[sample];
262
+ }
263
+
264
+ signals->self->nsamples = nsamples;
265
+ }
266
+
267
+ template <>
268
+ void
269
+ Signals_write_samples (
270
+ Signals* signals, const SignalSamples<float>& samples, long nsamples)
271
+ {
272
+ write_samples(signals, samples, nsamples);
273
+ }
274
+
275
+ template <>
276
+ void
277
+ Signals_write_samples (
278
+ Signals* signals, const SignalSamples<double>& samples, long nsamples)
279
+ {
280
+ write_samples(signals, samples, nsamples);
281
+ }
282
+
283
+ void
284
+ Signals_set_nsamples (Signals* signals, uint nsamples)
285
+ {
286
+ if (!signals)
287
+ argument_error(__FILE__, __LINE__);
288
+
289
+ signals->self->nsamples = nsamples;
290
+ }
291
+
292
+ float
293
+ Signals_get_seconds (const Signals& signals)
294
+ {
295
+ return (float) (signals.nsamples() / signals.sample_rate());
296
+ }
297
+
298
+ static void
299
+ make_audio_buffer (
300
+ AudioFile<float>::AudioBuffer* buffer, const Signals& signals)
301
+ {
302
+ assert(buffer && signals);
303
+
304
+ const Frames* frames = Signals_get_frames(&signals);
305
+ assert(frames);
306
+
307
+ buffer->clear();
308
+ for (uint ch = 0; ch < frames->nchannels(); ++ch)
309
+ {
310
+ buffer->emplace_back(std::vector<float>());
311
+ auto& channel = buffer->back();
312
+
313
+ uint nframes = frames->nframes();
314
+ channel.reserve(nframes);
315
+
316
+ for (uint i = 0; i < nframes; ++i)
317
+ channel.emplace_back((*frames)(i, ch));
318
+ }
319
+ }
320
+
321
+ void
322
+ Signals_save (const Signals& signals, const char* path)
323
+ {
324
+ AudioFile<float> file;
325
+ file.setSampleRate(signals.sample_rate());
326
+ make_audio_buffer(&file.samples, signals);
327
+ file.save(path);
328
+ }
329
+
330
+
331
+ Signals::Signals ()
332
+ {
43
333
  }
44
334
 
45
335
  Signals::~Signals ()
@@ -51,35 +341,51 @@ namespace Beeps
51
341
  {
52
342
  Signals t;
53
343
  if (self->frames)
54
- t.self->frames.reset(new stk::StkFrames(*self->frames));
344
+ t.self->frames.reset(new Frames(*self->frames));
345
+ t.self->nsamples = self->nsamples;
55
346
  return t;
56
347
  }
57
348
 
58
- float
59
- Signals::seconds () const
349
+ double
350
+ Signals::sample_rate () const
60
351
  {
61
- double sec = samples() / (double) sampling_rate();
62
- return (float) sec;
352
+ return self->frames ? self->frames->dataRate() : Beeps::sample_rate();
63
353
  }
64
354
 
65
355
  uint
66
- Signals::samples () const
356
+ Signals::nchannels () const
67
357
  {
68
- Data* p = self.get();
69
- return p ? p->frames->frames() : 0;
358
+ return self->frames ? self->frames->nchannels() : 0;
70
359
  }
71
360
 
72
361
  uint
73
- Signals::channels () const
362
+ Signals::nsamples () const
363
+ {
364
+ return self->nsamples;
365
+ }
366
+
367
+ uint
368
+ Signals::capacity () const
369
+ {
370
+ return self->frames ? self->frames->nframes() : 0;
371
+ }
372
+
373
+ bool
374
+ Signals::empty () const
375
+ {
376
+ return self->nsamples == 0;
377
+ }
378
+
379
+ const double*
380
+ Signals::samples () const
74
381
  {
75
- Data* p = self.get();
76
- return p ? p->frames->channels() : 0;
382
+ return self->frames ? self->frames->data() : NULL;
77
383
  }
78
384
 
79
385
  Signals::operator bool () const
80
386
  {
81
- const stk::StkFrames* f = Signals_get_frames(this);
82
- return f && f->frames() > 0 && f->channels() > 0;
387
+ const Frames* f = self->frames.get();
388
+ return f && f->dataRate() > 0 && f->nchannels() > 0 && f->nframes() > 0;
83
389
  }
84
390
 
85
391
  bool
data/src/signals.h CHANGED
@@ -4,17 +4,207 @@
4
4
  #define __BEEPS_SRC_SIGNALS_H__
5
5
 
6
6
 
7
+ #include <vector>
7
8
  #include <Stk.h>
9
+ #include <xot/pimpl.h>
8
10
  #include <beeps/signals.h>
11
+ #include <beeps/exception.h>
9
12
 
10
13
 
11
14
  namespace Beeps
12
15
  {
13
16
 
14
17
 
15
- stk::StkFrames* Signals_get_frames ( Signals* signals);
18
+ typedef stk::StkFloat Float;
16
19
 
17
- const stk::StkFrames* Signals_get_frames (const Signals* signals);
20
+
21
+ class Frames;
22
+
23
+ template <typename T> class SignalSamples;
24
+
25
+
26
+ Frames* Signals_get_frames ( Signals* signals);
27
+
28
+ const Frames* Signals_get_frames (const Signals* signals);
29
+
30
+ Signals Signals_create (
31
+ uint capacity, uint nchannels = 1, double sample_rate = 0);
32
+
33
+ Signals Signals_create (
34
+ const float* const* channels,
35
+ uint nsamples, uint nchannels, double sample_rate = 0);
36
+
37
+ void Signals_resize (Signals* signals, uint capacity);
38
+
39
+ void Signals_resize (Signals* signals, uint nsamples, Float value);
40
+
41
+ void Signals_clear (Signals* signals);
42
+
43
+ uint Signals_copy (Signals* to, const Signals& from, uint from_offset);
44
+
45
+ void Signals_apply (Signals* signals, const Signals& multiplier);
46
+
47
+ template <typename T>
48
+ void Signals_write_samples (
49
+ Signals* signals, const SignalSamples<T>& samples, long nsamples = -1);
50
+
51
+ void Signals_set_nsamples (Signals* signals, uint nsamples);
52
+
53
+ float Signals_get_seconds (const Signals& signals);
54
+
55
+ void Signals_save (const Signals& signals, const char* path);
56
+
57
+ Signals Signals_load (const char* path);
58
+
59
+
60
+ class Frames : public stk::StkFrames
61
+ {
62
+
63
+ public:
64
+
65
+ Frames (unsigned int nFrames = 0, unsigned int nChannels = 0)
66
+ : stk::StkFrames(nFrames, nChannels)
67
+ {
68
+ }
69
+
70
+ size_t slice (size_t start, size_t length)
71
+ {
72
+ assert(!saved_data_);
73
+
74
+ size_t end = start + length;
75
+ assert(start <= nFrames_ && end <= nFrames_);
76
+
77
+ saved_data_ = data_;
78
+ saved_nFrames_ = nFrames_;
79
+ saved_size_ = size_;
80
+ saved_bufferSize_ = bufferSize_;
81
+
82
+ data_ += start * nChannels_;
83
+ nFrames_ = length;
84
+ size_ = length * nChannels_;
85
+ bufferSize_ = size_;
86
+
87
+ return end;
88
+ }
89
+
90
+ void unslice ()
91
+ {
92
+ assert(saved_data_);
93
+
94
+ data_ = saved_data_;
95
+ nFrames_ = saved_nFrames_;
96
+ size_ = saved_size_;
97
+ bufferSize_ = saved_bufferSize_;
98
+ }
99
+
100
+ uint nchannels () const
101
+ {
102
+ return nChannels_;
103
+ }
104
+
105
+ uint nframes () const
106
+ {
107
+ return nFrames_;
108
+ }
109
+
110
+ const Float* data () const
111
+ {
112
+ return data_;
113
+ }
114
+
115
+ private:
116
+
117
+ Float* saved_data_ = NULL;
118
+
119
+ size_t saved_nFrames_ = 0, saved_size_ = 0, saved_bufferSize_ = 0;
120
+
121
+ };// Frames
122
+
123
+
124
+ template <typename T>
125
+ class SignalSamples
126
+ {
127
+
128
+ typedef SignalSamples<T> This;
129
+
130
+ public:
131
+
132
+ SignalSamples (uint nsamples, uint nchannels)
133
+ {
134
+ self->nsamples = nsamples;
135
+ self->samples.resize(nsamples * nchannels, 0);
136
+ self->update_channels(nchannels);
137
+ }
138
+
139
+ SignalSamples (const Signals& signals)
140
+ {
141
+ if (!signals)
142
+ argument_error(__FILE__, __LINE__);
143
+
144
+ const Frames* f = Signals_get_frames(&signals);
145
+ assert(f);
146
+
147
+ uint nsamples = signals.nsamples();
148
+ uint nchannels = signals.nchannels();
149
+
150
+ auto& samples = self->samples;
151
+ samples.reserve(nsamples * nchannels);
152
+
153
+ for (uint channel = 0; channel < nchannels; ++channel)
154
+ {
155
+ for (uint sample = 0; sample < nsamples; ++sample)
156
+ samples.push_back((*f)(sample, channel));
157
+ }
158
+
159
+ self->nsamples = nsamples;
160
+ self->update_channels(nchannels);
161
+ }
162
+
163
+ uint nchannels () const
164
+ {
165
+ return (uint) self->channels.size();
166
+ }
167
+
168
+ uint nsamples () const
169
+ {
170
+ return self->nsamples;
171
+ }
172
+
173
+ T* const* channels () {return &self->channels[0];}
174
+
175
+ const T* const* channels () const
176
+ {
177
+ return const_cast<This*>(this)->channels();
178
+ }
179
+
180
+ T* channel (uint index) {return self->channels[index];}
181
+
182
+ const T* channel (uint index) const
183
+ {
184
+ return const_cast<This*>(this)->channel(index);
185
+ }
186
+
187
+ struct Data
188
+ {
189
+
190
+ uint nsamples = 0;
191
+
192
+ std::vector<T> samples;
193
+
194
+ std::vector<T*> channels;
195
+
196
+ void update_channels (uint nchannels)
197
+ {
198
+ channels.clear();
199
+ for (uint i = 0; i < nchannels; ++i)
200
+ channels.push_back(&samples[nsamples * i]);
201
+ }
202
+
203
+ };// Data
204
+
205
+ Xot::PSharedImpl<Data> self;
206
+
207
+ };// SignalSamples
18
208
 
19
209
 
20
210
  }// Beeps