beeps 0.3.6 → 0.3.7

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/beeps/beeps.cpp +7 -0
  3. data/.doc/ext/beeps/high_pass.cpp +63 -0
  4. data/.doc/ext/beeps/low_pass.cpp +63 -0
  5. data/.doc/ext/beeps/native.cpp +8 -0
  6. data/.doc/ext/beeps/oscillator.cpp +87 -10
  7. data/.doc/ext/beeps/processor.cpp +14 -1
  8. data/.doc/ext/beeps/reverb.cpp +99 -0
  9. data/.doc/ext/beeps/signals.cpp +128 -0
  10. data/ChangeLog.md +24 -0
  11. data/Rakefile +1 -1
  12. data/VERSION +1 -1
  13. data/beeps.gemspec +2 -2
  14. data/ext/beeps/beeps.cpp +8 -0
  15. data/ext/beeps/high_pass.cpp +66 -0
  16. data/ext/beeps/low_pass.cpp +66 -0
  17. data/ext/beeps/native.cpp +8 -0
  18. data/ext/beeps/oscillator.cpp +95 -12
  19. data/ext/beeps/processor.cpp +15 -1
  20. data/ext/beeps/reverb.cpp +106 -0
  21. data/ext/beeps/signals.cpp +136 -0
  22. data/include/beeps/beeps.h +2 -2
  23. data/include/beeps/defs.h +3 -0
  24. data/include/beeps/filter.h +118 -17
  25. data/include/beeps/generator.h +50 -17
  26. data/include/beeps/processor.h +23 -6
  27. data/include/beeps/ruby/filter.h +33 -0
  28. data/include/beeps/ruby/signals.h +40 -0
  29. data/include/beeps/signals.h +1 -1
  30. data/lib/beeps/processor.rb +46 -1
  31. data/lib/beeps/signals.rb +19 -0
  32. data/lib/beeps.rb +1 -0
  33. data/src/analyser.cpp +34 -37
  34. data/src/beeps.cpp +7 -6
  35. data/src/envelope.cpp +60 -46
  36. data/src/file_in.cpp +6 -6
  37. data/src/gain.cpp +5 -5
  38. data/src/high_pass.cpp +57 -0
  39. data/src/low_pass.cpp +57 -0
  40. data/src/mic_in.cpp +16 -14
  41. data/src/mixer.cpp +38 -20
  42. data/src/oscillator.cpp +260 -168
  43. data/src/pitch_shift.cpp +6 -6
  44. data/src/processor.cpp +118 -11
  45. data/src/processor.h +8 -0
  46. data/src/reverb.cpp +124 -0
  47. data/src/sequencer.cpp +18 -14
  48. data/src/signals.cpp +264 -106
  49. data/src/signals.h +28 -89
  50. data/src/sound.cpp +28 -20
  51. data/src/time_stretch.cpp +6 -6
  52. data/src/win32/signals.cpp +8 -7
  53. data/src/x_pass.h +51 -0
  54. data/test/helper.rb +14 -0
  55. data/test/test_analyser.rb +26 -0
  56. data/test/test_envelope.rb +55 -0
  57. data/test/test_file_in.rb +22 -1
  58. data/test/test_gain.rb +28 -0
  59. data/test/test_high_pass.rb +41 -0
  60. data/test/test_low_pass.rb +41 -0
  61. data/test/test_mixer.rb +63 -0
  62. data/test/test_oscillator.rb +58 -0
  63. data/test/test_pitch_shift.rb +32 -0
  64. data/test/test_processor.rb +7 -0
  65. data/test/test_signals.rb +60 -0
  66. data/test/test_time_stretch.rb +36 -0
  67. metadata +48 -10
data/src/analyser.cpp CHANGED
@@ -186,48 +186,46 @@ namespace Beeps
186
186
  return self->spectrum;
187
187
  }
188
188
 
189
+ Analyser::operator bool () const
190
+ {
191
+ if (!Super::operator bool()) return false;
192
+ return self->is_valid();
193
+ }
194
+
189
195
  static void
190
196
  shift (Signals* signals, uint nsamples)
