beeps 0.3.6 → 0.3.7

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/beeps/beeps.cpp +7 -0
  3. data/.doc/ext/beeps/high_pass.cpp +63 -0
  4. data/.doc/ext/beeps/low_pass.cpp +63 -0
  5. data/.doc/ext/beeps/native.cpp +8 -0
  6. data/.doc/ext/beeps/oscillator.cpp +87 -10
  7. data/.doc/ext/beeps/processor.cpp +14 -1
  8. data/.doc/ext/beeps/reverb.cpp +99 -0
  9. data/.doc/ext/beeps/signals.cpp +128 -0
  10. data/ChangeLog.md +24 -0
  11. data/Rakefile +1 -1
  12. data/VERSION +1 -1
  13. data/beeps.gemspec +2 -2
  14. data/ext/beeps/beeps.cpp +8 -0
  15. data/ext/beeps/high_pass.cpp +66 -0
  16. data/ext/beeps/low_pass.cpp +66 -0
  17. data/ext/beeps/native.cpp +8 -0
  18. data/ext/beeps/oscillator.cpp +95 -12
  19. data/ext/beeps/processor.cpp +15 -1
  20. data/ext/beeps/reverb.cpp +106 -0
  21. data/ext/beeps/signals.cpp +136 -0
  22. data/include/beeps/beeps.h +2 -2
  23. data/include/beeps/defs.h +3 -0
  24. data/include/beeps/filter.h +118 -17
  25. data/include/beeps/generator.h +50 -17
  26. data/include/beeps/processor.h +23 -6
  27. data/include/beeps/ruby/filter.h +33 -0
  28. data/include/beeps/ruby/signals.h +40 -0
  29. data/include/beeps/signals.h +1 -1
  30. data/lib/beeps/processor.rb +46 -1
  31. data/lib/beeps/signals.rb +19 -0
  32. data/lib/beeps.rb +1 -0
  33. data/src/analyser.cpp +34 -37
  34. data/src/beeps.cpp +7 -6
  35. data/src/envelope.cpp +60 -46
  36. data/src/file_in.cpp +6 -6
  37. data/src/gain.cpp +5 -5
  38. data/src/high_pass.cpp +57 -0
  39. data/src/low_pass.cpp +57 -0
  40. data/src/mic_in.cpp +16 -14
  41. data/src/mixer.cpp +38 -20
  42. data/src/oscillator.cpp +260 -168
  43. data/src/pitch_shift.cpp +6 -6
  44. data/src/processor.cpp +118 -11
  45. data/src/processor.h +8 -0
  46. data/src/reverb.cpp +124 -0
  47. data/src/sequencer.cpp +18 -14
  48. data/src/signals.cpp +264 -106
  49. data/src/signals.h +28 -89
  50. data/src/sound.cpp +28 -20
  51. data/src/time_stretch.cpp +6 -6
  52. data/src/win32/signals.cpp +8 -7
  53. data/src/x_pass.h +51 -0
  54. data/test/helper.rb +14 -0
  55. data/test/test_analyser.rb +26 -0
  56. data/test/test_envelope.rb +55 -0
  57. data/test/test_file_in.rb +22 -1
  58. data/test/test_gain.rb +28 -0
  59. data/test/test_high_pass.rb +41 -0
  60. data/test/test_low_pass.rb +41 -0
  61. data/test/test_mixer.rb +63 -0
  62. data/test/test_oscillator.rb +58 -0
  63. data/test/test_pitch_shift.rb +32 -0
  64. data/test/test_processor.rb +7 -0
  65. data/test/test_signals.rb +60 -0
  66. data/test/test_time_stretch.rb +36 -0
  67. metadata +48 -10
data/src/oscillator.cpp CHANGED
@@ -3,12 +3,11 @@
3
3
 
4
4
  #include <assert.h>
5
5
  #include <cmath>
6
+ #include <algorithm>
6
7
  #include <vector>
