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.
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
- struct Note
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 = Signals_create(nsamples, nchannels, sample_rate);
125
- s.self->nsamples = nsamples;
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
- Signals_fill (Signals* signals, uint nsamples, Sample value)
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
- Signals_set_nsamples(signals, nsamples);
212
+ signals->self->frames->resize(capacity, signals->nchannels());
213
+ }
224
214
 
225
- Sample* p = Signals_at(signals, 0);
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 self->nsamples == 0;
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 (Signals* signals, uint nsamples, Sample value);
47
+ void Signals_fill (
48
+ Signals* signals, uint nsamples, Sample value,
49
+ uint offset = 0);
48
50
 
49
- uint Signals_copy (Signals* to, const Signals& from, uint from_offset);
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 Signals_set_nsamples (Signals* signals, uint nsamples);
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
@@ -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 -3, get_samples(10000, osc(offset: -3)).sum / 10000
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 -3, get_samples(100, osc(gain: 3)).min
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
@@ -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