191
197
  {
198
+ if (nsamples == 0)
199
+ return;
200
+
192
201
  if (nsamples > signals->nsamples())
193
202
  return Signals_clear(signals);
194
203
 
195
- Frames* frames = Signals_get_frames(signals);
196
- assert(frames);
197
-
198
- Float* from = &(*frames)(nsamples, 0);
199
- Float* to = &(*frames)(0, 0);
200
- uint size = (signals->nsamples() - nsamples) * signals->nchannels();
204
+ Sample* from = Signals_at(signals, nsamples);
205
+ Sample* to = Signals_at(signals, 0);
206
+ uint nsamples_remain = signals->nsamples() - nsamples;
207
+ uint size = nsamples_remain * signals->nchannels();
201
208
  for (uint i = 0; i < size; ++i)
202
209
  *to++ = *from++;
203
210
 
204
- Signals_set_nsamples(signals, signals->nsamples() - nsamples);
211
+ Signals_set_nsamples(signals, nsamples_remain);
205
212
  }
206
213
 
207
214
  static void
208
215
  append (Signals* to, const Signals& from)
209
216
  {
210
- assert(to);
211
-
212
- Frames* tof = Signals_get_frames(to);
213
- const Frames* fromf = Signals_get_frames(&from);
214
- assert(fromf && tof);
217
+ assert(to->nchannels() == from.nchannels());
218
+ assert(to->nsamples() + from.nsamples() <= to->capacity());
215
219
 
216
- uint to_cap = to->capacity();
217
- uint to_nsamples = to->nsamples();
218
- uint from_nsamples = from.nsamples();
219
- uint from_start = from_nsamples > to_cap ? from_nsamples - to_cap : 0;
220
- uint nsamples = from_nsamples - from_start;
221
- assert(to_nsamples + nsamples <= to_cap);
222
-
223
- for (uint ch = 0; ch < tof->nchannels(); ++ch)
224
- {
225
- uint from_ch = ch < fromf->nchannels() ? ch : 0;
226
- for (uint i = 0; i < nsamples; ++i)
227
- (*tof)(to_nsamples + i, ch) = (*fromf)(from_start + i, from_ch);
228
- }
220
+ uint nchannels = to->nchannels();
221
+ uint nsamples = std::min(from.nsamples(), to->capacity() - to->nsamples());
222
+ uint size = nsamples * nchannels;
223
+ Sample* to_p = Signals_at(to, to->nsamples());
224
+ const Sample* from_p = Signals_at(from, 0);
225
+ for (uint i = 0; i < size; ++i)
226
+ *to_p++ = *from_p++;
229
227
 
230
- Signals_set_nsamples(to, to_nsamples + nsamples);
228
+ Signals_set_nsamples(to, to->nsamples() + nsamples);
231
229
  }
232
230
 
233
231
  void
@@ -235,20 +233,19 @@ namespace Beeps
235
233
  {
236
234
  Super::filter(context, signals, offset);
237
235
 
238
- Signals& sig = self->signals;
239
- uint nsamples = sig.nsamples() + signals->nsamples();
240
- if (nsamples > sig.capacity())
241
- shift(&sig, nsamples - sig.capacity());
236
+ auto& in = *signals;
237
+ auto& my = self->signals;
242
238
 
243
- append(&sig, *signals);
239
+ if (my.nchannels() != in.nchannels() || my.sample_rate() != in.sample_rate())
240
+ my = Signals_create(my.capacity(), in.nchannels(), in.sample_rate());
244
241
 
245
- self->spectrum.clear();
246
- }
242
+ uint total_nsamples = my.nsamples() + in.nsamples();
243
+ if (total_nsamples > my.capacity())
244
+ shift(&my, total_nsamples - my.capacity());
247
245
 
248
- Analyser::operator bool () const
249
- {
250
- if (!Super::operator bool()) return false;
251
- return self->is_valid();
246
+ append(&my, in);
247
+
248
+ self->spectrum.clear();
252
249
  }
253
250
 
254
251
 
data/src/beeps.cpp CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include "Stk.h"
6
6
  #include "beeps/exception.h"
7
+ #include "beeps/debug.h"
7
8
  #include "openal.h"
8
9
  #include "sound.h"
9
10
  #include "mic_in.h"
@@ -32,6 +33,12 @@ namespace Beeps
32
33
  Beeps_fin();
33
34
  }
34
35
 