7
- #include "SineWave.h"
8
- #include "Blit.h"
9
- #include "BlitSquare.h"
10
- #include "BlitSaw.h"
11
8
  #include "beeps/exception.h"
9
+ #include "beeps/debug.h"
10
+ #include "processor.h"
12
11
  #include "signals.h"
13
12
 
14
13
 
@@ -16,40 +15,9 @@ namespace Beeps
16
15
  {
17
16
 
18
17
 
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
- }
18
+ static const uint NSEGMENTS_PER_WAVEFORM_CYCLE = 32;
28
19
 
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
20
+ static const uint MIN_BUFFER_SIZE = 64;
53
21
 
54
22
 
55
23
  class Osc
@@ -61,10 +29,12 @@ namespace Beeps
61
29
 
62
30
  virtual void reset () = 0;
63
31
 
64
- virtual void tick (Frames* frames) = 0;
32
+ virtual void tick (stk::StkFrames* frames) = 0;
65
33
 
66
34
  virtual void set_frequency (float freq) = 0;
67
35
 
36
+ virtual float frequency () const = 0;
37
+
68
38
  virtual void set_phase (float phase) = 0;
69
39
 
70
40
  virtual float phase () const = 0;
@@ -72,74 +42,6 @@ namespace Beeps
72
42
  };// Osc
73
43
 
74
44
 
75
- template <typename OSC, uint DROP_MSEC>
76
- class StkOsc : public Osc
77
- {
78
-
79
- public:
80
-
81
- void reset () override
82
- {
83
- osc.reset();
84
- drop_msec = DROP_MSEC;
85
- }
86
-
87
- void tick (Frames* frames) override
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
-
96
- osc.tick(*frames);
97
- }
98
-
99
- void set_frequency (float freq) override
100
- {
101
- osc.setFrequency(freq);
102
- }
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
-
114
- protected:
115
-
116
- OSC osc;
117
-
118
- uint drop_msec = DROP_MSEC;
119
-
120
- };// StkOsc
121
-
122
-
123
- typedef StkOsc<SineWave, 0> SineOsc;
124
-
125
- typedef StkOsc<stk::BlitSquare, 100> SquareOsc;
126
-
127
- typedef StkOsc<BlitSaw, 200> SawtoothOsc;
128
-
129
-
130
- class TriangleOsc : public StkOsc<stk::Blit, 0>
131
- {
132
-
133
- public:
134
-
135
- TriangleOsc ()
136
- {
137
- osc.setHarmonics(10);
138
- }
139
-
140
- };// TriangleOsc
141
-
142
-
143
45
  class NoiseOsc : public Osc
144
46
  {
145
47
 
@@ -150,9 +52,9 @@ namespace Beeps
150
52
  time = 0;
151
53
  }
152
54
 
153
- void tick (Frames* frames) override
55
+ void tick (stk::StkFrames* frames) override
154
56
  {
155
- if (0 < freq && (freq * 2) <= frames->sample_rate())
57
+ if (0 < freq && (freq * 2) <= frames->dataRate())
156
58
  tick_with_freq(frames);
157
59
  else
158
60
  tick_without_freq(frames);
@@ -163,6 +65,11 @@ namespace Beeps
163
65
  this->freq = freq;
164
66
  }
165
67
 
68
+ float frequency () const override
69
+ {
70
+ return freq;
71
+ }
72
+
166
73
  void set_phase (float phase) override
167
74
  {
168
75
  time = freq == 0 ? 0 : phase * (1.f / freq);
@@ -179,32 +86,32 @@ namespace Beeps
179
86
 
180
87
  double time = 0;
181
88
 
182
- void tick_without_freq (Frames* frames)
89
+ void tick_without_freq (stk::StkFrames* frames)
183
90
  {
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)
91
+ uint nchannels = frames->channels();
92
+ uint nframes = frames->frames();
93
+ Sample* p = &(*frames)(0, 0);
94
+ for (uint i = 0; i < nframes; ++i, ++p)
188
95
  {
189
96
  uint ch = i % nchannels;
190
- *pframe = ch == 0 ? noise() : pframe[-ch];
97
+ *p = ch == 0 ? noise() : p[-ch];
191
98
  }
192
99
  }
