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.
- checksums.yaml +4 -4
- data/.doc/ext/beeps/beeps.cpp +7 -0
- data/.doc/ext/beeps/high_pass.cpp +63 -0
- data/.doc/ext/beeps/low_pass.cpp +63 -0
- data/.doc/ext/beeps/native.cpp +8 -0
- data/.doc/ext/beeps/oscillator.cpp +87 -10
- data/.doc/ext/beeps/processor.cpp +14 -1
- data/.doc/ext/beeps/reverb.cpp +99 -0
- data/.doc/ext/beeps/signals.cpp +128 -0
- data/ChangeLog.md +24 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/beeps.gemspec +2 -2
- data/ext/beeps/beeps.cpp +8 -0
- data/ext/beeps/high_pass.cpp +66 -0
- data/ext/beeps/low_pass.cpp +66 -0
- data/ext/beeps/native.cpp +8 -0
- data/ext/beeps/oscillator.cpp +95 -12
- data/ext/beeps/processor.cpp +15 -1
- data/ext/beeps/reverb.cpp +106 -0
- data/ext/beeps/signals.cpp +136 -0
- data/include/beeps/beeps.h +2 -2
- data/include/beeps/defs.h +3 -0
- data/include/beeps/filter.h +118 -17
- data/include/beeps/generator.h +50 -17
- data/include/beeps/processor.h +23 -6
- data/include/beeps/ruby/filter.h +33 -0
- data/include/beeps/ruby/signals.h +40 -0
- data/include/beeps/signals.h +1 -1
- data/lib/beeps/processor.rb +46 -1
- data/lib/beeps/signals.rb +19 -0
- data/lib/beeps.rb +1 -0
- data/src/analyser.cpp +34 -37
- data/src/beeps.cpp +7 -6
- data/src/envelope.cpp +60 -46
- data/src/file_in.cpp +6 -6
- data/src/gain.cpp +5 -5
- data/src/high_pass.cpp +57 -0
- data/src/low_pass.cpp +57 -0
- data/src/mic_in.cpp +16 -14
- data/src/mixer.cpp +38 -20
- data/src/oscillator.cpp +260 -168
- data/src/pitch_shift.cpp +6 -6
- data/src/processor.cpp +118 -11
- data/src/processor.h +8 -0
- data/src/reverb.cpp +124 -0
- data/src/sequencer.cpp +18 -14
- data/src/signals.cpp +264 -106
- data/src/signals.h +28 -89
- data/src/sound.cpp +28 -20
- data/src/time_stretch.cpp +6 -6
- data/src/win32/signals.cpp +8 -7
- data/src/x_pass.h +51 -0
- data/test/helper.rb +14 -0
- data/test/test_analyser.rb +26 -0
- data/test/test_envelope.rb +55 -0
- data/test/test_file_in.rb +22 -1
- data/test/test_gain.rb +28 -0
- data/test/test_high_pass.rb +41 -0
- data/test/test_low_pass.rb +41 -0
- data/test/test_mixer.rb +63 -0
- data/test/test_oscillator.rb +58 -0
- data/test/test_pitch_shift.rb +32 -0
- data/test/test_processor.rb +7 -0
- data/test/test_signals.rb +60 -0
- data/test/test_time_stretch.rb +36 -0
- 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
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
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,
|
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
|
217
|
-
uint
|
218
|
-
uint
|
219
|
-
|
220
|
-
|
221
|
-
|
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,
|
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
|
-
|
239
|
-
|
240
|
-
if (nsamples > sig.capacity())
|
241
|
-
shift(&sig, nsamples - sig.capacity());
|
236
|
+
auto& in = *signals;
|
237
|
+
auto& my = self->signals;
|
242
238
|
|
243
|
-
|
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
|
-
|
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
|
-
|
249
|
-
|
250
|
-
|
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
|
-
|
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
|
-
|
155
|
-
|
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
|
-
|
158
|
-
|
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) <=
|
186
|
+
assert(0 < len && (start + len) <= signals->nsamples());
|
161
187
|
|
162
|
-
return
|
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.
|
201
|
+
self->adsr.skipAttackPhase();
|
177
202
|
|
178
|
-
float
|
179
|
-
float
|
180
|
-
self->time
|
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
|
-
|
183
|
-
|
184
|
-
assert(on <= off);
|
211
|
+
if (release_end >= 0 && release_end < end)
|
212
|
+
end = release_end;
|
185
213
|
|
186
|
-
|
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
|
-
|
218
|
+
float len = end == release_end ? end - start : -1;
|
219
|
+
tick(envelope, signals, 0, len);
|
192
220
|
return;
|
193
221
|
}
|
194
222
|
|
195
|
-
|
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
|
-
|
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
|
-
|
219
|
-
|
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
|
-
|
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
|
-
|
241
|
-
|
262
|
+
if (self->adsr_signals.nsamples() < signals->nsamples())
|
263
|
+
Signals_set_nsamples(signals, self->adsr_signals.nsamples());
|
242
264
|
|
243
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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(
|
99
|
-
for (uint ch = 0; 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
|
-
|
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
|
-
|
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
|
-
|
78
|
-
Mixer::filter (Context* context, Signals* signals, uint* offset)
|
79
|
+
Mixer::operator bool () const
|
79
80
|
{
|
80
|
-
|
81
|
+
const auto* input = this->input();
|
82
|
+
if (input && !*input)
|
83
|
+
return false;
|
81
84
|
|
82
|
-
|
85
|
+
if (!input && self->inputs.empty())
|
86
|
+
return false;
|
83
87
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
for (auto& i : self->inputs)
|
89
|
+
if (!*i) return false;
|
90
|
+
|
91
|
+
return true;
|
92
|
+
}
|
89
93
|
|
90
|
-
|
91
|
-
|
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
|
-
|
94
|
-
if (size < min_size) min_size = size;
|
107
|
+
Processor_get_context(context)->process(input, &insig, &offset);
|
95
108
|
|
96
|
-
|
97
|
-
|
109
|
+
if (insig.nsamples() > signals->nsamples())
|
110
|
+
Signals_set_nsamples(signals, insig.nsamples());
|
98
111
|
|
99
|
-
|
112
|
+
Signals_add(signals, insig);
|
100
113
|
}
|
101
114
|
|
102
|
-
|
115
|
+
void
|
116
|
+
Mixer::filter (Context* context, Signals* signals, uint* offset)
|
103
117
|
{
|
104
|
-
|
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
|
-
|
108
|
-
|
124
|
+
mix(this, input.get(), context, signals, *offset);
|
125
|
+
|
126
|
+
*offset += signals->nsamples();
|
109
127
|
}
|
110
128
|
|
111
129
|
|