36
+ double
37
+ sample_rate ()
38
+ {
39
+ return stk::Stk::sampleRate();
40
+ }
41
+
35
42
  void
36
43
  process_streams ()
37
44
  {
@@ -39,11 +46,5 @@ namespace Beeps
39
46
  SoundPlayer_process_streams();
40
47
  }
41
48
 
42
- double
43
- sample_rate ()
44
- {
45
- return stk::Stk::sampleRate();
46
- }
47
-
48
49
 
49
50
  }// Beeps
data/src/envelope.cpp CHANGED
@@ -14,10 +14,25 @@ namespace Beeps
14
14
  static const float TIME_ZERO = 0.0000001;
15
15
 
16
16
 
17
+ class ADSR : public stk::ADSR
18
+ {
19
+
20
+ public:
21
+
22
+ void skipAttackPhase()
23
+ {
24
+ value_ = 1;
25
+ target_ = 1;
26
+ state_ = DECAY;
27
+ }
28
+
29
+ };// ADSR
30
+
31
+
17
32
  struct Envelope::Data
18
33
  {
19
34
 
20
- stk::ADSR adsr;
35
+ ADSR adsr;
21
36
 
22
37
  Signals adsr_signals;
23
38
 
@@ -151,15 +166,28 @@ namespace Beeps
151
166
  return self->release_time;
152
167
  }
153
168
 
154
- static size_t
155
- slice (Frames* frames, size_t start, float length_sec = -1)
169
+ Envelope::operator bool () const
170
+ {
171
+ if (!Super::operator bool()) return false;
172
+ return
173
+ self->attack_time >= 0 &&
174
+ self->decay_time >= 0 &&
175
+ self->sustain_level >= 0 &&
176
+ self->release_time >= 0 &&
177
+ self->time >= 0;
178
+ }
179
+
180
+ static uint
181
+ tick (Envelope* envelope, Signals* signals, uint start, float length_sec = -1)
156
182
  {
157
- size_t max = frames->nframes() - start;
158
- size_t len = length_sec >= 0 ? length_sec * frames->sample_rate() : max;
183
+ uint max = signals->capacity() - start;
184
+ uint len = length_sec >= 0 ? length_sec * signals->sample_rate() : max;
159
185
  if (len > max) len = max;
160
- assert(0 < len && (start + len) <= frames->nframes());
186
+ assert(0 < len && (start + len) <= signals->nsamples());
161
187
 
162
- return frames->slice(start, len);
188
+ return Signals_tick(
189
+ signals, start, start + len,
190
+ [&](stk::StkFrames* frames) {envelope->self->adsr.tick(*frames);});
163
191
  }
164
192
 
165
193
  static void
@@ -169,57 +197,52 @@ namespace Beeps
169
197
 
170
198
  Envelope::Data* self = envelope->self.get();
171
199
 
172
- Frames* frames = Signals_get_frames(signals);
173
- assert(frames);
174
-
175
200
  if (self->time == 0 && self->attack_time == 0)
176
- self->adsr.setValue(self->sustain_level);// skip attack phase
201
+ self->adsr.skipAttackPhase();
177
202
 
178
- float start = self->time;
179
- float end = start + Signals_get_seconds(*signals);
180
- self->time = end;
203
+ float on = self->note_on_time;
204
+ float off = self->note_off_time;
205
+ float start = self->time;
206
+ float end = start + signals->capacity() / signals->sample_rate();
207
+ float release_end = off >= 0 ? off + self->release_time : -1;
208
+ bool has_on = 0 <= on && start <= on && on < end;
209
+ bool has_off = 0 <= off && start <= off && off < end;
181
210
 
182
- float on = self->note_on_time;
183
- float off = self->note_off_time;
184
- assert(on <= off);
211
+ if (release_end >= 0 && release_end < end)
212
+ end = release_end;
185
213
 
186
- bool has_on = 0 <= on && start <= on && on < end;
187
- bool has_off = 0 <= off && start <= off && off < end;
214
+ self->time = end;
188
215
 
189
216
  if (!has_on && !has_off)
190
217
  {
191
- self->adsr.tick(*frames);
218
+ float len = end == release_end ? end - start : -1;
219
+ tick(envelope, signals, 0, len);
192
220
  return;
193
221
  }
194
222
 
195
- size_t last = 0;
223
+ uint pos = 0;
196
224
  if (has_on)
