beeps 0.3.8 → 0.3.10
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/analyser.cpp +2 -2
- data/.doc/ext/beeps/native.cpp +5 -5
- data/.doc/ext/beeps/oscillator.cpp +2 -2
- data/.doc/ext/beeps/sequencer.cpp +17 -0
- data/.doc/ext/beeps/sound.cpp +1 -1
- data/.doc/ext/beeps/text_in.cpp +63 -0
- data/.doc/ext/beeps/value.cpp +107 -0
- data/CLAUDE.md +24 -0
- data/ChangeLog.md +18 -0
- data/README.md +1 -0
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/beeps.gemspec +2 -2
- data/ext/beeps/analyser.cpp +2 -2
- data/ext/beeps/extconf.rb +10 -6
- data/ext/beeps/native.cpp +5 -5
- data/ext/beeps/oscillator.cpp +2 -2
- data/ext/beeps/sequencer.cpp +18 -0
- data/ext/beeps/sound.cpp +1 -1
- data/ext/beeps/text_in.cpp +66 -0
- data/ext/beeps/value.cpp +114 -0
- data/include/beeps/generator.h +121 -0
- data/include/beeps/ruby/generator.h +22 -0
- data/include/beeps/signals.h +2 -0
- data/lib/beeps/ext.rb +1 -1
- data/lib/beeps/processor.rb +56 -1
- data/src/osx/signals.h +23 -0
- data/src/osx/signals.mm +66 -15
- data/src/osx/text_in.mm +133 -0
- data/src/sdl/beeps.cpp +19 -0
- data/src/sdl/signals.cpp +18 -0
- data/src/sdl/text_in.cpp +61 -0
- data/src/sequencer.cpp +31 -16
- data/src/signals.cpp +104 -30
- data/src/signals.h +10 -4
- data/src/value.cpp +181 -0
- data/src/win32/text_in.cpp +62 -0
- data/test/test_oscillator.rb +2 -2
- data/test/test_sequencer.rb +25 -0
- data/test/test_value.rb +47 -0
- metadata +24 -18
data/src/sequencer.cpp
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#include "beeps/generator.h"
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
#include <list>
|
|
5
4
|
#include <algorithm>
|
|
6
5
|
#include "beeps/exception.h"
|
|
7
6
|
#include "beeps/debug.h"
|
|
@@ -16,21 +15,7 @@ namespace Beeps
|
|
|
16
15
|
struct Sequencer::Data
|
|
17
16
|
{
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
Processor::Ref processor;
|
|
23
|
-
|
|
24
|
-
float offset, duration;
|
|
25
|
-
|
|
26
|
-
Note (Processor* processor, float offset, float duration)
|
|
27
|
-
: processor(processor), offset(offset), duration(duration)
|
|
28
|
-
{
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
};// Note
|
|
32
|
-
|
|
33
|
-
std::list<Note> notes;
|
|
18
|
+
NoteList notes;
|
|
34
19
|
|
|
35
20
|
float time_scale = 1;
|
|
36
21
|
|
|
@@ -42,6 +27,12 @@ namespace Beeps
|
|
|
42
27
|
};// Sequencer::Data
|
|
43
28
|
|
|
44
29
|
|
|
30
|
+
Sequencer::Note::Note (Processor* processor, float offset, float duration)
|
|
31
|
+
: processor(processor), offset(offset), duration(duration)
|
|
32
|
+
{
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
45
36
|
Sequencer::Sequencer ()
|
|
46
37
|
{
|
|
47
38
|
}
|
|
@@ -99,6 +90,30 @@ namespace Beeps
|
|
|
99
90
|
return self->time_scale;
|
|
100
91
|
}
|
|
101
92
|
|
|
93
|
+
Sequencer::iterator
|
|
94
|
+
Sequencer::begin ()
|
|
95
|
+
{
|
|
96
|
+
return self->notes.begin();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
Sequencer::const_iterator
|
|
100
|
+
Sequencer::begin () const
|
|
101
|
+
{
|
|
102
|
+
return self->notes.begin();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Sequencer::iterator
|
|
106
|
+
Sequencer::end ()
|
|
107
|
+
{
|
|
108
|
+
return self->notes.end();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
Sequencer::const_iterator
|
|
112
|
+
Sequencer::end () const
|
|
113
|
+
{
|
|
114
|
+
return self->notes.end();
|
|
115
|
+
}
|
|
116
|
+
|
|
102
117
|
Sequencer::operator bool () const
|
|
103
118
|
{
|
|
104
119
|
if (!Super::operator bool()) return false;
|
data/src/signals.cpp
CHANGED
|
@@ -116,13 +116,13 @@ namespace Beeps
|
|
|
116
116
|
Signals
|
|
117
117
|
Signals_create (
|
|
118
118
|
const float* const* channels,
|
|
119
|
-
uint nsamples, uint nchannels, double sample_rate)
|
|
119
|
+
uint nsamples, uint nchannels, double sample_rate, uint capacity)
|
|
120
120
|
{
|
|
121
121
|
if (!channels)
|
|
122
122
|
argument_error(__FILE__, __LINE__);
|
|
123
123
|
|
|
124
|
-
Signals s
|
|
125
|
-
|
|
124
|
+
Signals s = Signals_create(
|
|
125
|
+
capacity > nsamples ? capacity : nsamples, nchannels, sample_rate);
|
|
126
126
|
|
|
127
127
|
for (uint channel = 0; channel < nchannels; ++channel)
|
|
128
128
|
{
|
|
@@ -131,32 +131,10 @@ namespace Beeps
|
|
|
131
131
|
*p = channels[channel][i];
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
s.self->nsamples = nsamples;
|
|
134
135
|
return s;
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
void
|
|
138
|
-
Signals_clear (Signals* signals)
|
|
139
|
-
{
|
|
140
|
-
if (!signals)
|
|
141
|
-
argument_error(__FILE__, __LINE__);
|
|
142
|
-
|
|
143
|
-
signals->self->nsamples = 0;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
void
|
|
147
|
-
Signals_clear (Signals* signals, uint capacity)
|
|
148
|
-
{
|
|
149
|
-
if (!signals)
|
|
150
|
-
argument_error(__FILE__, __LINE__);
|
|
151
|
-
if (!*signals)
|
|
152
|
-
argument_error(__FILE__, __LINE__);
|
|
153
|
-
if (capacity <= 0)
|
|
154
|
-
argument_error(__FILE__, __LINE__);
|
|
155
|
-
|
|
156
|
-
Signals_clear(signals);
|
|
157
|
-
signals->self->frames->resize(capacity, signals->nchannels());
|
|
158
|
-
}
|
|
159
|
-
|
|
160
138
|
uint
|
|
161
139
|
Signals_tick (Signals* signals, std::function<void(stk::StkFrames*)> fun)
|
|
162
140
|
{
|
|
@@ -212,20 +190,70 @@ namespace Beeps
|
|
|
212
190
|
}
|
|
213
191
|
|
|
214
192
|
void
|
|
215
|
-
|
|
193
|
+
Signals_clear (Signals* signals)
|
|
194
|
+
{
|
|
195
|
+
if (!signals)
|
|
196
|
+
argument_error(__FILE__, __LINE__);
|
|
197
|
+
|
|
198
|
+
signals->self->nsamples = 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
void
|
|
202
|
+
Signals_clear (Signals* signals, uint capacity)
|
|
216
203
|
{
|
|
217
204
|
if (!signals)
|
|
218
205
|
argument_error(__FILE__, __LINE__);
|
|
219
206
|
if (!*signals)
|
|
220
207
|
argument_error(__FILE__, __LINE__);
|
|
208
|
+
if (capacity <= 0)
|
|
209
|
+
argument_error(__FILE__, __LINE__);
|
|
221
210
|
|
|
222
211
|
Signals_clear(signals);
|
|
223
|
-
|
|
212
|
+
signals->self->frames->resize(capacity, signals->nchannels());
|
|
213
|
+
}
|
|
224
214
|
|
|
225
|
-
|
|
215
|
+
void
|
|
216
|
+
Signals_fill (Signals* signals, uint nsamples, Sample value, uint offset)
|
|
217
|
+
{
|
|
218
|
+
if (!signals)
|
|
219
|
+
argument_error(__FILE__, __LINE__);
|
|
220
|
+
if (!*signals)
|
|
221
|
+
argument_error(__FILE__, __LINE__);
|
|
222
|
+
|
|
223
|
+
uint new_nsamples = offset + nsamples;
|
|
224
|
+
if (new_nsamples > signals->capacity())
|
|
225
|
+
beeps_error(__FILE__, __LINE__);
|
|
226
|
+
|
|
227
|
+
Sample* p = Signals_at(signals, offset);
|
|
226
228
|
size_t size = nsamples * signals->nchannels();
|
|
227
229
|
for (size_t i = 0; i < size; ++i)
|
|
228
230
|
*p++ = value;
|
|
231
|
+
|
|
232
|
+
Signals_set_nsamples(signals, new_nsamples);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
void
|
|
236
|
+
Signals_shift (Signals* signals, uint nsamples)
|
|
237
|
+
{
|
|
238
|
+
if (!signals)
|
|
239
|
+
argument_error(__FILE__, __LINE__);
|
|
240
|
+
if (!*signals)
|
|
241
|
+
argument_error(__FILE__, __LINE__);
|
|
242
|
+
|
|
243
|
+
if (nsamples == 0)
|
|
244
|
+
return;
|
|
245
|
+
|
|
246
|
+
int new_nsamples = signals->nsamples() - nsamples;
|
|
247
|
+
if (new_nsamples < 0)
|
|
248
|
+
new_nsamples = 0;
|
|
249
|
+
|
|
250
|
+
Sample* from = Signals_at(signals, nsamples);
|
|
251
|
+
Sample* to = Signals_at(signals, 0);
|
|
252
|
+
int size = new_nsamples * signals->nchannels();
|
|
253
|
+
for (int i = 0; i < size; ++i)
|
|
254
|
+
*to++ = *from++;
|
|
255
|
+
|
|
256
|
+
Signals_set_nsamples(signals, new_nsamples);
|
|
229
257
|
}
|
|
230
258
|
|
|
231
259
|
static uint
|
|
@@ -450,6 +478,43 @@ namespace Beeps
|
|
|
450
478
|
write_samples(signals, samples, nsamples);
|
|
451
479
|
}
|
|
452
480
|
|
|
481
|
+
void
|
|
482
|
+
Signals_set_capacity (Signals* signals, uint capacity)
|
|
483
|
+
{
|
|
484
|
+
if (!signals)
|
|
485
|
+
argument_error(__FILE__, __LINE__);
|
|
486
|
+
if (!*signals)
|
|
487
|
+
argument_error(__FILE__, __LINE__);
|
|
488
|
+
if (capacity == 0)
|
|
489
|
+
argument_error(__FILE__, __LINE__);
|
|
490
|
+
|
|
491
|
+
if (capacity == signals->capacity())
|
|
492
|
+
return;
|
|
493
|
+
|
|
494
|
+
uint nsamples = signals->nsamples();
|
|
495
|
+
uint nchannels = signals->nchannels();
|
|
496
|
+
|
|
497
|
+
if (capacity < signals->capacity())
|
|
498
|
+
{
|
|
499
|
+
signals->self->frames->resize(capacity, nchannels);
|
|
500
|
+
if (capacity < nsamples) Signals_set_nsamples(signals, capacity);
|
|
501
|
+
}
|
|
502
|
+
else
|
|
503
|
+
{
|
|
504
|
+
double sample_rate = signals->sample_rate();
|
|
505
|
+
const Sample* from = Signals_at(signals, 0);
|
|
506
|
+
|
|
507
|
+
std::unique_ptr<Frames> old = std::move(signals->self->frames);
|
|
508
|
+
signals->self->frames.reset(
|
|
509
|
+
new Frames(capacity * nchannels, nchannels, sample_rate));
|
|
510
|
+
|
|
511
|
+
Sample* to = Signals_at(signals, 0);
|
|
512
|
+
uint size = nsamples * nchannels;
|
|
513
|
+
for (uint i = 0; i < size; ++i)
|
|
514
|
+
*to++ = *from++;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
453
518
|
void
|
|
454
519
|
Signals_set_nsamples (Signals* signals, uint nsamples)
|
|
455
520
|
{
|
|
@@ -568,7 +633,16 @@ namespace Beeps
|
|
|
568
633
|
bool
|
|
569
634
|
Signals::empty () const
|
|
570
635
|
{
|
|
571
|
-
return
|
|
636
|
+
return nsamples() == 0;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
bool
|
|
640
|
+
Signals::full () const
|
|
641
|
+
{
|
|
642
|
+
uint n = nsamples();
|
|
643
|
+
if (n == 0) return false;
|
|
644
|
+
|
|
645
|
+
return n == capacity();
|
|
572
646
|
}
|
|
573
647
|
|
|
574
648
|
const Sample*
|
data/src/signals.h
CHANGED
|
@@ -26,7 +26,7 @@ namespace Beeps
|
|
|
26
26
|
|
|
27
27
|
Signals Signals_create (
|
|
28
28
|
const float* const* channels,
|
|
29
|
-
uint nsamples, uint nchannels, double sample_rate = 0);
|
|
29
|
+
uint nsamples, uint nchannels, double sample_rate = 0, uint capacity = 0);
|
|
30
30
|
|
|
31
31
|
uint Signals_tick (
|
|
32
32
|
Signals* signals,
|
|
@@ -44,9 +44,13 @@ namespace Beeps
|
|
|
44
44
|
|
|
45
45
|
void Signals_clear (Signals* signals, uint capacity);
|
|
46
46
|
|
|
47
|
-
void Signals_fill (
|
|
47
|
+
void Signals_fill (
|
|
48
|
+
Signals* signals, uint nsamples, Sample value,
|
|
49
|
+
uint offset = 0);
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
void Signals_shift (Signals* signals, uint nsamples);
|
|
52
|
+
|
|
53
|
+
uint Signals_copy (Signals* to, const Signals& from, uint from_offset = 0);
|
|
50
54
|
|
|
51
55
|
void Signals_add ( Signals* signals, const Signals& add);
|
|
52
56
|
|
|
@@ -60,7 +64,9 @@ namespace Beeps
|
|
|
60
64
|
void Signals_write_samples (
|
|
61
65
|
Signals* signals, const SignalSamples<T>& samples, long nsamples = -1);
|
|
62
66
|
|
|
63
|
-
void
|
|
67
|
+
void Signals_set_capacity (Signals* signals, uint capacity);
|
|
68
|
+
|
|
69
|
+
void Signals_set_nsamples (Signals* signals, uint nsamples);
|
|
64
70
|
|
|
65
71
|
Sample* Signals_at ( Signals* signals, uint index, uint channel = 0);
|
|
66
72
|
|
data/src/value.cpp
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#include "beeps/generator.h"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#include <algorithm>
|
|
5
|
+
#include "beeps/exception.h"
|
|
6
|
+
#include "processor.h"
|
|
7
|
+
#include "signals.h"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
namespace Beeps
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
struct Value::Data
|
|
15
|
+
{
|
|
16
|
+
|
|
17
|
+
Type type = TYPE_NONE;
|
|
18
|
+
|
|
19
|
+
PointList points;
|
|
20
|
+
|
|
21
|
+
};// Value::Data
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
Value::Point::Point (float value, float time)
|
|
25
|
+
: value(value), time(time)
|
|
26
|
+
{
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Value::Value (float value, Type type)
|
|
31
|
+
{
|
|
32
|
+
self->type = type;
|
|
33
|
+
set_value(value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Value::~Value ()
|
|
37
|
+
{
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void
|
|
41
|
+
Value::set_type (Type type)
|
|
42
|
+
{
|
|
43
|
+
self->type = type;
|
|
44
|
+
|
|
45
|
+
set_updated();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Value::Type
|
|
49
|
+
Value::type () const
|
|
50
|
+
{
|
|
51
|
+
return self->type;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void
|
|
55
|
+
Value::set_value (float value)
|
|
56
|
+
{
|
|
57
|
+
self->points.clear();
|
|
58
|
+
self->points.push_back(Point(value, 0));
|
|
59
|
+
|
|
60
|
+
set_updated();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void
|
|
64
|
+
Value::insert (float value, float time)
|
|
65
|
+
{
|
|
66
|
+
if (time < 0)
|
|
67
|
+
argument_error(__FILE__, __LINE__, "time must be >= 0");
|
|
68
|
+
|
|
69
|
+
auto& points = self->points;
|
|
70
|
+
auto it = std::find_if(
|
|
71
|
+
points.begin(), points.end(),
|
|
72
|
+
[&](const auto& p) {return time <= p.time;});
|
|
73
|
+
if (it != points.end() && it->time == time)
|
|
74
|
+
{
|
|
75
|
+
if (it->value == value) return;
|
|
76
|
+
it->value = value;
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
points.emplace(it, value, time);
|
|
80
|
+
|
|
81
|
+
set_updated();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
void
|
|
85
|
+
Value::clear ()
|
|
86
|
+
{
|
|
87
|
+
self->points.clear();
|
|
88
|
+
|
|
89
|
+
set_updated();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
Value::iterator
|
|
93
|
+
Value::begin ()
|
|
94
|
+
{
|
|
95
|
+
return self->points.begin();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Value::const_iterator
|
|
99
|
+
Value::begin () const
|
|
100
|
+
{
|
|
101
|
+
return self->points.begin();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
Value::iterator
|
|
105
|
+
Value::end ()
|
|
106
|
+
{
|
|
107
|
+
return self->points.end();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
Value::const_iterator
|
|
111
|
+
Value::end () const
|
|
112
|
+
{
|
|
113
|
+
return self->points.end();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static float
|
|
117
|
+
interpolate_linear (const Value::PointList& points, float time)
|
|
118
|
+
{
|
|
119
|
+
if (points.empty()) return 0;
|
|
120
|
+
if (time <= points[0].time) return points[0].value;
|
|
121
|
+
|
|
122
|
+
for (size_t i = 0; i + 1 < points.size(); ++i)
|
|
123
|
+
{
|
|
124
|
+
const auto& p0 = points[i];
|
|
125
|
+
const auto& p1 = points[i + 1];
|
|
126
|
+
if (time < p1.time)
|
|
127
|
+
{
|
|
128
|
+
float t = (time - p0.time) / (p1.time - p0.time);
|
|
129
|
+
return p0.value + (p1.value - p0.value) * t;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return points.back().value;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static decltype(&interpolate_linear)
|
|
136
|
+
get_interpolate_func (Value::Type type)
|
|
137
|
+
{
|
|
138
|
+
switch (type)
|
|
139
|
+
{
|
|
140
|
+
case Value::LINEAR: return interpolate_linear;
|
|
141
|
+
default: return NULL;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void
|
|
146
|
+
Value::generate (Context* context, Signals* signals, uint* offset)
|
|
147
|
+
{
|
|
148
|
+
Super::generate(context, signals, offset);
|
|
149
|
+
|
|
150
|
+
auto& points = self->points;
|
|
151
|
+
uint nsamples = signals->capacity();
|
|
152
|
+
|
|
153
|
+
if (points.size() == 1)
|
|
154
|
+
Signals_fill(signals, nsamples, points[0].value);
|
|
155
|
+
else
|
|
156
|
+
{
|
|
157
|
+
auto interpolate = get_interpolate_func(self->type);
|
|
158
|
+
if (!interpolate)
|
|
159
|
+
invalid_state_error(__FILE__, __LINE__);
|
|
160
|
+
|
|
161
|
+
double sample_rate = signals->sample_rate();
|
|
162
|
+
Sample* p = Signals_at(signals, 0);
|
|
163
|
+
for (uint i = 0; i < nsamples; ++i)
|
|
164
|
+
p[i] = interpolate(points, (*offset + i) / sample_rate);
|
|
165
|
+
Signals_set_nsamples(signals, nsamples);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
*offset += signals->nsamples();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
int
|
|
172
|
+
Value::max_segment_size_for_process (
|
|
173
|
+
double sample_rate, uint nsamples) const
|
|
174
|
+
{
|
|
175
|
+
if (self->points.size() == 1)
|
|
176
|
+
return Super::max_segment_size_for_process(sample_rate, nsamples);
|
|
177
|
+
return sample_rate / 256;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
}// Beeps
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// -*- c++ -*-
|
|
2
|
+
#include "beeps/generator.h"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#include "beeps/exception.h"
|
|
6
|
+
#include "../signals.h"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
namespace Beeps
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
struct TextIn::Data
|
|
14
|
+
{
|
|
15
|
+
|
|
16
|
+
double sample_rate = 0;
|
|
17
|
+
|
|
18
|
+
};// TextIn::Data
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
TextIn::TextIn (const char* text, double sample_rate)
|
|
22
|
+
{
|
|
23
|
+
if (sample_rate == 0)
|
|
24
|
+
sample_rate = Beeps::sample_rate();
|
|
25
|
+
if (sample_rate <= 0)
|
|
26
|
+
argument_error(__FILE__, __LINE__);
|
|
27
|
+
|
|
28
|
+
self->sample_rate = sample_rate;
|
|
29
|
+
|
|
30
|
+
if (text) synthesize(text);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
TextIn::~TextIn ()
|
|
34
|
+
{
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void
|
|
38
|
+
TextIn::synthesize (const char* text)
|
|
39
|
+
{
|
|
40
|
+
not_implemented_error(__FILE__, __LINE__);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
double
|
|
44
|
+
TextIn::sample_rate () const
|
|
45
|
+
{
|
|
46
|
+
return self->sample_rate;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
TextIn::operator bool () const
|
|
50
|
+
{
|
|
51
|
+
if (!Super::operator bool()) return false;
|
|
52
|
+
return self->sample_rate > 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
void
|
|
56
|
+
TextIn::generate (Context* context, Signals* signals, uint* offset)
|
|
57
|
+
{
|
|
58
|
+
Super::generate(context, signals, offset);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
}// Beeps
|
data/test/test_oscillator.rb
CHANGED
|
@@ -23,12 +23,12 @@ class TestOscillator < Test::Unit::TestCase
|
|
|
23
23
|
def test_offset()
|
|
24
24
|
assert_in_delta 0, get_samples(10000, osc(offset: 0)).sum / 10000
|
|
25
25
|
assert_in_delta 3, get_samples(10000, osc(offset: 3)).sum / 10000
|
|
26
|
-
assert_in_delta
|
|
26
|
+
assert_in_delta(-3, get_samples(10000, osc(offset: -3)).sum / 10000)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def test_gain()
|
|
30
30
|
assert_in_delta 3, get_samples(100, osc(gain: 3)).max
|
|
31
|
-
assert_in_delta
|
|
31
|
+
assert_in_delta(-3, get_samples(100, osc(gain: 3)).min)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def test_offset_and_gain()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require_relative 'helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TestSequencer < Test::Unit::TestCase
|
|
5
|
+
|
|
6
|
+
B = Beeps
|
|
7
|
+
|
|
8
|
+
def seq(&b)
|
|
9
|
+
B::Sequencer.new.tap {b.call _1}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def osc(type = :sine, samples: nil, freq: 1, **kwargs)
|
|
13
|
+
B::Oscillator.new(type, samples: samples, freq: freq, **kwargs)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_each_note()
|
|
17
|
+
assert_equal(
|
|
18
|
+
[[B::Oscillator, 0, 1]],
|
|
19
|
+
seq {_1.add osc, 0, 1}.map {|p, *args| [p.class, *args]})
|
|
20
|
+
|
|
21
|
+
assert_equal [0], seq {_1.add osc, 0, 1} .map {_2}
|
|
22
|
+
assert_equal [0, 2], seq {_1.add osc, 0, 1; _1.add osc, 2, 3}.map {_2}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end# TestSequencer
|
data/test/test_value.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require_relative 'helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TestValue < Test::Unit::TestCase
|
|
5
|
+
|
|
6
|
+
B = Beeps
|
|
7
|
+
|
|
8
|
+
def val(...) = B::Value.new(...)
|
|
9
|
+
|
|
10
|
+
def test_constant()
|
|
11
|
+
assert_each_in_delta [5] * 3, get_samples(2, val(5))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_linear_interpolation()
|
|
15
|
+
v = val 0
|
|
16
|
+
v.insert 2, 1
|
|
17
|
+
v.insert 1, 2
|
|
18
|
+
assert_each_in_delta [0, 1, 2, 1.5, 1], get_samples(2, v, seconds: 2)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_insert()
|
|
22
|
+
v = val 0
|
|
23
|
+
v.insert 1, 1
|
|
24
|
+
assert_equal [[0, 0], [1, 1]], v.to_a
|
|
25
|
+
|
|
26
|
+
v.insert 2, 1
|
|
27
|
+
assert_equal [[0, 0], [2, 1]], v.to_a
|
|
28
|
+
|
|
29
|
+
assert_raise(ArgumentError) {v.insert 1, -1}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_clear()
|
|
33
|
+
v = val 0
|
|
34
|
+
assert_equal 1, v.to_a.size
|
|
35
|
+
|
|
36
|
+
v.clear
|
|
37
|
+
assert_equal 0, v.to_a.size
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_each()
|
|
41
|
+
v = val 0
|
|
42
|
+
v.insert 1, 1
|
|
43
|
+
v.insert 2, 2
|
|
44
|
+
assert_equal [[0, 0], [1, 1], [2, 2]], v.to_a
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end# TestValue
|