beeps 0.1.32 → 0.1.33
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/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 +4 -1
- data/ChangeLog.md +8 -0
- data/Rakefile +26 -4
- 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 +54 -16
- 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/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
|