197
225
  {
198
226
  if (start < on)
199
- {
200
- last = slice(frames, 0, on - start);
201
- self->adsr.tick(*frames);
202
- frames->unslice();
203
- }
227
+ pos = tick(envelope, signals, pos, on - start);
204
228
  self->adsr.keyOn();
205
229
  }
206
230
  if (has_on || has_off)
207
231
  {
208
232
  float len = has_off ? off - (has_on ? on : start) : -1;
209
- last = slice(frames, last, len);
210
- self->adsr.tick(*frames);
211
- frames->unslice();
233
+ pos = tick(envelope, signals, pos, len);
212
234
  }
213
235
  if (has_off)
214
236
  {
215
237
  self->adsr.keyOff();
216
238
  if (off < end)
217
239
  {
218
- slice(frames, last, -1);
219
- self->adsr.tick(*frames);
220
- frames->unslice();
240
+ float len = end == release_end ? end - off : -1;
241
+ pos = tick(envelope, signals, pos, len);
221
242
  }
222
243
  }
244
+
245
+ Signals_set_nsamples(signals, pos);
223
246
  }
224
247
 
225
248
  void
@@ -232,23 +255,14 @@ namespace Beeps
232
255
  self->adsr_signals =
233
256
  Signals_create(signals->nsamples(), 1, signals->sample_rate());
234
257
  }
235
-
236
- if (self->adsr_signals.nsamples() != signals->nsamples())
237
- Signals_resize(&self->adsr_signals, signals->nsamples(), 0);
258
+ else
259
+ Signals_clear(&self->adsr_signals, signals->nsamples());
238
260
 
239
261
  process_envelope_signals(this, &self->adsr_signals);
240
- Signals_multiply(signals, self->adsr_signals);
241
- }
262
+ if (self->adsr_signals.nsamples() < signals->nsamples())
263
+ Signals_set_nsamples(signals, self->adsr_signals.nsamples());
242
264
 
243
- Envelope::operator bool () const
244
- {
245
- if (!Super::operator bool()) return false;
246
- return
247
- self->attack_time >= 0 &&
248
- self->decay_time >= 0 &&
249
- self->sustain_level >= 0 &&
250
- self->release_time >= 0 &&
251
- self->time >= 0;
265
+ Signals_multiply(signals, self->adsr_signals);
252
266
  }
253
267
 
254
268
 
data/src/file_in.cpp CHANGED
@@ -76,6 +76,12 @@ namespace Beeps
76
76
  return Signals_get_seconds(self->signals);
77
77
  }
78
78
 
79
+ FileIn::operator bool () const
80
+ {
81
+ if (!Super::operator bool()) return false;
82
+ return self->signals;
83
+ }
84
+
79
85
  void
80
86
  FileIn::generate (Context* context, Signals* signals, uint* offset)
81
87
  {
@@ -84,11 +90,5 @@ namespace Beeps
84
90
  *offset += Signals_copy(signals, self->signals, *offset);
85
91
  }
86
92
 
87
- FileIn::operator bool () const
88
- {
89
- if (!Super::operator bool()) return false;
90
- return self->signals;
91
- }
92
-
93
93
 
94
94
  }// Beeps
data/src/gain.cpp CHANGED
@@ -44,11 +44,11 @@ namespace Beeps
44
44
  {
45
45
  Super::filter(context, signals, offset);
46
46
 
47
- Frames* frames = Signals_get_frames(signals);
48
- if (!frames)
49
- argument_error(__FILE__, __LINE__);
50
-
51
- *frames *= self->gain;
47
+ float gain = self->gain;
48
+ uint size = signals->nsamples() * signals->nchannels();
49
+ Sample* p = Signals_at(signals, 0);
50
+ for (uint i = 0; i < size; ++i)
51
+ *p++ *= gain;
52
52
  }
53
53
 
54
54
 
data/src/high_pass.cpp ADDED
@@ -0,0 +1,57 @@
1
+ #include "x_pass.h"
2
+
3
+
4
+ namespace Beeps
5
+ {
6
+
7
+
8
+ struct HighPass::Data : public xPassFilterData
9
+ {
10
+
11
+ Data ()
12
+ : xPassFilterData(100)
13
+ {
14
+ }
15
+
16
+ };// HighPass::Data
17
+
18
+
19
+ HighPass::HighPass (Processor* input)
20
+ : Super(input)
21
+ {
22
+ }
23
+
24
+ HighPass::~HighPass ()
25
+ {
26
+ }
27
+
28
+ void
29
+ HighPass::set_cutoff_frequency (float frequency)
30
+ {
31
+ if (frequency <= 0)
32
+ argument_error(__FILE__, __LINE__);
33
+
34
+ if (frequency == self->cutoff_freq)
35
+ return;
36
+
37
+ self->cutoff_freq = frequency;
38
+ set_updated();
39
+ }
40
+
41
+ float
42
+ HighPass::cutoff_frequency () const
43
+ {
44
+ return self->cutoff_freq;
45
+ }
46
+
47
+ void
48
+ HighPass::filter (Context* context, Signals* signals, uint* offset)
49
+ {
50
+ Super::filter(context, signals, offset);
51
+
52
+ self->biquad.setHighPass(self->cutoff_freq);
53
+ self->tick(signals);
54
+ }
55
+
56
+
57
+ }// Beeps
data/src/low_pass.cpp ADDED
@@ -0,0 +1,57 @@
1
+ #include "x_pass.h"
2
+
3
+
4
+ namespace Beeps
5
+ {
6
+
7
+
8
+ struct LowPass::Data : public xPassFilterData
9
+ {
10
+
11
+ Data ()
12
+ : xPassFilterData(1000)
13
+ {
14
+ }
15
+
16
+ };// LowPass::Data
17
+
18
+
19
+ LowPass::LowPass (Processor* input)
20
+ : Super(input)
21
+ {
22
+ }
23
+
24
+ LowPass::~LowPass ()
25
+ {
26
+ }
27
+
28
+ void
29
+ LowPass::set_cutoff_frequency (float frequency)
30
+ {
31
+ if (frequency <= 0)
32
+ argument_error(__FILE__, __LINE__);
33
+
34
+ if (frequency == self->cutoff_freq)
35
+ return;
36
+
37
+ self->cutoff_freq = frequency;
38
+ set_updated();
39
+ }
40
+
41
+ float
42
+ LowPass::cutoff_frequency () const
43
+ {
44
+ return self->cutoff_freq;
45
+ }
46
+
47
+ void
48
+ LowPass::filter (Context* context, Signals* signals, uint* offset)
49
+ {
50
+ Super::filter(context, signals, offset);
51
+
52
+ self->biquad.setLowPass(self->cutoff_freq);
53
+ self->tick(signals);
54
+ }
55
+
56
+
57
+ }// Beeps
data/src/mic_in.cpp CHANGED
@@ -86,22 +86,19 @@ namespace Beeps
86
86
 
87
87
  if (!is_valid()) return;
88
88
 
89
- Frames* frames = Signals_get_frames(signals);
90
- assert(frames);
91
-
92
89
  auto& samples = self->samples;
93
90
  uint nchannels = self->nchannels;
94
91
  uint nsamples = (uint) (samples.size() / nchannels);
95
92
  uint offset = *gen_offset < self->offset ? 0 : *gen_offset - self->offset;
96
93
  if (offset >= nsamples) return;
97
94
 
98
- nsamples = std::min(frames->nframes(), nsamples - offset);
99
- for (uint ch = 0; ch < frames->nchannels(); ++ch)
95
+ nsamples = std::min(signals->capacity(), nsamples - offset);
96
+ for (uint ch = 0; ch < signals->nchannels(); ++ch)
100
97
  {
101
98
  uint samples_ch = ch < nchannels ? ch : 0;
102
99
  float div = 1.0f / SHRT_MAX;
103
100
  for (uint i = 0; i < nsamples; ++i)
104
- (*frames)(i, ch) = samples[(offset + i) * nchannels + samples_ch] * div;
101
+ *Signals_at(signals, i, ch) = samples[(offset + i) * nchannels + samples_ch] * div;
105
102
  }
106
103
  Signals_set_nsamples(signals, nsamples);
107
104
 
@@ -207,10 +204,15 @@ namespace Beeps
207
204
 
208
205
  MicIn::MicIn (uint nchannels, double sample_rate)
209
206
  {
207
+ if (sample_rate == 0)
208
+ sample_rate = Beeps::sample_rate();
209
+
210
+ if (nchannels <= 0)
211
+ argument_error(__FILE__, __LINE__);
210
212
  if (nchannels > 2)
211
213
  argument_error(__FILE__, __LINE__);
212
-
213
- if (sample_rate <= 0) sample_rate = Beeps::sample_rate();
214
+ if (sample_rate <= 0)
215
+ argument_error(__FILE__, __LINE__);
214
216
 
215
217
  self->mic.self->sample_rate = sample_rate;
216
218
  self->mic.self->nchannels = nchannels;
@@ -254,6 +256,12 @@ namespace Beeps
254
256
  return self->mic.self->nchannels;
255
257
  }
256
258
 
259
+ MicIn::operator bool () const
260
+ {
261
+ if (!Super::operator bool()) return false;
262
+ return self->mic.is_valid();
263
+ }
264
+
257
265
  void
258
266
  MicIn::generate (Context* context, Signals* signals, uint* offset)
259
267
  {
@@ -262,11 +270,5 @@ namespace Beeps
262
270
  self->mic.get_signals(signals, offset);
263
271
  }
264
272
 
265
- MicIn::operator bool () const
266
- {
267
- if (!Super::operator bool()) return false;
268
- return self->mic.is_valid();
269
- }
270
-
271
273
 
272
274
  }// Beeps
data/src/mixer.cpp CHANGED
@@ -16,6 +16,8 @@ namespace Beeps
16
16
 
17
17
  std::vector<Processor::Ref> inputs;
18
18
 
19
+ Signals input_signals;
20
+
19
21
  };// Mixer::Data
20
22
 
21
23
 
@@ -74,38 +76,54 @@ namespace Beeps
74
76
  return self->inputs.end();
75
77
  }
76
78
 
77
- void
78
- Mixer::filter (Context* context, Signals* signals, uint* offset)
79
+ Mixer::operator bool () const
79
80
  {
80
- Super::filter(context, signals, offset);
81
+ const auto* input = this->input();
82
+ if (input && !*input)
83
+ return false;
81
84
 
82
- Signals_resize(signals, signals->capacity(), 0);
85
+ if (!input && self->inputs.empty())
86
+ return false;
83
87
 
84
- Signals sig = Signals_create(signals->capacity(), signals->nchannels());
85
- uint min_size = signals->capacity();
86
- for (auto& input : self->inputs)
87
- {
88
- Signals_clear(&sig);
88
+ for (auto& i : self->inputs)
89
+ if (!*i) return false;
90
+
91
+ return true;
92
+ }
89
93
 
90
- uint sig_offset = *offset;
91
- Processor_get_context(context)->process(input, &sig, &sig_offset);
94
+ static void
95
+ mix (
96
+ Mixer* mixer, Processor* input,
97
+ Processor::Context* context, Signals* signals, uint offset)
98
+ {
99
+ Mixer::Data* self = mixer->self.get();
100
+
101
+ auto& insig = self->input_signals;
102
+ if (!insig)
103
+ insig = Signals_create(signals->capacity(), signals->nchannels());
104
+ else
105
+ Signals_clear(&insig, signals->capacity());
92
106
 
93
- uint size = sig_offset - *offset;
94
- if (size < min_size) min_size = size;
107
+ Processor_get_context(context)->process(input, &insig, &offset);
95
108
 
96
- Signals_add(signals, sig);
97
- }
109
+ if (insig.nsamples() > signals->nsamples())
110
+ Signals_set_nsamples(signals, insig.nsamples());
98
111
 
99
- *offset += min_size;
112
+ Signals_add(signals, insig);
100
113
  }
101
114
 
102
- Mixer::operator bool () const
115
+ void
116
+ Mixer::filter (Context* context, Signals* signals, uint* offset)
103
117
  {
104
- if (self->inputs.empty()) return false;
118
+ Signals_fill(signals, signals->capacity(), 0);
119
+ Signals_clear(signals);
120
+
121
+ Super::filter(context, signals, offset);
105
122
 
106
123
  for (auto& input : self->inputs)
107
- if (!*input) return false;
108
- return true;
124
+ mix(this, input.get(), context, signals, *offset);
125
+
126
+ *offset += signals->nsamples();
109
127
  }
110
128
 
111
129