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/signals.h CHANGED
@@ -5,9 +5,11 @@
5
5
 
6
6
 
7
7
  #include <assert.h>
8
+ #include <functional>
8
9
  #include <vector>
9
10
  #include <Stk.h>
10
11
  #include <xot/pimpl.h>
12
+ #include "beeps/beeps.h"
11
13
  #include "beeps/signals.h"
12
14
  #include "beeps/exception.h"
13
15
 
@@ -16,11 +18,6 @@ namespace Beeps
16
18
  {
17
19
 
18
20
 
19
- typedef stk::StkFloat Float;
20
-
21
-
22
- class Frames;
23
-
24
21
  template <typename T> class SignalSamples;
25
22
 
26
23
 
@@ -31,11 +28,23 @@ namespace Beeps
31
28
  const float* const* channels,
32
29
  uint nsamples, uint nchannels, double sample_rate = 0);
33
30
 
31
+ uint Signals_tick (
32
+ Signals* signals,
33
+ std::function<void(stk::StkFrames*)> fun);
34
+
35
+ uint Signals_tick (
36
+ Signals* output, const Signals& input,
37
+ std::function<void(stk::StkFrames*, const stk::StkFrames&)> fun);
38
+
39
+ uint Signals_tick (
40
+ Signals* signals, uint start, uint length,
41
+ std::function<void(stk::StkFrames*)> fun);
42
+
34
43
  void Signals_clear (Signals* signals);
35
44
 
36
45
  void Signals_clear (Signals* signals, uint capacity);
37
46
 
38
- void Signals_resize (Signals* signals, uint nsamples, Float value);
47
+ void Signals_fill (Signals* signals, uint nsamples, Sample value);
39
48
 
40
49
  uint Signals_copy (Signals* to, const Signals& from, uint from_offset);
41
50
 
@@ -43,98 +52,30 @@ namespace Beeps
43
52
 
44
53
  void Signals_multiply (Signals* signals, const Signals& multiplier);
45
54
 
55
+ void Signals_offset_and_scale (
56
+ Signals* signals, float offset, float scale,
57
+ int channel = -1, uint start = 0, int end = -1);
58
+
46
59
  template <typename T>
47
60
  void Signals_write_samples (
48
61
  Signals* signals, const SignalSamples<T>& samples, long nsamples = -1);
49
62
 
50
63
  void Signals_set_nsamples (Signals* signals, uint nsamples);
51
64
 
52
- float Signals_get_seconds (const Signals& signals);
65
+ Sample* Signals_at ( Signals* signals, uint index, uint channel = 0);
66
+
67
+ const Sample* Signals_at (const Signals* signals, uint index, uint channel = 0);
53
68
 
54
- Frames* Signals_get_frames ( Signals* signals);
69
+ const Sample* Signals_at (const Signals& signals, uint index, uint channel = 0);
55
70
 
56
- const Frames* Signals_get_frames (const Signals* signals);
71
+ float Signals_get_seconds (const Signals& signals);
57
72
 
58
73
  void Signals_save (const Signals& signals, const char* path);
59
74
 
60
75
  Signals Signals_load (const char* path);
61
76
 
62
77
 
63
- class Frames : public stk::StkFrames
64
- {
65
-
66
- public:
67
-
68
- Frames (unsigned int nframes = 0, unsigned int nchannels = 1)
69
- : stk::StkFrames(nframes, nchannels)
70
- {
71
- }
72
-
73
- size_t slice (size_t start, size_t length)
74
- {
75
- assert(!saved_data_);
76
-
77
- size_t end = start + length;
78
- assert(start <= nFrames_ && end <= nFrames_);
79
-
80
- saved_data_ = data_;
81
- saved_nFrames_ = nFrames_;
82
- saved_size_ = size_;
83
- saved_bufferSize_ = bufferSize_;
84
-
85
- data_ += start * nChannels_;
86
- nFrames_ = length;
87
- size_ = length * nChannels_;
88
- bufferSize_ = size_;
89
-
90
- return end;
91
- }
92
-
93
- void unslice ()
94
- {
95
- assert(saved_data_);
96
-
97
- data_ = saved_data_;
98
- nFrames_ = saved_nFrames_;
99
- size_ = saved_size_;
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();
111
- }
112
-
113
- uint nchannels () const
114
- {
115
- return nChannels_;
116
- }
117
-
118
- uint nframes () const
119
- {
120
- return (uint) nFrames_;
121
- }
122
-
123
- const Float* data () const
124
- {
125
- return data_;
126
- }
127
-
128
- private:
129
-
130
- Float* saved_data_ = NULL;
131
-
132
- size_t saved_nFrames_ = 0, saved_size_ = 0, saved_bufferSize_ = 0;
133
-
134
- };// Frames
135
-
136
-
137
- template <typename T>
78
+ template <typename T = Sample>
138
79
  class SignalSamples
