beeps 0.1.31 → 0.1.33
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.doc/ext/beeps/adsr.cpp +139 -0
- data/.doc/ext/beeps/analyser.cpp +128 -0
- data/.doc/ext/beeps/beeps.cpp +9 -1
- data/.doc/ext/beeps/file_in.cpp +55 -9
- data/.doc/ext/beeps/gain.cpp +64 -0
- data/.doc/ext/beeps/mic_in.cpp +83 -0
- data/.doc/ext/beeps/native.cpp +20 -8
- data/.doc/ext/beeps/oscillator.cpp +88 -0
- data/.doc/ext/beeps/pitch_shift.cpp +64 -0
- data/.doc/ext/beeps/processor.cpp +31 -2
- data/.doc/ext/beeps/sound.cpp +90 -7
- data/.doc/ext/beeps/sound_player.cpp +156 -0
- data/.doc/ext/beeps/time_stretch.cpp +64 -0
- data/.github/workflows/release-gem.yml +62 -0
- data/.github/workflows/test.yml +0 -6
- data/.github/workflows/utils.rb +13 -5
- data/ChangeLog.md +13 -0
- data/Rakefile +27 -6
- data/VERSION +1 -1
- data/beeps.gemspec +2 -2
- data/ext/beeps/adsr.cpp +150 -0
- data/ext/beeps/analyser.cpp +134 -0
- data/ext/beeps/beeps.cpp +10 -1
- data/ext/beeps/extconf.rb +1 -2
- data/ext/beeps/file_in.cpp +60 -9
- data/ext/beeps/gain.cpp +67 -0
- data/ext/beeps/mic_in.cpp +88 -0
- data/ext/beeps/native.cpp +20 -8
- data/ext/beeps/oscillator.cpp +93 -0
- data/ext/beeps/pitch_shift.cpp +67 -0
- data/ext/beeps/processor.cpp +34 -2
- data/ext/beeps/sound.cpp +99 -7
- data/ext/beeps/sound_player.cpp +169 -0
- data/ext/beeps/time_stretch.cpp +67 -0
- data/include/beeps/beeps.h +2 -1
- data/include/beeps/filter.h +179 -0
- data/include/beeps/generator.h +120 -0
- data/include/beeps/processor.h +37 -68
- data/include/beeps/ruby/filter.h +78 -0
- data/include/beeps/ruby/generator.h +60 -0
- data/include/beeps/ruby/processor.h +5 -45
- data/include/beeps/ruby/sound.h +14 -3
- data/include/beeps/signals.h +10 -4
- data/include/beeps/sound.h +67 -2
- data/lib/beeps/beeps.rb +6 -1
- data/lib/beeps/processor.rb +95 -15
- data/lib/beeps/sound.rb +29 -2
- data/src/adsr.cpp +245 -0
- data/src/analyser.cpp +254 -0
- data/src/beeps.cpp +11 -2
- data/src/file_in.cpp +94 -0
- data/src/gain.cpp +55 -0
- data/src/mic_in.cpp +262 -0
- data/src/mic_in.h +20 -0
- data/src/openal.cpp +2 -1
- data/src/oscillator.cpp +145 -0
- data/src/osx/signals.mm +83 -0
- data/src/pitch_shift.cpp +82 -0
- data/src/processor.cpp +202 -88
- data/src/processor.h +98 -0
- data/src/signals.cpp +326 -20
- data/src/signals.h +192 -2
- data/src/sound.cpp +735 -113
- data/src/sound.h +6 -1
- data/src/time_stretch.cpp +91 -0
- data/test/helper.rb +2 -1
- data/test/test_beeps.rb +10 -7
- data/test/test_beeps_init.rb +18 -0
- data/test/test_file_in.rb +15 -0
- data/test/test_processor.rb +50 -0
- data/test/test_sound.rb +87 -11
- data/test/test_sound_player.rb +134 -0
- metadata +55 -17
- data/.doc/ext/beeps/sawtooth_wave.cpp +0 -61
- data/.doc/ext/beeps/sine_wave.cpp +0 -61
- data/.doc/ext/beeps/square_wave.cpp +0 -61
- data/.github/workflows/release.yml +0 -34
- data/ext/beeps/sawtooth_wave.cpp +0 -64
- data/ext/beeps/sine_wave.cpp +0 -64
- 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<
|
19
|
+
std::unique_ptr<Frames> frames;
|
20
|
+
|
21
|
+
uint nsamples = 0;
|
17
22
|
|
18
23
|
};// Signals::Data
|
19
24
|
|
20
25
|
|
21
|
-
|
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
|
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
|
-
|
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 (
|
40
|
-
|
206
|
+
if (!to || !*to || !from)
|
207
|
+
argument_error(__FILE__, __LINE__);
|
208
|
+
|
209
|
+
Signals_clear(to);
|
41
210
|
|
42
|
-
|
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
|
344
|
+
t.self->frames.reset(new Frames(*self->frames));
|
345
|
+
t.self->nsamples = self->nsamples;
|
55
346
|
return t;
|
56
347
|
}
|
57
348
|
|
58
|
-
|
59
|
-
Signals::
|
349
|
+
double
|
350
|
+
Signals::sample_rate () const
|
60
351
|
{
|
61
|
-
|
62
|
-
return (float) sec;
|
352
|
+
return self->frames ? self->frames->dataRate() : Beeps::sample_rate();
|
63
353
|
}
|
64
354
|
|
65
355
|
uint
|
66
|
-
Signals::
|
356
|
+
Signals::nchannels () const
|
67
357
|
{
|
68
|
-
|
69
|
-
return p ? p->frames->frames() : 0;
|
358
|
+
return self->frames ? self->frames->nchannels() : 0;
|
70
359
|
}
|
71
360
|
|
72
361
|
uint
|
73
|
-
Signals::
|
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
|
-
|
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
|
82
|
-
return f && f->
|
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
|
-
|
18
|
+
typedef stk::StkFloat Float;
|
16
19
|
|
17
|
-
|
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
|