beeps 0.3.2 → 0.3.4

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.
@@ -1,6 +1,7 @@
1
1
  require 'xot/setter'
2
2
  require 'xot/const_symbol_accessor'
3
3
  require 'xot/universal_accessor'
4
+ require 'xot/hookable'
4
5
  require 'xot/block_util'
5
6
  require 'beeps/ext'
6
7
 
@@ -11,55 +12,76 @@ module Beeps
11
12
  class Processor
12
13
 
13
14
  include Xot::Setter
15
+ include Xot::Hookable
14
16
 
15
- def initialize(**options, &block)
17
+ def initialize(*inputs, **options, &block)
16
18
  super()
19
+ add_input(*inputs)
17
20
  set options unless options.empty?
18
21
  Xot::BlockUtil.instance_eval_or_block_call self, &block if block
19
22
  end
20
23
 
21
- def >>(o)
22
- o.input = self
23
- o
24
+ universal_accessor :input
25
+
26
+ def add_input(*inputs)
27
+ last = inputs.flatten.compact.last
28
+ self.input = last if last
24
29
  end
25
30
 
26
- def <<(o)
27
- self.input = o
28
- o
31
+ def >>(processor)
32
+ processor.add_input self
33
+ processor
29
34
  end
30
35
 
31
- universal_accessor :input
36
+ #def <<(processors)
37
+ # self.add_input(*processors)
38
+ # self
39
+ #end
32
40
 
33
41
  end# Processor
34
42
 
35
43
 
36
44
  class Oscillator
37
45
 
46
+ include Enumerable
47
+
38
48
  const_symbol_accessor :type, **{
39
49
  none: TYPE_NONE,
40
50
  sine: SINE,
41
51
  triangle: TRIANGLE,
42
52
  square: SQUARE,
43
- sawtooth: SAWTOOTH
53
+ sawtooth: SAWTOOTH,
54
+ noise: NOISE,
55
+ samples: SAMPLES
44
56
  }
45
57
 
46
- def initialize(type = :sine, *args, **kwargs, &block)
47
- super(*args, **kwargs, &block)
48
- self.type = type
58
+ def initialize(type = :sine, samples: nil, **kwargs, &block)
59
+ super(**kwargs, &block)
60
+ if samples
61
+ self.samples = samples
62
+ else
63
+ self.type = type
64
+ end
49
65
  end
50
66
 
67
+ universal_accessor :type, :frequency, :phase
68
+
51
69
  alias freq= frequency=
52
70
  alias freq frequency
53
71
 
54
- universal_accessor :type, :frequency, :freq
72
+ def each_sample(&block)
73
+ block ? each_sample!(&block) : enum_for(:each_sample!)
74
+ end
75
+
76
+ alias each each_sample
55
77
 
56
78
  end# Oscillator
57
79
 
58
80
 
59
81
  class FileIn
60
82
 
61
- def initialize(path = nil, *args, **kwargs, &block)
62
- super(*args, **kwargs, &block)
83
+ def initialize(path = nil, **kwargs, &block)
84
+ super(**kwargs, &block)
63
85
  self.path = path if path
64
86
  end
65
87
 
@@ -70,13 +92,50 @@ module Beeps
70
92
 
71
93
  class Gain
72
94
 
95
+ def initialize(gain = 1, **kwargs, &block)
96
+ super(gain: gain, **kwargs, &block)
97
+ end
98
+
73
99
  universal_accessor :gain
74
100
 
75
101
  end# Gain
76
102
 
77
103
 
104
+ class Mixer
105
+
106
+ include Enumerable
107
+
108
+ def add_input(*inputs)
109
+ add_input! inputs.flatten.compact
110
+ end
111
+
112
+ def remove_input(*inputs)
113
+ remove_input! inputs.flatten.compact
114
+ end
115
+
116
+ def each_input(&block)
117
+ block ? each_input!(&block) : enum_for(:each_input!)
118
+ end
119
+
120
+ alias each each_input
121
+
122
+ end# Mixer
123
+
124
+
78
125
  class Envelope
79
126
 
127
+ def initialize(
128
+ attack = nil, decay = nil, sustain = nil, release = nil,
129
+ *args, **kwargs, &block)
130
+
131
+ attack_time attack if attack
132
+ decay_time decay if decay
133
+ sustain_level sustain if sustain
134
+ release_time release if release
135
+
136
+ super(*args, **kwargs, &block)
137
+ end
138
+
80
139
  def note_on(delay = 0)
81
140
  note_on! delay
82
141
  end
@@ -115,6 +174,8 @@ module Beeps
115
174
 
116
175
  class Analyser
117
176
 
177
+ universal_accessor :fft_size
178
+
118
179
  def each_signal(nsamples = fft_size, &block)
119
180
  return enum_for(:each_signal, nsamples) unless block
120
181
  each_signal!(nsamples, &block)
@@ -125,8 +186,6 @@ module Beeps
125
186
  each_spectrum!(&block)
126
187
  end
127
188
 
128
- universal_accessor :fft_size
129
-
130
189
  end# Analyser
131
190
 
132
191
 
data/src/envelope.cpp CHANGED
@@ -11,6 +11,9 @@ namespace Beeps
11
11
  {
12
12
 
13
13
 
14
+ static const float TIME_ZERO = 0.0000001;
15
+
16
+
14
17
  struct Envelope::Data
15
18
  {
16
19
 
@@ -18,16 +21,19 @@ namespace Beeps
18
21
 
19
22
  Signals adsr_signals;
20
23
 
21
- float attack_time = 0, decay_time = 0, sustain_level = 1, release_time = 0;
24
+ float attack_time = 0.005;
25
+ float decay_time = 0.005;
26
+ float sustain_level = 1;
27
+ float release_time = 0.005;
22
28
 
23
29
  float time = 0, note_on_time = -1, note_off_time = -1;
24
30
 
25
31
  void update_envelope ()
26
32
  {
27
- adsr.setAttackTime( attack_time == 0 ? 0.01 : attack_time);
28
33
  adsr.setSustainLevel(sustain_level);
29
- adsr.setDecayTime( decay_time == 0 ? 0.01 : decay_time);
30
- adsr.setReleaseTime( release_time == 0 ? 0.01 : release_time);
34
+ adsr.setAttackTime( attack_time == 0 ? TIME_ZERO : attack_time);
35
+ adsr.setDecayTime( decay_time == 0 ? TIME_ZERO : decay_time);
36
+ adsr.setReleaseTime(release_time == 0 ? TIME_ZERO : release_time);
31
37
  }
32
38
 
33
39
  };// Envelope::Data
@@ -167,6 +173,9 @@ namespace Beeps
167
173
  Frames* frames = Signals_get_frames(signals);
168
174
  assert(frames);
169
175
 
176
+ if (self->time == 0 && self->attack_time == 0)
177
+ self->adsr.setValue(self->sustain_level);// skip attack phase
178
+
170
179
  float start = self->time;
171
180
  float end = start + Signals_get_seconds(*signals);
172
181
  self->time = end;
@@ -175,7 +184,7 @@ namespace Beeps
175
184
  float off = self->note_off_time;
176
185
  assert(on <= off);
177
186
 
178
- bool has_on = 0 <= on && start <= on && on < end;
187
+ bool has_on = 0 <= on && start <= on && on < end;
179
188
  bool has_off = 0 <= off && start <= off && off < end;
180
189
 
181
190
  if (!has_on && !has_off)
data/src/mixer.cpp ADDED
@@ -0,0 +1,112 @@
1
+ #include "beeps/filter.h"
2
+
3
+
4
+ #include <algorithm>
5
+ #include <vector>
6
+ #include "processor.h"
7
+ #include "signals.h"
8
+
9
+
10
+ namespace Beeps
11
+ {
12
+
13
+
14
+ struct Mixer::Data
15
+ {
16
+
17
+ std::vector<Processor::Ref> inputs;
18
+
19
+ };// Mixer::Data
20
+
21
+
22
+ Mixer::Mixer (Processor* input)
23
+ {
24
+ if (input) add_input(input);
25
+ }
26
+
27
+ Mixer::~Mixer ()
28
+ {
29
+ }
30
+
31
+ void
32
+ Mixer::add_input (Processor* input)
33
+ {
34
+ auto it = std::find(self->inputs.begin(), self->inputs.end(), input);
35
+ if (it != self->inputs.end()) return;
36
+
37
+ self->inputs.emplace_back(input);
38
+
39
+ set_updated();
40
+ }
41
+
42
+ void
43
+ Mixer::remove_input (Processor* input)
44
+ {
45
+ auto it = std::find(self->inputs.begin(), self->inputs.end(), input);
46
+ if (it == self->inputs.end()) return;
47
+
48
+ self->inputs.erase(it);
49
+
50
+ set_updated();
51
+ }
52
+
53
+ Mixer::iterator
54
+ Mixer::begin ()
55
+ {
56
+ return self->inputs.begin();
57
+ }
58
+
59
+ Mixer::const_iterator
60
+ Mixer::begin () const
61
+ {
62
+ return self->inputs.begin();
63
+ }
64
+
65
+ Mixer::iterator
66
+ Mixer::end ()
67
+ {
68
+ return self->inputs.end();
69
+ }
70
+
71
+ Mixer::const_iterator
72
+ Mixer::end () const
73
+ {
74
+ return self->inputs.end();
75
+ }
76
+
77
+ void
78
+ Mixer::filter (Context* context, Signals* signals, uint* offset)
79
+ {
80
+ Super::filter(context, signals, offset);
81
+
82
+ Signals_resize(signals, signals->capacity(), 0);
83
+
84
+ Signals sig = Signals_create(signals->capacity(), signals->nchannels());
85
+ uint min_size = signals->capacity();
86
+ for (auto& input : self->inputs)
87
+ {
88
+ Signals_clear(&sig);
89
+
90
+ uint sig_offset = *offset;
91
+ Processor_get_context(context)->process(input, &sig, &sig_offset);
92
+
93
+ uint size = sig_offset - *offset;
94
+ if (size < min_size) min_size = size;
95
+
96
+ Signals_add(signals, sig);
97
+ }
98
+
99
+ *offset += min_size;
100
+ }
101
+
102
+ Mixer::operator bool () const
103
+ {
104
+ if (self->inputs.empty()) return false;
105
+
106
+ for (auto& input : self->inputs)
107
+ if (!*input) return false;
108
+ return true;
109
+ }
110
+
111
+
112
+ }// Beeps
data/src/oscillator.cpp CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
 
4
4
  #include <assert.h>
5
+ #include <cmath>
6
+ #include <vector>
5
7
  #include "SineWave.h"
6
8
  #include "Blit.h"
7
9
  #include "BlitSquare.h"
@@ -14,6 +16,42 @@ namespace Beeps
14
16
  {
15
17
 
16
18
 
19
+ class SineWave : public stk::SineWave
20
+ {
21
+
22
+ public:
23
+
24
+ void setPhase (stk::StkFloat phase)
25
+ {
26
+ time_ = std::fmod(phase, 1.f) * TABLE_SIZE;
27
+ }
28
+
29
+ stk::StkFloat getPhase () const
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
53
+
54
+
17
55
  class Osc
18
56
  {
19
57
 
@@ -27,10 +65,14 @@ namespace Beeps
27
65
 
28
66
  virtual void set_frequency (float freq) = 0;
29
67
 
68
+ virtual void set_phase (float phase) = 0;
69
+
70
+ virtual float phase () const = 0;
71
+
30
72
  };// Osc
31
73
 
32
74
 
33
- template <typename OSC>
75
+ template <typename OSC, uint DROP_MSEC>
34
76
  class StkOsc : public Osc
35
77
  {
36
78
 
@@ -39,10 +81,18 @@ namespace Beeps
39
81
  void reset () override
40
82
  {
41
83
  osc.reset();
84
+ drop_msec = DROP_MSEC;
42
85
  }
43
86
 
44
87
  void tick (Frames* frames) override
45
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
+
46
96
  osc.tick(*frames);
47
97
  }
48
98
 
@@ -51,21 +101,33 @@ namespace Beeps
51
101
  osc.setFrequency(freq);
52
102
  }
53
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
+
54
114
  protected:
55
115
 
56
116
  OSC osc;
57
117
 
118
+ uint drop_msec = DROP_MSEC;
119
+
58
120
  };// StkOsc
59
121
 
60
122
 
61
- typedef StkOsc<stk::SineWave> SineOsc;
123
+ typedef StkOsc<SineWave, 0> SineOsc;
62
124
 
63
- typedef StkOsc<stk::BlitSquare> SquareOsc;
125
+ typedef StkOsc<stk::BlitSquare, 100> SquareOsc;
64
126
 
65
- typedef StkOsc<stk::BlitSaw> SawtoothOsc;
127
+ typedef StkOsc<BlitSaw, 200> SawtoothOsc;
66
128
 
67
129
 
68
- class TriangleOsc : public StkOsc<stk::Blit>
130
+ class TriangleOsc : public StkOsc<stk::Blit, 0>
69
131
  {
70
132
 
71
133
  public:
@@ -78,6 +140,164 @@ namespace Beeps
78
140
  };// TriangleOsc
79
141
 
80
142
 
143
+ class NoiseOsc : public Osc
144
+ {
145
+
146
+ public:
147
+
148
+ void reset () override
149
+ {
150
+ time = 0;
151
+ }
152
+
153
+ void tick (Frames* frames) override
154
+ {
155
+ if (0 < freq && (freq * 2) <= frames->sample_rate())
156
+ tick_with_freq(frames);
157
+ else
158
+ tick_without_freq(frames);
159
+ }
160
+
161
+ void set_frequency (float freq) override
162
+ {
163
+ this->freq = freq;
164
+ }
165
+
166
+ void set_phase (float phase) override
167
+ {
168
+ time = freq == 0 ? 0 : phase * (1.f / freq);
169
+ }
170
+
171
+ float phase () const override
172
+ {
173
+ return freq == 0 ? 0 : time / (1.f / freq);
174
+ }
175
+
176
+ private:
177
+
178
+ float freq = 0;
179
+
180
+ double time = 0;
181
+
182
+ void tick_without_freq (Frames* frames)
183
+ {
184
+ uint nchannels = frames->nchannels();
185
+ uint nframes = frames->nframes();
186
+ Float* pframe = &(*frames)(0, 0);
187
+ for (uint i = 0; i < nframes; ++i, ++pframe)
188
+ {
189
+ uint ch = i % nchannels;
190
+ *pframe = ch == 0 ? noise() : pframe[-ch];
191
+ }
192
+ }
193
+
194
+ void tick_with_freq (Frames* frames)
195
+ {
196
+ float time_per_sample = 1.f / frames->sample_rate();
197
+ float time_per_freq = 1.f / (freq * 2);
198
+
199
+ uint nchannels = frames->nchannels();
200
+ uint nframes = frames->nframes();
201
+ Float* pframe = &(*frames)(0, 0);
202
+ float value = noise();
203
+ for (uint i = 0; i < nframes; ++i, ++pframe)
204
+ {
205
+ if (i % nchannels == 0)
206
+ {
207
+ *pframe = value;
208
+
209
+ time += time_per_sample;
210
+ while (time >= time_per_freq)
211
+ {
212
+ value = noise();
213
+ time -= time_per_freq;
214
+ }
215
+ }
216
+ else
217
+ *pframe = value;
218
+ }
219
+ }
220
+
221
+ double noise () const
222
+ {
223
+ return rand() / ((double) RAND_MAX + 1) * 2 - 1;
224
+ }
225
+
226
+ };// NoiseOsc
227
+
228
+
229
+ class WaveformOsc : public Osc
230
+ {
231
+
232
+ public:
233
+
234
+ typedef std::vector<float> Table;
235
+
236
+ WaveformOsc (float* samples, size_t nsamples, float frequency)
237
+ : table(samples, samples + nsamples), freq(frequency), time(0)
238
+ {
239
+ }
240
+
241
+ void reset () override
242
+ {
243
+ time = 0;
244
+ }
245
+
246
+ void tick (Frames* frames) override
247
+ {
248
+ size_t size = table.size();
249
+ float dt = size * freq / frames->sample_rate();
250
+
251
+ uint nchannels = frames->nchannels();
252
+ uint nframes = frames->nframes();
253
+ Float* pframe = &(*frames)(0, 0);
254
+ for (uint i = 0; i < nframes; ++i, ++pframe)
255
+ {
256
+ uint ch = i % nchannels;
257
+ if (ch == 0)
258
+ {
259
+ size_t index0 = (size_t) time;
260
+ size_t index1 = index0 == size - 1 ? 0 : index0 + 1;
261
+ float frac = time - index0;
262
+ *pframe = table[index0] * (1.f - frac) + table[index1] * frac;
263
+
264
+ time += dt;
265
+ while (time >= size) time -= size;
266
+ }
267
+ else
268
+ *pframe = pframe[-ch];
269
+ }
270
+ }
271
+
272
+ void set_frequency (float freq) override
273
+ {
274
+ this->freq = freq;
275
+ }
276
+
277
+ void set_phase (float phase) override
278
+ {
279
+ this->time = std::fmod(phase, 1.f) * table.size();
280
+ }
281
+
282
+ float phase () const override
283
+ {
284
+ return time / table.size();
285
+ }
286
+
287
+ const Table& samples () const
288
+ {
289
+ return table;
290
+ }
291
+
292
+ private:
293
+
294
+ Table table;
295
+
296
+ float freq, time;
297
+
298
+ };// WaveformOsc
299
+
300
+
81
301
  struct Oscillator::Data
82
302
  {
83
303
 
@@ -95,6 +315,11 @@ namespace Beeps
95
315
  set_type(type);
96
316
  }
97
317
 
318
+ Oscillator::Oscillator (float* samples, size_t size)
319
+ {
320
+ set_samples(samples, size);
321
+ }
322
+
98
323
  Oscillator::~Oscillator ()
99
324
  {
100
325
  }
@@ -111,6 +336,8 @@ namespace Beeps
111
336
  {
112
337
  if (type == self->type) return;
113
338
 
339
+ float phase = self->osc ? self->osc->phase() : 0;
340
+
114
341
  self->type = type;
115
342
  self->osc.reset();
116
343
 
@@ -120,12 +347,15 @@ namespace Beeps
120
347
  case TRIANGLE: self->osc.reset(new TriangleOsc()); break;
121
348
  case SQUARE: self->osc.reset(new SquareOsc()); break;
122
349
  case SAWTOOTH: self->osc.reset(new SawtoothOsc()); break;
350
+ case NOISE: self->osc.reset(new NoiseOsc()); break;
123
351
  default:
124
352
  argument_error(
125
353
  __FILE__, __LINE__, "unknown oscilator type '%d'", self->type);
126
354
  break;
127
355
  }
128
356
 
357
+ self->osc->set_phase(phase);
358
+
129
359
  set_updated();
130
360
  }
131
361
 
@@ -135,6 +365,38 @@ namespace Beeps
135
365
  return self->type;
136
366
  }
137
367
 
368
+ void
369
+ Oscillator::set_samples (float* samples, size_t size)
370
+ {
371
+ float phase = self->osc ? self->osc->phase() : 0;
372
+
373
+ self->type = SAMPLES;
374
+ self->osc.reset(new WaveformOsc(samples, size, frequency()));
375
+ self->osc->set_phase(phase);
376
+
377
+ set_updated();
378
+ }
379
+
380
+ const float*
381
+ Oscillator::samples () const
382
+ {
383
+ if (self->type != SAMPLES)
384
+ return NULL;
385
+
386
+ auto* osc = (const WaveformOsc*) self->osc.get();
387
+ return &osc->samples()[0];
388
+ }
389
+
390
+ size_t
391
+ Oscillator::nsamples () const
392
+ {
393
+ if (self->type != SAMPLES)
394
+ return 0;
395
+
396
+ auto* osc = (WaveformOsc*) self->osc.get();
397
+ return osc->samples().size();
398
+ }
399
+
138
400
  void
139
401
  Oscillator::set_frequency (float frequency)
140
402
  {
@@ -142,7 +404,6 @@ namespace Beeps
142
404
  argument_error(__FILE__, __LINE__);
143
405
 
144
406
  self->frequency = frequency;
145
-
146
407
  set_updated();
147
408
  }
148
409
 
@@ -152,6 +413,19 @@ namespace Beeps
152
413
  return self->frequency;
153
414
  }
154
415
 
416
+ void
417
+ Oscillator::set_phase (float phase)
418
+ {
419
+ self->osc->set_phase(phase);
420
+ set_updated();
421
+ }
422
+
423
+ float
424
+ Oscillator::phase () const
425
+ {
426
+ return self->osc->phase();
427
+ }
428
+
155
429
  void
156
430
  Oscillator::generate (Context* context, Signals* signals, uint* offset)
157
431
  {