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.
- checksums.yaml +4 -4
- data/.doc/ext/beeps/beeps.cpp +7 -0
- data/.doc/ext/beeps/high_pass.cpp +63 -0
- data/.doc/ext/beeps/low_pass.cpp +63 -0
- data/.doc/ext/beeps/native.cpp +8 -0
- data/.doc/ext/beeps/oscillator.cpp +87 -10
- data/.doc/ext/beeps/processor.cpp +14 -1
- data/.doc/ext/beeps/reverb.cpp +99 -0
- data/.doc/ext/beeps/signals.cpp +128 -0
- data/ChangeLog.md +24 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/beeps.gemspec +2 -2
- data/ext/beeps/beeps.cpp +8 -0
- data/ext/beeps/high_pass.cpp +66 -0
- data/ext/beeps/low_pass.cpp +66 -0
- data/ext/beeps/native.cpp +8 -0
- data/ext/beeps/oscillator.cpp +95 -12
- data/ext/beeps/processor.cpp +15 -1
- data/ext/beeps/reverb.cpp +106 -0
- data/ext/beeps/signals.cpp +136 -0
- data/include/beeps/beeps.h +2 -2
- data/include/beeps/defs.h +3 -0
- data/include/beeps/filter.h +118 -17
- data/include/beeps/generator.h +50 -17
- data/include/beeps/processor.h +23 -6
- data/include/beeps/ruby/filter.h +33 -0
- data/include/beeps/ruby/signals.h +40 -0
- data/include/beeps/signals.h +1 -1
- data/lib/beeps/processor.rb +46 -1
- data/lib/beeps/signals.rb +19 -0
- data/lib/beeps.rb +1 -0
- data/src/analyser.cpp +34 -37
- data/src/beeps.cpp +7 -6
- data/src/envelope.cpp +60 -46
- data/src/file_in.cpp +6 -6
- data/src/gain.cpp +5 -5
- data/src/high_pass.cpp +57 -0
- data/src/low_pass.cpp +57 -0
- data/src/mic_in.cpp +16 -14
- data/src/mixer.cpp +38 -20
- data/src/oscillator.cpp +260 -168
- data/src/pitch_shift.cpp +6 -6
- data/src/processor.cpp +118 -11
- data/src/processor.h +8 -0
- data/src/reverb.cpp +124 -0
- data/src/sequencer.cpp +18 -14
- data/src/signals.cpp +264 -106
- data/src/signals.h +28 -89
- data/src/sound.cpp +28 -20
- data/src/time_stretch.cpp +6 -6
- data/src/win32/signals.cpp +8 -7
- data/src/x_pass.h +51 -0
- data/test/helper.rb +14 -0
- data/test/test_analyser.rb +26 -0
- data/test/test_envelope.rb +55 -0
- data/test/test_file_in.rb +22 -1
- data/test/test_gain.rb +28 -0
- data/test/test_high_pass.rb +41 -0
- data/test/test_low_pass.rb +41 -0
- data/test/test_mixer.rb +63 -0
- data/test/test_oscillator.rb +58 -0
- data/test/test_pitch_shift.rb +32 -0
- data/test/test_processor.rb +7 -0
- data/test/test_signals.rb +60 -0
- data/test/test_time_stretch.rb +36 -0
- 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
|
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
|
-
|
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
|
-
|
69
|
+
const Sample* Signals_at (const Signals& signals, uint index, uint channel = 0);
|
55
70
|
|
56
|
-
|
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
|
-
|
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
|
-
|
169
|
-
|
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
|
-
|
67
|
-
|
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
|
-
|
74
|
-
|
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) *
|
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))
|
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
|
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
|
-
|
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
|
data/src/win32/signals.cpp
CHANGED
@@ -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
|
-
|
166
|
-
|
167
|
-
|
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
|
-
|
174
|
-
|
175
|
-
|
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
|
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
|