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/oscillator.cpp
CHANGED
@@ -3,12 +3,11 @@
|
|
3
3
|
|
4
4
|
#include <assert.h>
|
5
5
|
#include <cmath>
|
6
|
+
#include <algorithm>
|
6
7
|
#include <vector>
|
7
|
-
#include "SineWave.h"
|
8
|
-
#include "Blit.h"
|
9
|
-
#include "BlitSquare.h"
|
10
|
-
#include "BlitSaw.h"
|
11
8
|
#include "beeps/exception.h"
|
9
|
+
#include "beeps/debug.h"
|
10
|
+
#include "processor.h"
|
12
11
|
#include "signals.h"
|
13
12
|
|
14
13
|
|
@@ -16,40 +15,9 @@ namespace Beeps
|
|
16
15
|
{
|
17
16
|
|
18
17
|
|
19
|
-
|
20
|
-
{
|
21
|
-
|
22
|
-
public:
|
23
|
-
|
24
|
-
void setPhase (stk::StkFloat phase)
|
25
|
-
{
|
26
|
-
time_ = std::fmod(phase, 1.f) * TABLE_SIZE;
|
27
|
-
}
|
18
|
+
static const uint NSEGMENTS_PER_WAVEFORM_CYCLE = 32;
|
28
19
|
|
29
|
-
|
30
|
-
{
|
31
|
-
return time_ / TABLE_SIZE;
|
32
|
-
}
|
33
|
-
|
34
|
-
};// SineWave
|
35
|
-
|
36
|
-
|
37
|
-
class BlitSaw : public stk::BlitSaw
|
38
|
-
{
|
39
|
-
|
40
|
-
public:
|
41
|
-
|
42
|
-
void setPhase (stk::StkFloat phase)
|
43
|
-
{
|
44
|
-
phase_ = M_PI * phase;
|
45
|
-
}
|
46
|
-
|
47
|
-
stk::StkFloat getPhase () const
|
48
|
-
{
|
49
|
-
return phase_ / M_PI;
|
50
|
-
}
|
51
|
-
|
52
|
-
};// BlitSaw
|
20
|
+
static const uint MIN_BUFFER_SIZE = 64;
|
53
21
|
|
54
22
|
|
55
23
|
class Osc
|
@@ -61,10 +29,12 @@ namespace Beeps
|
|
61
29
|
|
62
30
|
virtual void reset () = 0;
|
63
31
|
|
64
|
-
virtual void tick (
|
32
|
+
virtual void tick (stk::StkFrames* frames) = 0;
|
65
33
|
|
66
34
|
virtual void set_frequency (float freq) = 0;
|
67
35
|
|
36
|
+
virtual float frequency () const = 0;
|
37
|
+
|
68
38
|
virtual void set_phase (float phase) = 0;
|
69
39
|
|
70
40
|
virtual float phase () const = 0;
|
@@ -72,74 +42,6 @@ namespace Beeps
|
|
72
42
|
};// Osc
|
73
43
|
|
74
44
|
|
75
|
-
template <typename OSC, uint DROP_MSEC>
|
76
|
-
class StkOsc : public Osc
|
77
|
-
{
|
78
|
-
|
79
|
-
public:
|
80
|
-
|
81
|
-
void reset () override
|
82
|
-
{
|
83
|
-
osc.reset();
|
84
|
-
drop_msec = DROP_MSEC;
|
85
|
-
}
|
86
|
-
|
87
|
-
void tick (Frames* frames) override
|
88
|
-
{
|
89
|
-
if (drop_msec > 0)
|
90
|
-
{
|
91
|
-
Frames f((uint) (frames->dataRate() * (drop_msec / 1000.0)));
|
92
|
-
osc.tick(f);
|
93
|
-
drop_msec = 0;
|
94
|
-
}
|
95
|
-
|
96
|
-
osc.tick(*frames);
|
97
|
-
}
|
98
|
-
|
99
|
-
void set_frequency (float freq) override
|
100
|
-
{
|
101
|
-
osc.setFrequency(freq);
|
102
|
-
}
|
103
|
-
|
104
|
-
void set_phase (float phase) override
|
105
|
-
{
|
106
|
-
osc.setPhase(phase);
|
107
|
-
}
|
108
|
-
|
109
|
-
float phase () const override
|
110
|
-
{
|
111
|
-
return osc.getPhase();
|
112
|
-
}
|
113
|
-
|
114
|
-
protected:
|
115
|
-
|
116
|
-
OSC osc;
|
117
|
-
|
118
|
-
uint drop_msec = DROP_MSEC;
|
119
|
-
|
120
|
-
};// StkOsc
|
121
|
-
|
122
|
-
|
123
|
-
typedef StkOsc<SineWave, 0> SineOsc;
|
124
|
-
|
125
|
-
typedef StkOsc<stk::BlitSquare, 100> SquareOsc;
|
126
|
-
|
127
|
-
typedef StkOsc<BlitSaw, 200> SawtoothOsc;
|
128
|
-
|
129
|
-
|
130
|
-
class TriangleOsc : public StkOsc<stk::Blit, 0>
|
131
|
-
{
|
132
|
-
|
133
|
-
public:
|
134
|
-
|
135
|
-
TriangleOsc ()
|
136
|
-
{
|
137
|
-
osc.setHarmonics(10);
|
138
|
-
}
|
139
|
-
|
140
|
-
};// TriangleOsc
|
141
|
-
|
142
|
-
|
143
45
|
class NoiseOsc : public Osc
|
144
46
|
{
|
145
47
|
|
@@ -150,9 +52,9 @@ namespace Beeps
|
|
150
52
|
time = 0;
|
151
53
|
}
|
152
54
|
|
153
|
-
void tick (
|
55
|
+
void tick (stk::StkFrames* frames) override
|
154
56
|
{
|
155
|
-
if (0 < freq && (freq * 2) <= frames->
|
57
|
+
if (0 < freq && (freq * 2) <= frames->dataRate())
|
156
58
|
tick_with_freq(frames);
|
157
59
|
else
|
158
60
|
tick_without_freq(frames);
|
@@ -163,6 +65,11 @@ namespace Beeps
|
|
163
65
|
this->freq = freq;
|
164
66
|
}
|
165
67
|
|
68
|
+
float frequency () const override
|
69
|
+
{
|
70
|
+
return freq;
|
71
|
+
}
|
72
|
+
|
166
73
|
void set_phase (float phase) override
|
167
74
|
{
|
168
75
|
time = freq == 0 ? 0 : phase * (1.f / freq);
|
@@ -179,32 +86,32 @@ namespace Beeps
|
|
179
86
|
|
180
87
|
double time = 0;
|
181
88
|
|
182
|
-
void tick_without_freq (
|
89
|
+
void tick_without_freq (stk::StkFrames* frames)
|
183
90
|
{
|
184
|
-
uint nchannels = frames->
|
185
|
-
uint nframes = frames->
|
186
|
-
|
187
|
-
for (uint i = 0; i < nframes; ++i, ++
|
91
|
+
uint nchannels = frames->channels();
|
92
|
+
uint nframes = frames->frames();
|
93
|
+
Sample* p = &(*frames)(0, 0);
|
94
|
+
for (uint i = 0; i < nframes; ++i, ++p)
|
188
95
|
{
|
189
96
|
uint ch = i % nchannels;
|
190
|
-
*
|
97
|
+
*p = ch == 0 ? noise() : p[-ch];
|
191
98
|
}
|
192
99
|
}
|
193
100
|
|
194
|
-
void tick_with_freq (
|
101
|
+
void tick_with_freq (stk::StkFrames* frames)
|
195
102
|
{
|
196
|
-
float time_per_sample = 1.f / frames->
|
103
|
+
float time_per_sample = 1.f / frames->dataRate();
|
197
104
|
float time_per_freq = 1.f / (freq * 2);
|
198
105
|
|
199
|
-
uint nchannels = frames->
|
200
|
-
uint nframes = frames->
|
201
|
-
|
106
|
+
uint nchannels = frames->channels();
|
107
|
+
uint nframes = frames->frames();
|
108
|
+
Sample* p = &(*frames)(0, 0);
|
202
109
|
float value = noise();
|
203
|
-
for (uint i = 0; i < nframes; ++i, ++
|
110
|
+
for (uint i = 0; i < nframes; ++i, ++p)
|
204
111
|
{
|
205
112
|
if (i % nchannels == 0)
|
206
113
|
{
|
207
|
-
*
|
114
|
+
*p = value;
|
208
115
|
|
209
116
|
time += time_per_sample;
|
210
117
|
while (time >= time_per_freq)
|
@@ -214,7 +121,7 @@ namespace Beeps
|
|
214
121
|
}
|
215
122
|
}
|
216
123
|
else
|
217
|
-
*
|
124
|
+
*p = value;
|
218
125
|
}
|
219
126
|
}
|
220
127
|
|
@@ -231,10 +138,10 @@ namespace Beeps
|
|
231
138
|
|
232
139
|
public:
|
233
140
|
|
234
|
-
typedef std::vector<
|
141
|
+
typedef std::vector<Sample> Table;
|
235
142
|
|
236
|
-
WaveformOsc (
|
237
|
-
: table(samples, samples + nsamples), freq(
|
143
|
+
WaveformOsc (const Sample* samples, size_t nsamples)
|
144
|
+
: table(samples, samples + nsamples), freq(1), time(0)
|
238
145
|
{
|
239
146
|
}
|
240
147
|
|
@@ -243,15 +150,16 @@ namespace Beeps
|
|
243
150
|
time = 0;
|
244
151
|
}
|
245
152
|
|
246
|
-
void tick (
|
153
|
+
void tick (stk::StkFrames* frames) override
|
247
154
|
{
|
248
155
|
size_t size = table.size();
|
249
|
-
float dt = size * freq / frames->
|
156
|
+
float dt = size * freq / frames->dataRate();
|
250
157
|
|
251
|
-
uint nchannels = frames->
|
252
|
-
uint nframes = frames->
|
253
|
-
|
254
|
-
|
158
|
+
uint nchannels = frames->channels();
|
159
|
+
uint nframes = frames->frames();
|
160
|
+
Sample* p = &(*frames)(0, 0);
|
161
|
+
Sample prev = 0;
|
162
|
+
for (uint i = 0; i < nframes; ++i, ++p)
|
255
163
|
{
|
256
164
|
uint ch = i % nchannels;
|
257
165
|
if (ch == 0)
|
@@ -259,13 +167,13 @@ namespace Beeps
|
|
259
167
|
size_t index0 = (size_t) time;
|
260
168
|
size_t index1 = index0 == size - 1 ? 0 : index0 + 1;
|
261
169
|
float frac = time - index0;
|
262
|
-
*
|
170
|
+
*p = table[index0] * (1.f - frac) + table[index1] * frac;
|
171
|
+
prev = *p;
|
263
172
|
|
264
173
|
time += dt;
|
265
174
|
while (time >= size) time -= size;
|
266
175
|
}
|
267
|
-
else
|
268
|
-
*pframe = pframe[-ch];
|
176
|
+
else *p = prev;
|
269
177
|
}
|
270
178
|
}
|
271
179
|
|
@@ -274,6 +182,11 @@ namespace Beeps
|
|
274
182
|
this->freq = freq;
|
275
183
|
}
|
276
184
|
|
185
|
+
float frequency () const override
|
186
|
+
{
|
187
|
+
return freq;
|
188
|
+
}
|
189
|
+
|
277
190
|
void set_phase (float phase) override
|
278
191
|
{
|
279
192
|
this->time = std::fmod(phase, 1.f) * table.size();
|
@@ -301,21 +214,28 @@ namespace Beeps
|
|
301
214
|
struct Oscillator::Data
|
302
215
|
{
|
303
216
|
|
304
|
-
Type type
|
217
|
+
Type type = TYPE_NONE;
|
218
|
+
|
219
|
+
float gain = 1;
|
305
220
|
|
306
|
-
float
|
221
|
+
float offset = 0;
|
222
|
+
|
223
|
+
float duty = 0.5;
|
307
224
|
|
308
225
|
std::unique_ptr<Osc> osc;
|
309
226
|
|
310
227
|
};// Oscillator::Data
|
311
228
|
|
312
229
|
|
230
|
+
enum InputIndex {FREQUENCY = 0, PHASE, GAIN, OFFSET, DUTY};
|
231
|
+
|
232
|
+
|
313
233
|
Oscillator::Oscillator (Type type)
|
314
234
|
{
|
315
235
|
set_type(type);
|
316
236
|
}
|
317
237
|
|
318
|
-
Oscillator::Oscillator (
|
238
|
+
Oscillator::Oscillator (const Sample* samples, size_t size)
|
319
239
|
{
|
320
240
|
set_samples(samples, size);
|
321
241
|
}
|
@@ -329,32 +249,77 @@ namespace Beeps
|
|
329
249
|
{
|
330
250
|
Super::reset();
|
331
251
|
self->osc->reset();
|
252
|
+
|
253
|
+
set_updated();
|
332
254
|
}
|
333
255
|
|
334
|
-
|
335
|
-
Oscillator::
|
256
|
+
static Osc*
|
257
|
+
create_osc (Oscillator::Type type, size_t size, float duty)
|
336
258
|
{
|
337
|
-
|
259
|
+
std::function<Sample(float)> fun;
|
260
|
+
switch (type)
|
261
|
+
{
|
262
|
+
case Oscillator::SINE:
|
263
|
+
fun = [](float t) {return std::sin(t * M_PI * 2);};
|
264
|
+
break;
|
338
265
|
|
339
|
-
|
266
|
+
case Oscillator::TRIANGLE:
|
267
|
+
fun = [](float t) {return t < 0.5 ? t * 4 - 1 : 3 - t * 4;};
|
268
|
+
break;
|
340
269
|
|
341
|
-
|
342
|
-
|
270
|
+
case Oscillator::SAWTOOTH:
|
271
|
+
fun = [](float t) {return t * 2 - 1;};
|
272
|
+
break;
|
273
|
+
|
274
|
+
case Oscillator::SQUARE:
|
275
|
+
fun = [=](float t) {return t < duty ? 1 : -1;};
|
276
|
+
break;
|
277
|
+
|
278
|
+
case Oscillator::NOISE:
|
279
|
+
return new NoiseOsc();
|
343
280
|
|
344
|
-
switch (self->type)
|
345
|
-
{
|
346
|
-
case SINE: self->osc.reset(new SineOsc()); break;
|
347
|
-
case TRIANGLE: self->osc.reset(new TriangleOsc()); break;
|
348
|
-
case SQUARE: self->osc.reset(new SquareOsc()); break;
|
349
|
-
case SAWTOOTH: self->osc.reset(new SawtoothOsc()); break;
|
350
|
-
case NOISE: self->osc.reset(new NoiseOsc()); break;
|
351
281
|
default:
|
352
282
|
argument_error(
|
353
|
-
__FILE__, __LINE__, "unknown oscilator type '%d'",
|
283
|
+
__FILE__, __LINE__, "unknown oscilator type '%d'", type);
|
354
284
|
break;
|
355
285
|
}
|
356
286
|
|
287
|
+
std::vector<Sample> samples;
|
288
|
+
samples.resize(size);
|
289
|
+
for (size_t i = 0; i < size; ++i)
|
290
|
+
samples[i] = fun(i / (float) size);
|
291
|
+
|
292
|
+
return new WaveformOsc(&samples[0], samples.size());
|
293
|
+
}
|
294
|
+
|
295
|
+
static void
|
296
|
+
update_osc (Oscillator* pthis, std::function<Osc*()> fun)
|
297
|
+
{
|
298
|
+
Oscillator::Data* self = pthis->self.get();
|
299
|
+
|
300
|
+
float freq = self->osc ? self->osc->frequency() : 440;
|
301
|
+
float phase = self->osc ? self->osc->phase() : 0;
|
302
|
+
|
303
|
+
self->osc.reset(fun());
|
304
|
+
|
305
|
+
self->osc->set_frequency(freq);
|
357
306
|
self->osc->set_phase(phase);
|
307
|
+
}
|
308
|
+
|
309
|
+
static void
|
310
|
+
update_waveform (Oscillator* pthis)
|
311
|
+
{
|
312
|
+
update_osc(pthis, [&]()
|
313
|
+
{
|
314
|
+
return create_osc(pthis->type(), 32, pthis->duty());
|
315
|
+
});
|
316
|
+
}
|
317
|
+
|
318
|
+
void
|
319
|
+
Oscillator::set_type (Type type)
|
320
|
+
{
|
321
|
+
self->type = type;
|
322
|
+
update_waveform(this);
|
358
323
|
|
359
324
|
set_updated();
|
360
325
|
}
|
@@ -366,18 +331,18 @@ namespace Beeps
|
|
366
331
|
}
|
367
332
|
|
368
333
|
void
|
369
|
-
Oscillator::set_samples (
|
334
|
+
Oscillator::set_samples (const Sample* samples, size_t size)
|
370
335
|
{
|
371
|
-
float phase = self->osc ? self->osc->phase() : 0;
|
372
|
-
|
373
336
|
self->type = SAMPLES;
|
374
|
-
|
375
|
-
|
337
|
+
update_osc(this, [=]()
|
338
|
+
{
|
339
|
+
return new WaveformOsc(samples, size);
|
340
|
+
});
|
376
341
|
|
377
342
|
set_updated();
|
378
343
|
}
|
379
344
|
|
380
|
-
const
|
345
|
+
const Sample*
|
381
346
|
Oscillator::samples () const
|
382
347
|
{
|
383
348
|
if (self->type != SAMPLES)
|
@@ -403,21 +368,37 @@ namespace Beeps
|
|
403
368
|
if (frequency <= 0)
|
404
369
|
argument_error(__FILE__, __LINE__);
|
405
370
|
|
406
|
-
self->frequency
|
371
|
+
self->osc->set_frequency(frequency);
|
372
|
+
|
407
373
|
set_updated();
|
374
|
+
clear_sub_input_unless_processing(FREQUENCY);
|
375
|
+
}
|
376
|
+
|
377
|
+
void
|
378
|
+
Oscillator::set_frequency (Processor* frequency)
|
379
|
+
{
|
380
|
+
set_sub_input(FREQUENCY, frequency);
|
408
381
|
}
|
409
382
|
|
410
383
|
float
|
411
384
|
Oscillator::frequency () const
|
412
385
|
{
|
413
|
-
return self->frequency;
|
386
|
+
return self->osc->frequency();
|
414
387
|
}
|
415
388
|
|
416
389
|
void
|
417
390
|
Oscillator::set_phase (float phase)
|
418
391
|
{
|
419
392
|
self->osc->set_phase(phase);
|
393
|
+
|
420
394
|
set_updated();
|
395
|
+
clear_sub_input_unless_processing(PHASE);
|
396
|
+
}
|
397
|
+
|
398
|
+
void
|
399
|
+
Oscillator::set_phase (Processor* phase)
|
400
|
+
{
|
401
|
+
set_sub_input(PHASE, phase);
|
421
402
|
}
|
422
403
|
|
423
404
|
float
|
@@ -427,24 +408,135 @@ namespace Beeps
|
|
427
408
|
}
|
428
409
|
|
429
410
|
void
|
430
|
-
Oscillator::
|
411
|
+
Oscillator::set_gain (float gain)
|
431
412
|
{
|
432
|
-
|
413
|
+
if (gain == self->gain)
|
414
|
+
return;
|
415
|
+
|
416
|
+
self->gain = gain;
|
417
|
+
|
418
|
+
set_updated();
|
419
|
+
clear_sub_input_unless_processing(GAIN);
|
420
|
+
}
|
421
|
+
|
422
|
+
void
|
423
|
+
Oscillator::set_gain (Processor* gain)
|
424
|
+
{
|
425
|
+
set_sub_input(GAIN, gain);
|
426
|
+
}
|
433
427
|
|
434
|
-
|
435
|
-
|
428
|
+
float
|
429
|
+
Oscillator::gain () const
|
430
|
+
{
|
431
|
+
return self->gain;
|
432
|
+
}
|
433
|
+
|
434
|
+
void
|
435
|
+
Oscillator::set_offset (float offset)
|
436
|
+
{
|
437
|
+
if (offset == self->offset)
|
438
|
+
return;
|
439
|
+
|
440
|
+
self->offset = offset;
|
441
|
+
|
442
|
+
set_updated();
|
443
|
+
clear_sub_input_unless_processing(OFFSET);
|
444
|
+
}
|
445
|
+
|
446
|
+
void
|
447
|
+
Oscillator::set_offset (Processor* offset)
|
448
|
+
{
|
449
|
+
set_sub_input(OFFSET, offset);
|
450
|
+
}
|
451
|
+
|
452
|
+
float
|
453
|
+
Oscillator::offset () const
|
454
|
+
{
|
455
|
+
return self->offset;
|
456
|
+
}
|
457
|
+
|
458
|
+
void
|
459
|
+
Oscillator::set_duty (float duty)
|
460
|
+
{
|
461
|
+
if (duty <= 0)
|
462
|
+
argument_error(__FILE__, __LINE__);
|
463
|
+
if (duty >= 1)
|
436
464
|
argument_error(__FILE__, __LINE__);
|
437
465
|
|
438
|
-
|
439
|
-
|
466
|
+
if (duty == self->duty)
|
467
|
+
return;
|
468
|
+
|
469
|
+
self->duty = duty;
|
470
|
+
if (type() == SQUARE) update_waveform(this);
|
471
|
+
|
472
|
+
set_updated();
|
473
|
+
clear_sub_input_unless_processing(DUTY);
|
474
|
+
}
|
475
|
+
|
476
|
+
void
|
477
|
+
Oscillator::set_duty (Processor* duty)
|
478
|
+
{
|
479
|
+
set_sub_input(DUTY, duty);
|
480
|
+
}
|
440
481
|
|
441
|
-
|
482
|
+
float
|
483
|
+
Oscillator::duty () const
|
484
|
+
{
|
485
|
+
return self->duty;
|
442
486
|
}
|
443
487
|
|
444
488
|
Oscillator::operator bool () const
|
445
489
|
{
|
446
|
-
if (!Super::operator bool())
|
447
|
-
|
490
|
+
if (!Super::operator bool())
|
491
|
+
return false;
|
492
|
+
|
493
|
+
return self->type != TYPE_NONE && self->osc;
|
494
|
+
}
|
495
|
+
|
496
|
+
void
|
497
|
+
Oscillator::generate (Context* context, Signals* signals, uint* offset)
|
498
|
+
{
|
499
|
+
Super::generate(context, signals, offset);
|
500
|
+
|
501
|
+
Processor* pfreq = sub_input(FREQUENCY);
|
502
|
+
Processor* pphase = sub_input(PHASE);
|
503
|
+
Processor* pgain = sub_input(GAIN);
|
504
|
+
Processor* poffset = sub_input(OFFSET);
|
505
|
+
Processor* pduty = sub_input(DUTY);
|
506
|
+
|
507
|
+
auto* pcontext = Processor_get_context(context);
|
508
|
+
double sample_rate = signals->sample_rate();
|
509
|
+
uint nsamples = signals->capacity();
|
510
|
+
uint seg_size = get_segment_size(sample_rate, nsamples);
|
511
|
+
|
512
|
+
for (uint start = 0; start < nsamples; start += seg_size)
|
513
|
+
{
|
514
|
+
uint seg_offset = *offset + start;
|
515
|
+
if (pfreq) set_frequency(pcontext->process(pfreq, seg_size, seg_offset));
|
516
|
+
if (pphase) set_phase( pcontext->process(pphase, seg_size, seg_offset));
|
517
|
+
if (pgain) set_gain( pcontext->process(pgain, seg_size, seg_offset));
|
518
|
+
if (poffset) set_offset( pcontext->process(poffset, seg_size, seg_offset));
|
519
|
+
if (pduty) set_duty( pcontext->process(pduty, seg_size, seg_offset));
|
520
|
+
|
521
|
+
uint end = std::min(start + seg_size, nsamples);
|
522
|
+
Signals_tick(signals, start, end, [&](stk::StkFrames* frames)
|
523
|
+
{
|
524
|
+
self->osc->tick(frames);
|
525
|
+
});
|
526
|
+
Signals_offset_and_scale(signals, self->offset, self->gain, -1, start, end);
|
527
|
+
}
|
528
|
+
|
529
|
+
*offset += signals->nsamples();
|
530
|
+
}
|
531
|
+
|
532
|
+
int
|
533
|
+
Oscillator::max_segment_size_for_process (
|
534
|
+
double sample_rate, uint nsamples) const
|
535
|
+
{
|
536
|
+
return std::clamp(
|
537
|
+
(uint) (sample_rate / frequency() / NSEGMENTS_PER_WAVEFORM_CYCLE),
|
538
|
+
MIN_BUFFER_SIZE,
|
539
|
+
nsamples);
|
448
540
|
}
|
449
541
|
|
450
542
|
|
data/src/pitch_shift.cpp
CHANGED
@@ -52,6 +52,12 @@ namespace Beeps
|
|
52
52
|
return self->shift;
|
53
53
|
}
|
54
54
|
|
55
|
+
PitchShift::operator bool () const
|
56
|
+
{
|
57
|
+
if (!Super::operator bool()) return false;
|
58
|
+
return self->shift > 0;
|
59
|
+
}
|
60
|
+
|
55
61
|
void
|
56
62
|
PitchShift::filter (Context* context, Signals* signals, uint* offset)
|
57
63
|
{
|
@@ -72,11 +78,5 @@ namespace Beeps
|
|
72
78
|
Signals_write_samples(signals, output, signals->nsamples());
|
73
79
|
}
|
74
80
|
|
75
|
-
PitchShift::operator bool () const
|
76
|
-
{
|
77
|
-
if (!Super::operator bool()) return false;
|
78
|
-
return self->shift > 0;
|
79
|
-
}
|
80
|
-
|
81
81
|
|
82
82
|
}// Beeps
|