139
80
  {
140
81
 
@@ -154,9 +95,6 @@ namespace Beeps
154
95
  if (!signals)
155
96
  argument_error(__FILE__, __LINE__);
156
97
 
157
- const Frames* f = Signals_get_frames(&signals);
158
- assert(f);
159
-
160
98
  uint nsamples = signals.nsamples();
161
99
  uint nchannels = signals.nchannels();
162
100
 
@@ -165,8 +103,9 @@ namespace Beeps
165
103
 
166
104
  for (uint channel = 0; channel < nchannels; ++channel)
167
105
  {
168
- for (uint sample = 0; sample < nsamples; ++sample)
169
- samples.push_back((*f)(sample, channel));
106
+ const Sample* p = Signals_at(signals, 0);
107
+ for (uint i = 0; i < nsamples; ++i, p += nchannels)
108
+ samples.push_back(*p);
170
109
  }
171
110
 
172
111
  self->nsamples = nsamples;
data/src/sound.cpp CHANGED
@@ -7,8 +7,8 @@
7
7
  #include <algorithm>
8
8
  #include "Stk.h"
9
9
  #include "beeps/beeps.h"
10
- #include "beeps/exception.h"
11
10
  #include "beeps/generator.h"
11
+ #include "beeps/exception.h"
12
12
  #include "beeps/debug.h"
13
13
  #include "openal.h"
14
14
  #include "processor.h"
@@ -60,25 +60,23 @@ namespace Beeps
60
60
  double sample_rate = signals.sample_rate();
61
61
  uint nchannels = signals.nchannels();
62
62
  uint nsamples = signals.nsamples();
63
+ uint size = nsamples * nchannels;
63
64
  assert(sample_rate > 0 && nchannels > 0);
64
65
  if (nsamples <= 0) return 0;
65
66
 
66
- const Frames* frames = Signals_get_frames(&signals);
67
- assert(frames);
68
-
69
- std::vector<short> buffer;
70
- buffer.reserve(nsamples * nchannels);
71
- for (uint sample = 0; sample < nsamples; ++sample)
67
+ std::unique_ptr<short[]> buffer(new short[size]);
68
+ for (uint channel = 0; channel < nchannels; ++channel)
72
69
  {
73
- for (uint channel = 0; channel < nchannels; ++channel)
74
- buffer.push_back((*frames)(sample, channel) * SHRT_MAX);
70
+ const Sample* p = Signals_at(signals, 0, channel);
71
+ for (uint i = channel; i < size; i += nchannels, p += nchannels)
72
+ buffer[i] = *p * SHRT_MAX;
75
73
  }
76
74
 
77
75
  alBufferData(
78
76
  self->id,
79
77
  nchannels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
80
78
  &buffer[0],
81
- sizeof(short) * nsamples * nchannels,
79
+ sizeof(short) * size,
82
80
  sample_rate);
83
81
  OpenAL_check_error(__FILE__, __LINE__);
84
82
 
@@ -416,7 +414,11 @@ namespace Beeps
416
414
  for (int i = 0; i < 2; ++i)
417
415
  {
418
416
  SoundBuffer buffer(true);
419
- if (!process_stream(&buffer)) break;
417
+ if (!process_stream(&buffer))
418
+ {
419
+ source.stop();
420
+ break;
421
+ }
420
422
 
421
423
  source.queue(buffer);
422
424
  buffers.emplace_back(buffer);
@@ -425,7 +427,10 @@ namespace Beeps
425
427
 
426
428
  bool process_stream (SoundBuffer* buffer)
427
429
  {
428
- assert(buffer && processor && stream_context);
430
+ assert(buffer && processor);
431
+
432
+ if (!stream_context)
433
+ return false;
429
434
 
430
435
  Signals signals = stream_context->process_next(processor);
431
436
  if (stream_context->is_finished())
@@ -443,7 +448,10 @@ namespace Beeps
443
448
  return;
444
449
 
445
450
  if (!process_stream(&buffer))
451
+ {
452
+ source.stop();
446
453
  return;
454
+ }
447
455
 
448
456
  source.queue(buffer);
449
457
  if (source.state() == STOPPED) source.play();
@@ -687,13 +695,8 @@ namespace Beeps
687
695
 
688
696
  SoundData (
689
697
  Processor* processor, float seconds, uint nchannels, double sample_rate)
698
+ : signals(get_signals(processor, seconds, nchannels, sample_rate))
690
699
  {
691
- assert(
692
- processor && *processor &&
693
- seconds > 0 && nchannels > 0 && sample_rate > 0);
694
-
695
- StreamContext context(seconds * sample_rate, nchannels, sample_rate);
696
- this->signals = context.process_next(processor);
697
700
  }
698
701
 
699
702
  void attach_to (SoundPlayer* player) override
@@ -799,12 +802,17 @@ namespace Beeps
799
802
  {
800
803
  Processor::Ref ref = processor;
801
804
 
805
+ if (sample_rate == 0)
806
+ sample_rate = Beeps::sample_rate();
807
+
802
808
  if (!processor)
803
809
  argument_error(__FILE__, __LINE__);
804
810
  if (!*processor)
805
811
  argument_error(__FILE__, __LINE__);
806
-
807
- if (sample_rate <= 0) sample_rate = Beeps::sample_rate();
812
+ if (nchannels <= 0)
813
+ argument_error(__FILE__, __LINE__);
814
+ if (sample_rate <= 0)
815
+ argument_error(__FILE__, __LINE__);
808
816
 
809
817
  if (seconds > 0)
810
818
  self.reset(new SoundData(processor, seconds, nchannels, sample_rate));
data/src/time_stretch.cpp CHANGED
@@ -54,6 +54,12 @@ namespace Beeps
54
54
  return self->scale;
55
55
  }
56
56
 
57
+ TimeStretch::operator bool () const
58
+ {
59
+ if (!Super::operator bool()) return false;
60
+ return self->scale > 0;
61
+ }
62
+
57
63
  void
58
64
  TimeStretch::filter (Context* context, Signals* signals, uint* offset)
59
65
  {
@@ -81,11 +87,5 @@ namespace Beeps
81
87
  Signals_write_samples(signals, output);
82
88
  }
83
89
 
84
- TimeStretch::operator bool () const
85
- {
86
- if (!Super::operator bool()) return false;
87
- return self->scale > 0;
88
- }
89
-
90
90
 
91
91
  }// Beeps
@@ -154,7 +154,6 @@ namespace Beeps
154
154
  uint nchannels = format.nChannels;
155
155
  uint nsamples = bytes.size() / Bps / nchannels;
156
156
  Signals signals = Signals_create(nsamples, nchannels, format.nSamplesPerSec);
157
- Frames* frames = Signals_get_frames(&signals);
158
157
 
159
158
  for (uint channel = 0; channel < nchannels; ++channel)
160
159
  {
@@ -162,17 +161,19 @@ namespace Beeps
162
161
  {
163
162
  case 1:
164
163
  {
165
- const uchar* p = ((uchar*) &bytes[0]) + channel;
166
- for (uint sample = 0; sample < nsamples; ++sample, p += nchannels)
167
- (*frames)(sample, channel) = (*p - 128) / 128.f;
164
+ Sample* to_p = Signals_at(&signals, 0, channel);
165
+ const uchar* from_p = ((uchar*) &bytes[0]) + channel;
166
+ for (uint i = 0; i < nsamples; ++i, to_p += nchannels, from_p += nchannels)
167
+ *to_p = (*to_p - 128) / 128.f;
168
168
  break;
169
169
  }
170
170
 
171
171
  case 2:
172
172
  {
173
- const ushort* p = ((ushort*) &bytes[0]) + channel;
174
- for (uint sample = 0; sample < nsamples; ++sample, p += nchannels)
175
- (*frames)(sample, channel) = *p / 32768.f;
173
+ Sample* to_p = Signals_at(&signals, 0, channel);
174
+ const ushort* from_p = ((ushort*) &bytes[0]) + channel;
175
+ for (uint i = 0; i < nsamples; ++i, to_p += nchannels, from_p += nchannels)
176
+ *to_p = *from_p / 32768.f;
176
177
  break;
177
178
  }
178
179
  }
data/src/x_pass.h ADDED
@@ -0,0 +1,51 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __BEEPS_SRC_X_PASS_H__
4
+ #define __BEEPS_SRC_X_PASS_H__
5
+
6
+
7
+ #include <BiQuad.h>
8
+ #include "beeps/filter.h"
9
+ #include "signals.h"
10
+
11
+
12
+ namespace Beeps
13
+ {
14
+
15
+
16
+ struct xPassFilterData
17
+ {
18
+
19
+ stk::BiQuad biquad;
20
+
21
+ float cutoff_freq;
22
+
23
+ xPassFilterData (float cutoff_frequency)
24
+ : cutoff_freq(cutoff_frequency)
25
+ {
26
+ }
27
+
28
+ void tick (Signals* signals)
29
+ {
30
+ uint nchannels = signals->nchannels();
31
+ Signals filtered = Signals_create(
32
+ signals->nsamples(), nchannels, signals->sample_rate());
33
+
34
+ Signals_tick(
35
+ &filtered, *signals,
36
+ [&](stk::StkFrames* out, const stk::StkFrames& in)
37
+ {
38
+ for (uint ch = 0; ch < nchannels; ++ch)
39
+ biquad.tick(const_cast<stk::StkFrames&>(in), *out, ch, ch);
40
+ });
41
+
42
+ *signals = filtered;
43
+ }
44
+
45
+ };// xPassFilterData
46
+
47
+
48
+ }// Beeps
49
+
50
+
51
+ #endif//EOH
data/test/helper.rb CHANGED
@@ -8,3 +8,17 @@ require 'beeps'
8
8
  require 'test/unit'
9
9
 
10
10
  include Xot::Test
11
+
12
+
13
+ def get_samples(resolution_per_sec, processor, *a, seconds: 1, **k, &b)
14
+ resolution = resolution_per_sec * seconds
15
+ nsamples = Beeps.sample_rate * seconds
16
+ samples =
17
+ Beeps::Processor.get_signals(processor, *a, seconds: seconds, **k, &b).to_a
18
+ (0..resolution).to_a
19
+ .map {_1 / resolution.to_f}
20
+ .map {(nsamples * _1).to_i}
21
+ .map {_1 == 0 ? 0 : _1 - 1}
22
+ .map {samples[_1]}
23
+ .reverse.drop_while {_1.nil?}.reverse
24
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestAnalyser < Test::Unit::TestCase
5
+
6
+ B = Beeps
7
+
8
+ def analyser(...)
9
+ B::Analyser.new(...)
10
+ end
11
+
12
+ def osc(...)
13
+ B::Oscillator.new(...)
14
+ end
15
+
16
+ def test_initialize()
17
+ assert_equal 1024, analyser.fft_size
18
+ end
19
+
20
+ def test_process()
21
+ assert_equal(
22
+ get_samples(1000, osc(:sine)),
23
+ get_samples(1000, osc(:sine) >> analyser))
24
+ end
25
+
26
+ end# TestAnalyser
@@ -0,0 +1,55 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestEnvelope < Test::Unit::TestCase
5
+
6
+ B = Beeps
7
+
8
+ def envelope(on_sec = 0, off_sec, a: 0, d: 0, s: 1, r: 0)
9
+ B::Envelope.new attack: a, decay: d, sustain: s, release: r do
10
+ note_on on_sec
11
+ note_off off_sec
12
+ end
13
+ end
14
+
15
+ def const(value = 1)
16
+ B::Oscillator.new samples: [value]
17
+ end
18
+
19
+ def test_attack()
20
+ o = const(1) >> envelope(1, a: 0.1)
21
+ assert_each_in_delta [0] + [1] * 10, get_samples(10, o)
22
+ end
23
+
24
+ def test_decay_sustain()
25
+ o = const(1) >> envelope(1, d: 0.2, s: 0.8)
26
+ assert_each_in_delta [1, 0.9] + [0.8] * 9, get_samples(10, o)
27
+ end
28
+
29
+ def test_release()
30
+ o = const(1) >> envelope(0.8, r: 0.1)
31
+ assert_each_in_delta [1] * 9 + [0], get_samples(10, o)
32
+ end
33
+
34
+ def test_adsr()
35
+ o = const(1) >> envelope(1, a: 0.1, d: 0.2, s: 0.8, r: 0.4)
36
+ assert_each_in_delta(
37
+ [0, 1, 0.9] + [0.8] * 8 + [0.6, 0.4, 0.2, 0],
38
+ get_samples(10, o, seconds: 2))
39
+ end
40
+
41
+ def test_duration()
42
+ o = const(1) >> envelope(0.1)
43
+ assert_each_in_epsilon [1] * 2, get_samples(10, o, seconds: 2)
44
+
45
+ o = const(1) >> envelope(1)
46
+ assert_each_in_epsilon [1] * 11, get_samples(10, o, seconds: 2)
47
+
48
+ o = const(1) >> envelope(2)
49
+ assert_each_in_epsilon [1] * 21, get_samples(10, o, seconds: 2)
50
+
51
+ o = const(1) >> envelope(3)
52
+ assert_each_in_epsilon [1] * 21, get_samples(10, o, seconds: 2)
53
+ end
54
+
55
+ end# TestEnvelope
data/test/test_file_in.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'tempfile'
1
2
  require_relative 'helper'
2
3
 
3
4
 
@@ -5,7 +6,27 @@ class TestFileIn < Test::Unit::TestCase
5
6
 
6
7
  B = Beeps
7
8
 
8
- def test_initialize()
9
+ def filein(path)
10
+ B::FileIn.new path
11
+ end
12
+
13
+ def osc(...)
14
+ B::Oscillator.new(...)
15
+ end
16
+
17
+ def test_load_file()
18
+ Tempfile.create 'tmp.wav' do |file|
19
+ file.close
20
+
21
+ B::Sound.new(osc(:sine), 3).save(file.path)
22
+
23
+ assert_each_in_delta(
24
+ get_samples(100, osc(:sine)),
25
+ get_samples(100, filein(file.path)))
26
+ end
27
+ end
28
+
29
+ def test_file_not_found()
9
30
  assert_raise(B::BeepsError) {B::FileIn.new 'nofile.wav'}
10
31
  end
11
32
 
data/test/test_gain.rb ADDED
@@ -0,0 +1,28 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestGain < Test::Unit::TestCase
5
+
6
+ B = Beeps
7
+
8
+ def gain(...)
9
+ B::Gain.new(...)
10
+ end
11
+
12
+ def const(value = 1)
13
+ B::Oscillator.new samples: [value]
14
+ end
15
+
16
+ def test_initialize()
17
+ assert_equal 1, gain .gain
18
+ assert_equal 2, gain(2).gain
19
+ end
20
+
21
+ def test_process()
22
+ assert_equal [2] * 4, get_samples(3, const(1) >> gain(2))
23
+ assert_equal [0.5] * 4, get_samples(3, const(1) >> gain(0.5))
24
+ assert_equal [0] * 4, get_samples(3, const(1) >> gain(0))
25
+ assert_equal [-1] * 4, get_samples(3, const(1) >> gain(-1))
26
+ end
27
+
28
+ end# TestGain
@@ -0,0 +1,41 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestHighPass < Test::Unit::TestCase
5
+
6
+ B = Beeps
7
+
8
+ def hpass(...)
9
+ B::HighPass.new(...)
10
+ end
11
+
12
+ def test_initialize()
13
+ assert_equal 100, hpass .cutoff
14
+ assert_equal 1, hpass(1).cutoff
15
+ end
16
+
17
+ def test_cutoff_freqneucy()
18
+ f = hpass 1
19
+ assert_equal 1, f.cutoff_frequency
20
+ assert_equal 1, f.cutoff
21
+
22
+ f.cutoff_frequency = 2
23
+ assert_equal 2, f.cutoff_frequency
24
+ assert_equal 2, f.cutoff
25
+
26
+ f.cutoff_frequency 3
27
+ assert_equal 3, f.cutoff_frequency
28
+ assert_equal 3, f.cutoff
29
+
30
+ f.cutoff = 4
31
+ assert_equal 4, f.cutoff_frequency
32
+ assert_equal 4, f.cutoff
33
+
34
+ f.cutoff 5
35
+ assert_equal 5, f.cutoff_frequency
36
+ assert_equal 5, f.cutoff
37
+
38
+ assert_raise(ArgumentError) {f.cutoff 0}
39
+ end
40
+
41
+ end# TestHighPass
@@ -0,0 +1,41 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestLowPass < Test::Unit::TestCase
5
+
6
+ B = Beeps
7
+
8
+ def lpass(...)
9
+ B::LowPass.new(...)
10
+ end
11
+
12
+ def test_initialize()
13
+ assert_equal 1000, lpass .cutoff
14
+ assert_equal 1, lpass(1).cutoff
15
+ end
16
+
17
+ def test_cutoff_freqneucy()
18
+ f = lpass 1
19
+ assert_equal 1, f.cutoff_frequency
20
+ assert_equal 1, f.cutoff
21
+
22
+ f.cutoff_frequency = 2
23
+ assert_equal 2, f.cutoff_frequency
24
+ assert_equal 2, f.cutoff
25
+
26
+ f.cutoff_frequency 3
27
+ assert_equal 3, f.cutoff_frequency
28
+ assert_equal 3, f.cutoff
29
+
30
+ f.cutoff = 4
31
+ assert_equal 4, f.cutoff_frequency
32
+ assert_equal 4, f.cutoff
33
+
34
+ f.cutoff 5
35
+ assert_equal 5, f.cutoff_frequency
36
+ assert_equal 5, f.cutoff
37
+
38
+ assert_raise(ArgumentError) {f.cutoff 0}
39
+ end
40
+
41
+ end# TestLowPass