beeps 0.3.3 → 0.3.5

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/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
  {
data/src/processor.cpp CHANGED
@@ -14,7 +14,7 @@ namespace Beeps
14
14
  struct Processor::Data
15
15
  {
16
16
 
17
- bool generator = false;
17
+ bool generator = false, started = false;
18
18
 
19
19
  float buffering_seconds = 0;
20
20
 
@@ -22,11 +22,6 @@ namespace Beeps
22
22
 
23
23
  Processor::Ref input;
24
24
 
25
- bool has_generator () const
26
- {
27
- return generator || (input && input->self->has_generator());
28
- }
29
-
30
25
  };// Processor::Data
31
26
 
32
27
 
@@ -57,6 +52,7 @@ namespace Beeps
57
52
  void
58
53
  Processor::reset ()
59
54
  {
55
+ self->started = false;
60
56
  if (self->input) self->input->reset();
61
57
 
62
58
  set_updated();
@@ -79,6 +75,11 @@ namespace Beeps
79
75
  return self->input;
80
76
  }
81
77
 
78
+ void
79
+ Processor::on_start ()
80
+ {
81
+ }
82
+
82
83
  const Processor*
83
84
  Processor::input () const
84
85
  {
@@ -87,7 +88,7 @@ namespace Beeps
87
88
 
88
89
  Processor::operator bool () const
89
90
  {
90
- return self->has_generator();
91
+ return self->generator || (self->input && *self->input);
91
92
  }
92
93
 
93
94
  bool
@@ -99,6 +100,12 @@ namespace Beeps
99
100
  void
100
101
  Processor::process (Context* context, Signals* signals, uint* offset)
101
102
  {
103
+ if (!self->started)
104
+ {
105
+ self->started = true;
106
+ on_start();
107
+ }
108
+
102
109
  if (self->generator)
103
110
  generate(context, signals, offset);
104
111
  else
data/src/signals.cpp CHANGED
@@ -216,6 +216,24 @@ namespace Beeps
216
216
  return resample_frames(to, from, from_offset);
217
217
  }
218
218
 
219
+ void
220
+ Signals_add (Signals* signals, const Signals& add)
221
+ {
222
+ if (!signals)
223
+ argument_error(__FILE__, __LINE__);
224
+ if (signals->nchannels() != add.nchannels())
225
+ argument_error(__FILE__, __LINE__);
226
+
227
+ Frames* sigf = Signals_get_frames(signals);
228
+ Frames* addf = Signals_get_frames(const_cast<Signals*>(&add));
229
+ Float* sigp = &(*sigf)(0, 0);
230
+ Float* addp = &(*addf)(0, 0);
231
+ uint nframes = std::min(sigf->nframes(), addf->nframes());
232
+
233
+ for (uint i = 0; i < nframes; ++i, ++sigp, ++addp)
234
+ *sigp += *addp;
235
+ }
236
+
219
237
  void
220
238
  Signals_multiply (Signals* signals, const Signals& multiplier)
221
239
  {
@@ -226,16 +244,16 @@ namespace Beeps
226
244
  if (signals->capacity() != multiplier.capacity())
227
245
  argument_error(__FILE__, __LINE__);
228
246
 
229
- Frames* sigf = Signals_get_frames(signals);
230
- Frames* mulf = Signals_get_frames(const_cast<Signals*>(&multiplier));
231
- uint nframes = sigf->nframes();
232
- uint stride = sigf->nchannels();
247
+ Frames* sigf = Signals_get_frames(signals);
248
+ Frames* mulf = Signals_get_frames(const_cast<Signals*>(&multiplier));
249
+ uint nchannels = sigf->nchannels();
250
+ uint nframes = sigf->nframes();
233
251
 
234
- for (uint ch = 0; ch < sigf->nchannels(); ++ch)
252
+ for (uint ch = 0; ch < nchannels; ++ch)
235
253
  {
236
254
  Float* sigp = &(*sigf)(0, ch);
237
255
  Float* mulp = &(*mulf)(0, 0);
238
- for (uint i = 0; i < nframes; ++i, sigp += stride, ++mulp)
256
+ for (uint i = 0; i < nframes; i += nchannels, sigp += nchannels, ++mulp)
239
257
  *sigp *= *mulp;
240
258
  }
241
259
  }
data/src/signals.h CHANGED
@@ -39,6 +39,8 @@ namespace Beeps
39
39
 
40
40
  uint Signals_copy (Signals* to, const Signals& from, uint from_offset);
41
41
 
42
+ void Signals_add ( Signals* signals, const Signals& add);
43
+
42
44
  void Signals_multiply (Signals* signals, const Signals& multiplier);
43
45
 
44
46
  template <typename T>
@@ -63,7 +65,7 @@ namespace Beeps
63
65
 
64
66
  public:
65
67
 
66
- Frames (unsigned int nframes = 0, unsigned int nchannels = 0)
68
+ Frames (unsigned int nframes = 0, unsigned int nchannels = 1)
67
69
  : stk::StkFrames(nframes, nchannels)
68
70
  {
69
71
  }
@@ -96,6 +98,16 @@ namespace Beeps
96
98
  nFrames_ = saved_nFrames_;
97
99
  size_ = saved_size_;
98
100
  bufferSize_ = saved_bufferSize_;
101
+
102
+ saved_data_ = NULL;
103
+ saved_nFrames_ = 0;
104
+ saved_size_ = 0;
105
+ saved_bufferSize_ = 0;
106
+ }
107
+
108
+ uint sample_rate () const
109
+ {
110
+ return dataRate();
99
111
  }
100
112
 
101
113
  uint nchannels () const
@@ -34,7 +34,7 @@ class TestProcessor < Test::Unit::TestCase
34
34
  assert_equal gain1, gain2.input
35
35
  end
36
36
 
37
- def test_shift_left()
37
+ def _test_shift_left()
38
38
  osc = B::Oscillator.new
39
39
  gain1 = B::Gain.new
40
40
  gain2 = B::Gain.new
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beeps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - xordog
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-22 00:00:00.000000000 Z
11
+ date: 2025-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: xot
@@ -16,40 +16,40 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.3.3
19
+ version: 0.3.5
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 0.3.3
22
+ version: 0.3.5
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: 0.3.3
29
+ version: 0.3.5
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.3.3
32
+ version: 0.3.5
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rucy
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.3.3
39
+ version: 0.3.5
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 0.3.3
42
+ version: 0.3.5
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: 0.3.3
49
+ version: 0.3.5
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 0.3.3
52
+ version: 0.3.5
53
53
  description: Synthesize and play beep sounds.
54
54
  email: xordog@gmail.com
55
55
  executables: []
@@ -63,6 +63,7 @@ extra_rdoc_files:
63
63
  - ".doc/ext/beeps/file_in.cpp"
64
64
  - ".doc/ext/beeps/gain.cpp"
65
65
  - ".doc/ext/beeps/mic_in.cpp"
66
+ - ".doc/ext/beeps/mixer.cpp"
66
67
  - ".doc/ext/beeps/native.cpp"
67
68
  - ".doc/ext/beeps/oscillator.cpp"
68
69
  - ".doc/ext/beeps/pitch_shift.cpp"
@@ -79,6 +80,7 @@ files:
79
80
  - ".doc/ext/beeps/file_in.cpp"
80
81
  - ".doc/ext/beeps/gain.cpp"
81
82
  - ".doc/ext/beeps/mic_in.cpp"
83
+ - ".doc/ext/beeps/mixer.cpp"
82
84
  - ".doc/ext/beeps/native.cpp"
83
85
  - ".doc/ext/beeps/oscillator.cpp"
84
86
  - ".doc/ext/beeps/pitch_shift.cpp"
@@ -87,10 +89,12 @@ files:
87
89
  - ".doc/ext/beeps/sound.cpp"
88
90
  - ".doc/ext/beeps/sound_player.cpp"
89
91
  - ".doc/ext/beeps/time_stretch.cpp"
92
+ - ".github/PULL_REQUEST_TEMPLATE.md"
90
93
  - ".github/workflows/release-gem.yml"
91
94
  - ".github/workflows/tag.yml"
92
95
  - ".github/workflows/test.yml"
93
96
  - ".github/workflows/utils.rb"
97
+ - CONTRIBUTING.md
94
98
  - ChangeLog.md
95
99
  - Gemfile
96
100
  - Gemfile.lock
@@ -108,6 +112,7 @@ files:
108
112
  - ext/beeps/file_in.cpp
109
113
  - ext/beeps/gain.cpp
110
114
  - ext/beeps/mic_in.cpp
115
+ - ext/beeps/mixer.cpp
111
116
  - ext/beeps/native.cpp
112
117
  - ext/beeps/oscillator.cpp
113
118
  - ext/beeps/pitch_shift.cpp
@@ -150,6 +155,7 @@ files:
150
155
  - src/gain.cpp
151
156
  - src/mic_in.cpp
152
157
  - src/mic_in.h
158
+ - src/mixer.cpp
153
159
  - src/openal.cpp
154
160
  - src/openal.h
155
161
  - src/oscillator.cpp
@@ -178,7 +184,8 @@ files:
178
184
  homepage: https://github.com/xord/beeps
179
185
  licenses:
180
186
  - MIT
181
- metadata: {}
187
+ metadata:
188
+ msys2_mingw_dependencies: openal
182
189
  post_install_message:
183
190
  rdoc_options: []
184
191
  require_paths: