beeps 0.1.31 → 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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/beeps/adsr.cpp +139 -0
  3. data/.doc/ext/beeps/analyser.cpp +128 -0
  4. data/.doc/ext/beeps/beeps.cpp +9 -1
  5. data/.doc/ext/beeps/file_in.cpp +55 -9
  6. data/.doc/ext/beeps/gain.cpp +64 -0
  7. data/.doc/ext/beeps/mic_in.cpp +83 -0
  8. data/.doc/ext/beeps/native.cpp +20 -8
  9. data/.doc/ext/beeps/oscillator.cpp +88 -0
  10. data/.doc/ext/beeps/pitch_shift.cpp +64 -0
  11. data/.doc/ext/beeps/processor.cpp +31 -2
  12. data/.doc/ext/beeps/sound.cpp +90 -7
  13. data/.doc/ext/beeps/sound_player.cpp +156 -0
  14. data/.doc/ext/beeps/time_stretch.cpp +64 -0
  15. data/.github/workflows/release-gem.yml +62 -0
  16. data/.github/workflows/test.yml +0 -6
  17. data/.github/workflows/utils.rb +13 -5
  18. data/ChangeLog.md +13 -0
  19. data/Rakefile +27 -6
  20. data/VERSION +1 -1
  21. data/beeps.gemspec +2 -2
  22. data/ext/beeps/adsr.cpp +150 -0
  23. data/ext/beeps/analyser.cpp +134 -0
  24. data/ext/beeps/beeps.cpp +10 -1
  25. data/ext/beeps/extconf.rb +1 -2
  26. data/ext/beeps/file_in.cpp +60 -9
  27. data/ext/beeps/gain.cpp +67 -0
  28. data/ext/beeps/mic_in.cpp +88 -0
  29. data/ext/beeps/native.cpp +20 -8
  30. data/ext/beeps/oscillator.cpp +93 -0
  31. data/ext/beeps/pitch_shift.cpp +67 -0
  32. data/ext/beeps/processor.cpp +34 -2
  33. data/ext/beeps/sound.cpp +99 -7
  34. data/ext/beeps/sound_player.cpp +169 -0
  35. data/ext/beeps/time_stretch.cpp +67 -0
  36. data/include/beeps/beeps.h +2 -1
  37. data/include/beeps/filter.h +179 -0
  38. data/include/beeps/generator.h +120 -0
  39. data/include/beeps/processor.h +37 -68
  40. data/include/beeps/ruby/filter.h +78 -0
  41. data/include/beeps/ruby/generator.h +60 -0
  42. data/include/beeps/ruby/processor.h +5 -45
  43. data/include/beeps/ruby/sound.h +14 -3
  44. data/include/beeps/signals.h +10 -4
  45. data/include/beeps/sound.h +67 -2
  46. data/lib/beeps/beeps.rb +6 -1
  47. data/lib/beeps/processor.rb +95 -15
  48. data/lib/beeps/sound.rb +29 -2
  49. data/src/adsr.cpp +245 -0
  50. data/src/analyser.cpp +254 -0
  51. data/src/beeps.cpp +11 -2
  52. data/src/file_in.cpp +94 -0
  53. data/src/gain.cpp +55 -0
  54. data/src/mic_in.cpp +262 -0
  55. data/src/mic_in.h +20 -0
  56. data/src/openal.cpp +2 -1
  57. data/src/oscillator.cpp +145 -0
  58. data/src/osx/signals.mm +83 -0
  59. data/src/pitch_shift.cpp +82 -0
  60. data/src/processor.cpp +202 -88
  61. data/src/processor.h +98 -0
  62. data/src/signals.cpp +326 -20
  63. data/src/signals.h +192 -2
  64. data/src/sound.cpp +735 -113
  65. data/src/sound.h +6 -1
  66. data/src/time_stretch.cpp +91 -0
  67. data/test/helper.rb +2 -1
  68. data/test/test_beeps.rb +10 -7
  69. data/test/test_beeps_init.rb +18 -0
  70. data/test/test_file_in.rb +15 -0
  71. data/test/test_processor.rb +50 -0
  72. data/test/test_sound.rb +87 -11
  73. data/test/test_sound_player.rb +134 -0
  74. metadata +55 -17
  75. data/.doc/ext/beeps/sawtooth_wave.cpp +0 -61
  76. data/.doc/ext/beeps/sine_wave.cpp +0 -61
  77. data/.doc/ext/beeps/square_wave.cpp +0 -61
  78. data/.github/workflows/release.yml +0 -34
  79. data/ext/beeps/sawtooth_wave.cpp +0 -64
  80. data/ext/beeps/sine_wave.cpp +0 -64
  81. data/ext/beeps/square_wave.cpp +0 -64
@@ -2,6 +2,7 @@
2
2
 
3
3
 
4
4
  require 'xot/setter'
5
+ require 'xot/const_symbol_accessor'
5
6
  require 'xot/universal_accessor'
6
7
  require 'xot/block_util'
7
8
  require 'beeps/ext'
@@ -14,43 +15,122 @@ module Beeps
14
15
 
15
16
  include Xot::Setter
16
17
 
17
- def initialize(options = nil, &block)
18
+ def initialize(**options, &block)
18
19
  super()
19
- set options if options
20
+ set options unless options.empty?
20
21
  Xot::BlockUtil.instance_eval_or_block_call self, &block if block
21
22
  end
22
23
 
24
+ def >>(o)
25
+ o.input = self
26
+ o
27
+ end
28
+
29
+ def <<(o)
30
+ self.input = o
31
+ o
32
+ end
33
+
34
+ universal_accessor :input
35
+
23
36
  end# Processor
24
37
 
25
38
 
26
- class SineWave
39
+ class Oscillator
40
+
41
+ const_symbol_accessor :type, **{
42
+ none: NONE,
43
+ sine: SINE,
44
+ triangle: TRIANGLE,
45
+ square: SQUARE,
46
+ sawtooth: SAWTOOTH
47
+ }
48
+
49
+ def initialize(type = :sine, *args, **kwargs, &block)
50
+ super(*args, **kwargs, &block)
51
+ self.type = type
52
+ end
27
53
 
28
54
  alias freq= frequency=
29
55
  alias freq frequency
30
56
 
31
- universal_accessor :frequency, :freq
57
+ universal_accessor :type, :frequency, :freq
32
58
 
33
- end# SineWave
59
+ end# Oscillator
34
60
 
35
61
 
36
- class SquareWave
62
+ class FileIn
37
63
 
38
- alias freq= frequency=
39
- alias freq frequency
64
+ def initialize(path = nil, *args, **kwargs, &block)
65
+ super(*args, **kwargs, &block)
66
+ self.path = path if path
67
+ end
40
68
 
41
- universal_accessor :frequency, :freq
69
+ universal_accessor :path
42
70
 
43
- end# SquareWave
71
+ end# FileIn
44
72
 
45
73
 
46
- class SawtoothWave
74
+ class Gain
47
75
 
48
- alias freq= frequency=
49
- alias freq frequency
76
+ universal_accessor :gain
77
+
78
+ end# Gain
79
+
80
+
81
+ class ADSR
82
+
83
+ def note_on(delay = 0)
84
+ note_on! delay
85
+ end
86
+
87
+ def note_off(delay = 0)
88
+ note_off! delay
89
+ end
90
+
91
+ universal_accessor :attack_time, :decay_time, :sustain_level, :release_time
92
+
93
+ alias attack= attack_time=
94
+ alias attack attack_time
95
+ alias decay= decay_time=
96
+ alias decay decay_time
97
+ alias sustain= sustain_level=
98
+ alias sustain sustain_level
99
+ alias release= release_time=
100
+ alias release release_time
101
+
102
+ end# ADSR
103
+
104
+
105
+ class TimeStretch
106
+
107
+ universal_accessor :scale
108
+
109
+ end# TimeStretch
110
+
111
+
112
+ class PitchShift
113
+
114
+ universal_accessor :shift
115
+
116
+ end# PitchShift
117
+
118
+
119
+ class Analyser
120
+
121
+ def each_signal(nsamples = fft_size, &block)
122
+ return enum_for(:each_signal, nsamples) unless block
123
+ each_signal!(nsamples, &block)
124
+ end
125
+
126
+ def each_spectrum(&block)
127
+ return enum_for(:each_spectrum) unless block
128
+ each_spectrum!(&block)
129
+ end
50
130
 
51
- universal_accessor :frequency, :freq
131
+ universal_accessor :fft_size
52
132
 
53
- end# SawtoothWave
133
+ end# Analyser
54
134
 
55
135
 
56
136
  end# Beeps
data/lib/beeps/sound.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
 
4
+ require 'xot/setter'
5
+ require 'xot/universal_accessor'
6
+ require 'xot/block_util'
4
7
  require 'beeps/ext'