193
100
 
194
- void tick_with_freq (Frames* frames)
101
+ void tick_with_freq (stk::StkFrames* frames)
195
102
  {
196
- float time_per_sample = 1.f / frames->sample_rate();
103
+ float time_per_sample = 1.f / frames->dataRate();
197
104
  float time_per_freq = 1.f / (freq * 2);
198
105
 
199
- uint nchannels = frames->nchannels();
200
- uint nframes = frames->nframes();
201
- Float* pframe = &(*frames)(0, 0);
106
+ uint nchannels = frames->channels();
107
+ uint nframes = frames->frames();
108
+ Sample* p = &(*frames)(0, 0);
202
109
  float value = noise();
203
- for (uint i = 0; i < nframes; ++i, ++pframe)
110
+ for (uint i = 0; i < nframes; ++i, ++p)
204
111
  {
205
112
  if (i % nchannels == 0)
206
113
  {
207
- *pframe = value;
114
+ *p = value;
208
115
 
209
116
  time += time_per_sample;
210
117
  while (time >= time_per_freq)
@@ -214,7 +121,7 @@ namespace Beeps
214
121
  }
215
122
  }
216
123
  else
217
- *pframe = value;
124
+ *p = value;
218
125
  }
219
126
  }
220
127
 
@@ -231,10 +138,10 @@ namespace Beeps
231
138
 
232
139
  public:
233
140
 
234
- typedef std::vector<float> Table;
141
+ typedef std::vector<Sample> Table;
235
142
 
236
- WaveformOsc (float* samples, size_t nsamples, float frequency)
237
- : table(samples, samples + nsamples), freq(frequency), time(0)
143
+ WaveformOsc (const Sample* samples, size_t nsamples)
144
+ : table(samples, samples + nsamples), freq(1), time(0)
238
145
  {
239
146
  }
240
147
 
@@ -243,15 +150,16 @@ namespace Beeps
243
150
  time = 0;
244
151
  }
245
152
 
246
- void tick (Frames* frames) override
153
+ void tick (stk::StkFrames* frames) override
247
154
  {
248
155
  size_t size = table.size();
249
- float dt = size * freq / frames->sample_rate();
156
+ float dt = size * freq / frames->dataRate();
250
157
 
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)
158
+ uint nchannels = frames->channels();
159
+ uint nframes = frames->frames();
160
+ Sample* p = &(*frames)(0, 0);
161
+ Sample prev = 0;
162
+ for (uint i = 0; i < nframes; ++i, ++p)
255
163
  {
256
164
  uint ch = i % nchannels;
257
165
  if (ch == 0)
@@ -259,13 +167,13 @@ namespace Beeps
259
167
  size_t index0 = (size_t) time;
260
168
  size_t index1 = index0 == size - 1 ? 0 : index0 + 1;
261
169
  float frac = time - index0;
262
- *pframe = table[index0] * (1.f - frac) + table[index1] * frac;
170
+ *p = table[index0] * (1.f - frac) + table[index1] * frac;
171
+ prev = *p;
263
172
 
264
173
  time += dt;
265
174
  while (time >= size) time -= size;
266
175
  }
267
- else
268
- *pframe = pframe[-ch];
176
+ else *p = prev;
269
177
  }
270
178
  }
271
179
 
@@ -274,6 +182,11 @@ namespace Beeps
274
182
  this->freq = freq;
275
183
  }
276
184
 
185
+ float frequency () const override
186
+ {
187
+ return freq;
188
+ }
189
+
277
190
  void set_phase (float phase) override
278
191
  {
279
192
  this->time = std::fmod(phase, 1.f) * table.size();
@@ -301,21 +214,28 @@ namespace Beeps
301
214
  struct Oscillator::Data
302
215
  {
303
216
 
304
- Type type = TYPE_NONE;
217
+ Type type = TYPE_NONE;
218
+
219
+ float gain = 1;
305
220
 
306
- float frequency = 440;
221
+ float offset = 0;
222
+
223
+ float duty = 0.5;
307
224
 
308
225
  std::unique_ptr<Osc> osc;
309
226
 
310
227
  };// Oscillator::Data
311
228
 
312
229
 
230
+ enum InputIndex {FREQUENCY = 0, PHASE, GAIN, OFFSET, DUTY};
231
+
232
+
313
233
  Oscillator::Oscillator (Type type)
314
234
  {
315
235
  set_type(type);
316
236
  }
317
237
 
318
- Oscillator::Oscillator (float* samples, size_t size)
238
+ Oscillator::Oscillator (const Sample* samples, size_t size)
319
239
  {
320
240
  set_samples(samples, size);
321
241
  }
@@ -329,32 +249,77 @@ namespace Beeps
329
249
  {
330
250
  Super::reset();
331
251
  self->osc->reset();
252
+
253
+ set_updated();
332
254
  }
333
255
 
334
- void
335
- Oscillator::set_type (Type type)
256
+ static Osc*
257
+ create_osc (Oscillator::Type type, size_t size, float duty)
336
258
  {
337
- if (type == self->type) return;
259
+ std::function<Sample(float)> fun;
260
+ switch (type)
261
+ {
262
+ case Oscillator::SINE:
263
+ fun = [](float t) {return std::sin(t * M_PI * 2);};
264
+ break;
338
265
 
339
- float phase = self->osc ? self->osc->phase() : 0;
266
+ case Oscillator::TRIANGLE:
267
+ fun = [](float t) {return t < 0.5 ? t * 4 - 1 : 3 - t * 4;};
268
+ break;
340
269
 
341
- self->type = type;
342
- self->osc.reset();
270
+ case Oscillator::SAWTOOTH:
271
+ fun = [](float t) {return t * 2 - 1;};
272
+ break;
273
+
274
+ case Oscillator::SQUARE:
275
+ fun = [=](float t) {return t < duty ? 1 : -1;};
276
+ break;
277
+
278
+ case Oscillator::NOISE:
279
+ return new NoiseOsc();
343
280
 
344
- switch (self->type)
345
- {
346
- case SINE: self->osc.reset(new SineOsc()); break;
347
- case TRIANGLE: self->osc.reset(new TriangleOsc()); break;
348
- case SQUARE: self->osc.reset(new SquareOsc()); break;
349
- case SAWTOOTH: self->osc.reset(new SawtoothOsc()); break;
350
- case NOISE: self->osc.reset(new NoiseOsc()); break;
351
281
  default:
352
282
  argument_error(
353
- __FILE__, __LINE__, "unknown oscilator type '%d'", self->type);
283
+ __FILE__, __LINE__, "unknown oscilator type '%d'", type);
354
284
  break;
355
285
  }
356
286
 
287
+ std::vector<Sample> samples;
288
+ samples.resize(size);
289
+ for (size_t i = 0; i < size; ++i)
290
+ samples[i] = fun(i / (float) size);
291
+
292
+ return new WaveformOsc(&samples[0], samples.size());
293
+ }
294
+
295
+ static void
296
+ update_osc (Oscillator* pthis, std::function<Osc*()> fun)
297
+ {
298
+ Oscillator::Data* self = pthis->self.get();
299
+
300
+ float freq = self->osc ? self->osc->frequency() : 440;
301
+ float phase = self->osc ? self->osc->phase() : 0;
302
+
303
+ self->osc.reset(fun());
304
+
305
+ self->osc->set_frequency(freq);
357
306
  self->osc->set_phase(phase);
307
+ }
308
+
309
+ static void
310
+ update_waveform (Oscillator* pthis)
311
+ {
312
+ update_osc(pthis, [&]()
313
+ {
314
+ return create_osc(pthis->type(), 32, pthis->duty());
315
+ });
316
+ }
317
+
318
+ void
319
+ Oscillator::set_type (Type type)
320
+ {
321
+ self->type = type;
322
+ update_waveform(this);
358
323
 
359
324
  set_updated();
360
325
  }
@@ -366,18 +331,18 @@ namespace Beeps
366
331
  }
367
332
 
368
333
  void
369
- Oscillator::set_samples (float* samples, size_t size)
334
+ Oscillator::set_samples (const Sample* samples, size_t size)
370
335
  {
371
- float phase = self->osc ? self->osc->phase() : 0;
372
-
373
336
  self->type = SAMPLES;
374
- self->osc.reset(new WaveformOsc(samples, size, frequency()));
375
- self->osc->set_phase(phase);
337
+ update_osc(this, [=]()
338
+ {
339
+ return new WaveformOsc(samples, size);
340
+ });
376
341
 
377
342
  set_updated();
378
343
  }
379
344
 
380
- const float*
345
+ const Sample*
381
346
  Oscillator::samples () const
382
347
  {
383
348
  if (self->type != SAMPLES)
@@ -403,21 +368,37 @@ namespace Beeps
403
368
  if (frequency <= 0)
404
369
  argument_error(__FILE__, __LINE__);
405
370
 
406
- self->frequency = frequency;
371
+ self->osc->set_frequency(frequency);
372
+
407
373
  set_updated();
374
+ clear_sub_input_unless_processing(FREQUENCY);
375
+ }
376
+
377
+ void
378
+ Oscillator::set_frequency (Processor* frequency)
379
+ {
380
+ set_sub_input(FREQUENCY, frequency);
408
381
  }
409
382
 
410
383
  float
411
384
  Oscillator::frequency () const
412
385
  {
413
- return self->frequency;
386
+ return self->osc->frequency();
414
387
  }
415
388
 
416
389
  void
417
390
  Oscillator::set_phase (float phase)
418
391
  {
419
392
  self->osc->set_phase(phase);
393
+
420
394
  set_updated();
395
+ clear_sub_input_unless_processing(PHASE);
396
+ }
397
+
398
+ void
399
+ Oscillator::set_phase (Processor* phase)
400
+ {
401
+ set_sub_input(PHASE, phase);
421
402
  }
422
403
 
423
404
  float
@@ -427,24 +408,135 @@ namespace Beeps
427
408
  }
428
409
 
429
410
  void
430
- Oscillator::generate (Context* context, Signals* signals, uint* offset)
411
+ Oscillator::set_gain (float gain)
431
412
  {
432
- Super::generate(context, signals, offset);
413
+ if (gain == self->gain)
414
+ return;
415
+
416
+ self->gain = gain;
417
+
418
+ set_updated();
419
+ clear_sub_input_unless_processing(GAIN);
420
+ }
421
+
422
+ void
423
+ Oscillator::set_gain (Processor* gain)
424
+ {
425
+ set_sub_input(GAIN, gain);
426
+ }
433
427
 
434
- Frames* frames = Signals_get_frames(signals);
435
- if (!frames)
428
+ float
429
+ Oscillator::gain () const
430
+ {
431
+ return self->gain;
432
+ }
433
+
434
+ void
435
+ Oscillator::set_offset (float offset)
436
+ {
437
+ if (offset == self->offset)
438
+ return;
439
+
440
+ self->offset = offset;
441
+
442
+ set_updated();
443
+ clear_sub_input_unless_processing(OFFSET);
444
+ }
445
+
446
+ void
447
+ Oscillator::set_offset (Processor* offset)
448
+ {
449
+ set_sub_input(OFFSET, offset);
450
+ }
451
+
452
+ float
453
+ Oscillator::offset () const
454
+ {
455
+ return self->offset;
456
+ }
457
+
458
+ void
459
+ Oscillator::set_duty (float duty)
460
+ {
461
+ if (duty <= 0)
462
+ argument_error(__FILE__, __LINE__);
463
+ if (duty >= 1)
436
464
  argument_error(__FILE__, __LINE__);
437
465
 
438
- self->osc->set_frequency(self->frequency);
439
- self->osc->tick(frames);
466
+ if (duty == self->duty)
467
+ return;
468
+
469
+ self->duty = duty;
470
+ if (type() == SQUARE) update_waveform(this);
471
+
472
+ set_updated();
473
+ clear_sub_input_unless_processing(DUTY);
474
+ }
475
+
476
+ void
477
+ Oscillator::set_duty (Processor* duty)
478
+ {
479
+ set_sub_input(DUTY, duty);
480
+ }
440
481
 
441
- Signals_set_nsamples(signals, frames->nframes());
482
+ float
483
+ Oscillator::duty () const
484
+ {
485
+ return self->duty;
442
486
  }
443
487
 
444
488
  Oscillator::operator bool () const
445
489
  {
446
- if (!Super::operator bool()) return false;
447
- return self->type != TYPE_NONE && self->frequency > 0 && self->osc;
490
+ if (!Super::operator bool())
491
+ return false;
492
+
493
+ return self->type != TYPE_NONE && self->osc;
494
+ }
495
+
496
+ void
497
+ Oscillator::generate (Context* context, Signals* signals, uint* offset)
498
+ {
499
+ Super::generate(context, signals, offset);
500
+
501
+ Processor* pfreq = sub_input(FREQUENCY);
502
+ Processor* pphase = sub_input(PHASE);
503
+ Processor* pgain = sub_input(GAIN);
504
+ Processor* poffset = sub_input(OFFSET);
505
+ Processor* pduty = sub_input(DUTY);
506
+
507
+ auto* pcontext = Processor_get_context(context);
508
+ double sample_rate = signals->sample_rate();
509
+ uint nsamples = signals->capacity();
510
+ uint seg_size = get_segment_size(sample_rate, nsamples);
511
+
512
+ for (uint start = 0; start < nsamples; start += seg_size)
513
+ {
514
+ uint seg_offset = *offset + start;
515
+ if (pfreq) set_frequency(pcontext->process(pfreq, seg_size, seg_offset));
516
+ if (pphase) set_phase( pcontext->process(pphase, seg_size, seg_offset));
517
+ if (pgain) set_gain( pcontext->process(pgain, seg_size, seg_offset));
518
+ if (poffset) set_offset( pcontext->process(poffset, seg_size, seg_offset));
519
+ if (pduty) set_duty( pcontext->process(pduty, seg_size, seg_offset));
520
+
521
+ uint end = std::min(start + seg_size, nsamples);
522
+ Signals_tick(signals, start, end, [&](stk::StkFrames* frames)
523
+ {
524
+ self->osc->tick(frames);
525
+ });
526
+ Signals_offset_and_scale(signals, self->offset, self->gain, -1, start, end);
527
+ }
528
+
529
+ *offset += signals->nsamples();
530
+ }
531
+
532
+ int
533
+ Oscillator::max_segment_size_for_process (
534
+ double sample_rate, uint nsamples) const
535
+ {
536
+ return std::clamp(
537
+ (uint) (sample_rate / frequency() / NSEGMENTS_PER_WAVEFORM_CYCLE),
538
+ MIN_BUFFER_SIZE,
539
+ nsamples);
448
540
  }
449
541
 
450
542
 
data/src/pitch_shift.cpp CHANGED
@@ -52,6 +52,12 @@ namespace Beeps
52
52
  return self->shift;
53
53
  }
54
54
 
55
+ PitchShift::operator bool () const
56
+ {
57
+ if (!Super::operator bool()) return false;
58
+ return self->shift > 0;
59
+ }
60
+
55
61
  void
56
62
  PitchShift::filter (Context* context, Signals* signals, uint* offset)
57
63
  {
@@ -72,11 +78,5 @@ namespace Beeps
72
78
  Signals_write_samples(signals, output, signals->nsamples());
73
79
  }
74
80
 
75
- PitchShift::operator bool () const
76
- {
77
- if (!Super::operator bool()) return false;
78
- return self->shift > 0;
79
- }
80
-
81
81
 
82
82
  }// Beeps