5
8
 
6
9
 
@@ -9,11 +12,35 @@ module Beeps
9
12
 
10
13
  class Sound
11
14
 
12
- def self.load(path)
13
- Sound.new FileIn.new(path), 1
15
+ include Xot::Setter
16
+
17
+ def initialize(
18
+ processor, seconds = 0, nchannels: 1, sample_rate: 0, **options, &block)
19
+
20
+ setup processor, seconds, nchannels, sample_rate
21
+ set(**options) unless options.empty?
22
+ Xot::BlockUtil.instance_eval_or_block_call self, &block if block
14
23
  end
15
24
 
25
+ def play(**options, &block)
26
+ play!.tap do |player|
27
+ player.set(**options) unless options.empty?
28
+ Xot::BlockUtil.instance_eval_or_block_call player, &block if block
29
+ end
30
+ end
31
+
32
+ universal_accessor :gain, :loop
33
+
16
34
  end# Sound
17
35
 
18
36
 
37
+ class SoundPlayer
38
+
39
+ include Xot::Setter
40
+
41
+ universal_accessor :gain, :loop
42
+
43
+ end# SoundPlayer
44
+
45
+
19
46
  end# Beeps
data/src/adsr.cpp ADDED
@@ -0,0 +1,245 @@
1
+ #include "beeps/filter.h"
2
+
3
+
4
+ #include <ADSR.h>
5
+ #include "signals.h"
6
+
7
+
8
+ namespace Beeps
9
+ {
10
+
11
+
12
+ struct ADSR::Data
13
+ {
14
+
15
+ stk::ADSR adsr;
16
+
17
+ Signals adsr_signals;
18
+
19
+ float attack_time = 0, decay_time = 0, sustain_level = 1, release_time = 0;
20
+
21
+ float time = 0, note_on_time = -1, note_off_time = -1;
22
+
23
+ void update_envelope ()
24
+ {
25
+ adsr.setAttackTime( attack_time == 0 ? 0.01 : attack_time);
26
+ adsr.setSustainLevel(sustain_level);
27
+ adsr.setDecayTime( decay_time == 0 ? 0.01 : decay_time);
28
+ adsr.setReleaseTime( release_time == 0 ? 0.01 : release_time);
29
+ }
30
+
31
+ };// ADSR::Data
32
+
33
+
34
+ ADSR::ADSR (Processor* input)
35
+ : Super(input)
36
+ {
37
+ self->update_envelope();
38
+ }
39
+
40
+ ADSR::~ADSR ()
41
+ {
42
+ }
43
+
44
+ void
45
+ ADSR::note_on (float delay)
46
+ {
47
+ if (delay < 0)
48
+ argument_error(__FILE__, __LINE__);
49
+
50
+ float on = self->time + delay, off = self->note_off_time;
51
+ if (0 <= off && off < on)
52
+ self->note_off_time = -1;
53
+
54
+ self->note_on_time = on;
55
+
56
+ set_updated();
57
+ }
58
+
59
+ void
60
+ ADSR::note_off (float delay)
61
+ {
62
+ if (delay < 0)
63
+ argument_error(__FILE__, __LINE__);
64
+
65
+ float off = self->time + delay, on = self->note_on_time;
66
+ if (0 <= on && off < on)
67
+ argument_error(__FILE__, __LINE__);
68
+
69
+ self->note_off_time = off;
70
+
71
+ set_updated();
72
+ }
73
+
74
+ void
75
+ ADSR::set_attack_time (float time)
76
+ {
77
+ if (time < 0)
78
+ argument_error(__FILE__, __LINE__);
79
+
80
+ self->attack_time = time;
81
+ self->update_envelope();
82
+
83
+ set_updated();
84
+ }
85
+
86
+ float
87
+ ADSR::attack_time () const
88
+ {
89
+ return self->attack_time;
90
+ }
91
+
92
+ void
93
+ ADSR::set_decay_time (float time)
94
+ {
95
+ if (time < 0)
96
+ argument_error(__FILE__, __LINE__);
97
+
98
+ self->decay_time = time;
99
+ self->update_envelope();
100
+
101
+ set_updated();
102
+ }
103
+
104
+ float
105
+ ADSR::decay_time () const
106
+ {
107
+ return self->decay_time;
108
+ }
109
+
110
+ void
111
+ ADSR::set_sustain_level (float level)
112
+ {
113
+ if (level < 0)
114
+ argument_error(__FILE__, __LINE__);
115
+
116
+ self->sustain_level = level;
117
+ self->update_envelope();
118
+
119
+ set_updated();
120
+ }
121
+
122
+ float
123
+ ADSR::sustain_level () const
124
+ {
125
+ return self->sustain_level;
126
+ }
127
+
128
+ void
129
+ ADSR::set_release_time (float time)
130
+ {
131
+ if (time < 0)
132
+ argument_error(__FILE__, __LINE__);
133
+
134
+ self->release_time = time;
135
+ self->update_envelope();
136
+
137
+ set_updated();
138
+ }
139
+
140
+ float
141
+ ADSR::release_time () const
142
+ {
143
+ return self->release_time;
144
+ }
145
+
146
+ static size_t
147
+ slice (Frames* frames, size_t start, float length_sec = -1)
148
+ {
149
+ Float sample_rate = frames->dataRate();
150
+ size_t len = length_sec >= 0
151
+ ? length_sec * sample_rate
152
+ : frames->nframes() - start;
153
+ assert(0 < len && (start + len) < frames->nsamples());
154
+
155
+ return frames->slice(start, len);
156
+ }
157
+
158
+ static void
159
+ process_envelope_signals (ADSR* adsr, Signals* signals)
160
+ {
161
+ assert(adsr && signals && signals->nchannels() == 1);
162
+
163
+ ADSR::Data* self = adsr->self.get();
164
+
165
+ Frames* frames = Signals_get_frames(signals);
166
+ assert(frames);
167
+
168
+ float start = self->time;
169
+ float end = start + Signals_get_seconds(*signals);
170
+ self->time = end;
171
+
172
+ float on = self->note_on_time;
173
+ float off = self->note_off_time;
174
+ assert(on <= off);
175
+
176
+ bool has_on = 0 <= on && start <= on && on < end;
177
+ bool has_off = 0 <= off && start <= off && off < end;
178
+
179
+ if (!has_on && !has_off)
180
+ {
181
+ self->adsr.tick(*frames);
182
+ return;
183
+ }
184
+
185
+ size_t last = 0;
186
+ if (has_on)
187
+ {
188
+ if (start < on)
189
+ {
190
+ last = slice(frames, 0, on - start);
191
+ self->adsr.tick(*frames);
192
+ frames->unslice();
193
+ }
194
+ self->adsr.keyOn();
195
+ }
196
+ if (has_on || has_off)
197
+ {
198
+ float len = has_off ? off - (has_on ? on : start) : -1;
199
+ last = slice(frames, last, len);
200
+ self->adsr.tick(*frames);
201
+ frames->unslice();
202
+ }
203
+ if (has_off)
204
+ {
205
+ self->adsr.keyOff();
206
+ if (off < end)
207
+ {
208
+ slice(frames, last, -1);
209
+ self->adsr.tick(*frames);
210
+ frames->unslice();
211
+ }
212
+ }
213
+ }
214
+
215
+ void
216
+ ADSR::filter (Context* context, Signals* signals, uint* offset)
217
+ {
218
+ Super::filter(context, signals, offset);
219
+
220
+ if (!self->adsr_signals)
221
+ {
222
+ self->adsr_signals =
223
+ Signals_create(signals->nsamples(), 1, signals->sample_rate());
224
+ }
225
+
226
+ if (self->adsr_signals.nsamples() != signals->nsamples())
227
+ Signals_resize(&self->adsr_signals, signals->nsamples(), 0);
228
+
229
+ process_envelope_signals(this, &self->adsr_signals);
230
+ Signals_apply(signals, self->adsr_signals);
231
+ }
232
+
233
+ ADSR::operator bool () const
234
+ {
235
+ if (!Super::operator bool()) return false;
236
+ return
237
+ self->attack_time >= 0 &&
238
+ self->decay_time >= 0 &&
239
+ self->sustain_level >= 0 &&
240
+ self->release_time >= 0 &&
241
+ self->time >= 0;
242
+ }
243
+
244
+
245
+ }// Beeps
data/src/analyser.cpp ADDED
@@ -0,0 +1,254 @@
1
+ #include "beeps/filter.h"
2
+
3
+
4
+ #include <math.h>
5
+ #include <algorithm>
6
+ #include "pffft.h"
7
+ #include "beeps/beeps.h"
8
+ #include "beeps/exception.h"
9
+ #include "signals.h"
10
+
11
+
12
+ namespace Beeps
13
+ {
14
+
15
+
16
+ struct PFFFTDestroySetup
17
+ {
18
+ void operator () (PFFFT_Setup* ptr)
19
+ {
20
+ pffft_destroy_setup(ptr);
21
+ }
22
+ };
23
+
24
+ struct PFFFTAlignedFree
25
+ {
26
+ void operator () (float* ptr)
27
+ {
28
+ pffft_aligned_free(ptr);
29
+ }
30
+ };
31
+
32
+
33
+ struct Analyser::Data
34
+ {
35
+
36
+ Signals signals;
37
+
38
+ Spectrum spectrum;
39
+
40
+ std::unique_ptr<PFFFT_Setup, PFFFTDestroySetup> pffft;
41
+
42
+ std::unique_ptr<float[], PFFFTAlignedFree> fft_buffer;
43
+
44
+ uint fft_size = 0;
45
+
46
+ ~Data ()
47
+ {
48
+ clear();
49
+ }
50
+
51
+ void setup (uint size)
52
+ {
53
+ if (size == fft_size) return;
54
+
55
+ clear();
56
+
57
+ signals = Signals_create(std::min(size, (uint) Beeps::sample_rate()));
58
+ pffft .reset(pffft_new_setup(size, PFFFT_REAL));
59
+ fft_buffer.reset((float*) pffft_aligned_malloc(sizeof(float) * size));
60
+ fft_size = size;
61
+ }
62
+
63
+ void clear ()
64
+ {
65
+ if (!pffft) return;
66
+
67
+ signals = Signals();
68
+ spectrum .clear();
69
+ pffft .reset();
70
+ fft_buffer.reset();
71
+ fft_size = 0;
72
+ }
73
+
74
+ bool is_valid () const
75
+ {
76
+ return signals && pffft && fft_buffer && fft_size > 0;
77
+ }
78
+
79
+ };// Analyser::Data
80
+
81
+
82
+ Analyser::Analyser (uint fft_size, Processor* input)
83
+ : Super(input)
84
+ {
85
+ set_fft_size(fft_size);
86
+ }
87
+
88
+ Analyser::~Analyser ()
89
+ {
90
+ }
91
+
92
+ static bool
93
+ is_valid_fft_size (uint size)
94
+ {
95
+ if (size < 32) return false;
96
+
97
+ while (size > 1)
98
+ {
99
+ if (size % 2 == 0) size /= 2;
100
+ else if (size % 3 == 0) size /= 3;
101
+ else if (size % 5 == 0) size /= 5;
102
+ else break;
103
+ }
104
+ return size == 1;
105
+ }
106
+
107
+ void
108
+ Analyser::set_fft_size (uint size)
109
+ {
110
+ if (!is_valid_fft_size(size))
111
+ beeps_error(__FILE__, __LINE__, "fft_size must be divisible by 2, 3, or 5");
112
+
113
+ self->setup(size);
114
+ }
115
+
116
+ uint
117
+ Analyser::fft_size () const
118
+ {
119
+ return self->fft_size;
120
+ }
121
+
122
+ float
123
+ Analyser::resolution () const
124
+ {
125
+ if (self->fft_size == 0) return 0;
126
+ return self->signals.sample_rate() / self->fft_size;
127
+ }
128
+
129
+ const Signals&
130
+ Analyser::signals () const
131
+ {
132
+ return self->signals;
133
+ }
134
+
135
+ static void
136
+ copy_signals_to_fft_buffer (float* buffer, uint size, const Signals& signals)
137
+ {
138
+ const double* samples = signals.samples();
139
+ uint nsamples = size > signals.nsamples() ? signals.nsamples() : size;
140
+
141
+ switch (signals.nchannels())
142
+ {
143
+ case 1:
144
+ for (uint i = 0; i < nsamples; ++i)
145
+ buffer[i] = samples[i];
146
+ break;
147
+
148
+ case 2:
149
+ for (uint i = 0; i < nsamples; ++i, samples += 2)
150
+ buffer[i] = (samples[0] + samples[1]) * 0.5;
151
+ break;
152
+
153
+ default:
154
+ beeps_error(__FILE__, __LINE__);
155
+ }
156
+
157
+ for (uint i = nsamples; i < size; ++i)
158
+ buffer[i] = 0;
159
+ }
160
+
161
+ static void
162
+ update_spectrum (Analyser::Spectrum* spectrum, float* buffer, uint buffer_size)
163
+ {
164
+ assert(spectrum && spectrum->empty() && buffer && (buffer_size % 2) == 0);
165
+
166
+ uint size = buffer_size / 2;
167
+ float div = 1.0 / size;
168
+ float* p = buffer;
169
+
170
+ spectrum->reserve(size);
171
+ for (uint i = 0; i < size; ++i, p += 2)
172
+ spectrum->push_back(sqrt(p[0] * p[0] + p[1] * p[1]) * div);
173
+ }
174
+
175
+ const Analyser::Spectrum&
176
+ Analyser::spectrum () const
177
+ {
178
+ if (self->spectrum.empty() && *this)
179
+ {
180
+ float* p = &self->fft_buffer[0];
181
+ copy_signals_to_fft_buffer(p, self->fft_size, self->signals);
182
+ pffft_transform_ordered(self->pffft.get(), p, p, NULL, PFFFT_FORWARD);
183
+ update_spectrum(&self->spectrum, p, self->fft_size);
184
+ }
185
+ return self->spectrum;
186
+ }
187
+
188
+ static void
189
+ shift (Signals* signals, uint nsamples)
190
+ {
191
+ if (nsamples > signals->nsamples())
192
+ return Signals_clear(signals);
193
+
194
+ Frames* frames = Signals_get_frames(signals);
195
+ assert(frames);
196
+
197
+ Float* from = &(*frames)(nsamples, 0);
198
+ Float* to = &(*frames)(0, 0);
199
+ uint size = (signals->nsamples() - nsamples) * signals->nchannels();
200
+ for (uint i = 0; i < size; ++i)
201
+ *to++ = *from++;
202
+
203
+ Signals_set_nsamples(signals, signals->nsamples() - nsamples);
204
+ }
205
+
206
+ static void
207
+ append (Signals* to, const Signals& from)
208
+ {
209
+ assert(to);
210
+
211
+ Frames* tof = Signals_get_frames(to);
212
+ const Frames* fromf = Signals_get_frames(&from);
213
+ assert(fromf && tof);
214
+
215
+ uint to_cap = to->capacity();
216
+ uint to_nsamples = to->nsamples();
217
+ uint from_nsamples = from.nsamples();
218
+ uint from_start = from_nsamples > to_cap ? from_nsamples - to_cap : 0;
219
+ uint nsamples = from_nsamples - from_start;
220
+ assert(to_nsamples + nsamples <= to_capacity);
221
+
222
+ for (uint ch = 0; ch < tof->nchannels(); ++ch)
223
+ {
224
+ uint from_ch = ch < fromf->nchannels() ? ch : 0;
225
+ for (uint i = 0; i < nsamples; ++i)
226
+ (*tof)(to_nsamples + i, ch) = (*fromf)(from_start + i, from_ch);
227
+ }
228
+
229
+ Signals_set_nsamples(to, to_nsamples + nsamples);
230
+ }
231
+
232
+ void
233
+ Analyser::filter (Context* context, Signals* signals, uint* offset)
234
+ {
235
+ Super::filter(context, signals, offset);
236
+
237
+ Signals& sig = self->signals;
238
+ uint nsamples = sig.nsamples() + signals->nsamples();
239
+ if (nsamples > sig.capacity())
240
+ shift(&sig, nsamples - sig.capacity());
241
+
242
+ append(&sig, *signals);
243
+
244
+ self->spectrum.clear();
245
+ }
246
+
247
+ Analyser::operator bool () const
248
+ {
249
+ if (!Super::operator bool()) return false;
250
+ return self->is_valid();
251
+ }
252
+
253
+
254
+ }// Beeps
data/src/beeps.cpp CHANGED
@@ -5,6 +5,8 @@
5
5
  #include "Stk.h"
6
6
  #include "beeps/exception.h"
7
7
  #include "openal.h"
8
+ #include "sound.h"
9
+ #include "mic_in.h"
8
10
 
9
11
 
10
12
  namespace Beeps
@@ -25,8 +27,15 @@ namespace Beeps
25
27
  OpenAL_fin();
26
28
  }
27
29
 
28
- uint
29
- sampling_rate ()
30
+ void
31
+ process_streams ()
32
+ {
33
+ MicIn_process_streams();
34
+ SoundPlayer_process_streams();
35
+ }
36
+
37
+ double
38
+ sample_rate ()
30
39
  {
31
40
  return stk::Stk::sampleRate();
32
41
  }