spcore 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.rdoc +14 -1
- data/README.rdoc +10 -2
- data/lib/spcore.rb +45 -14
- data/lib/spcore/{lib → core}/circular_buffer.rb +28 -1
- data/lib/spcore/core/constants.rb +7 -1
- data/lib/spcore/{lib → core}/delay_line.rb +15 -5
- data/lib/spcore/{lib → core}/envelope_detector.rb +13 -1
- data/lib/spcore/{lib → core}/oscillator.rb +33 -3
- data/lib/spcore/core/signal.rb +350 -0
- data/lib/spcore/filters/fir/dual_sinc_filter.rb +84 -0
- data/lib/spcore/filters/fir/fir.rb +87 -0
- data/lib/spcore/filters/fir/sinc_filter.rb +68 -0
- data/lib/spcore/{lib → filters/iir}/biquad_filter.rb +7 -0
- data/lib/spcore/{lib → filters/iir}/cookbook_allpass_filter.rb +2 -0
- data/lib/spcore/{lib → filters/iir}/cookbook_bandpass_filter.rb +2 -0
- data/lib/spcore/{lib → filters/iir}/cookbook_highpass_filter.rb +2 -0
- data/lib/spcore/{lib → filters/iir}/cookbook_lowpass_filter.rb +2 -0
- data/lib/spcore/{lib → filters/iir}/cookbook_notch_filter.rb +2 -0
- data/lib/spcore/interpolation/interpolation.rb +64 -0
- data/lib/spcore/resampling/discrete_resampling.rb +78 -0
- data/lib/spcore/resampling/hybrid_resampling.rb +30 -0
- data/lib/spcore/resampling/polynomial_resampling.rb +56 -0
- data/lib/spcore/transforms/dft.rb +47 -0
- data/lib/spcore/transforms/fft.rb +125 -0
- data/lib/spcore/{lib → util}/gain.rb +3 -0
- data/lib/spcore/{core → util}/limiters.rb +10 -1
- data/lib/spcore/util/plotter.rb +91 -0
- data/lib/spcore/{lib → util}/saturation.rb +2 -9
- data/lib/spcore/util/scale.rb +41 -0
- data/lib/spcore/util/signal_generator.rb +48 -0
- data/lib/spcore/version.rb +2 -1
- data/lib/spcore/windows/bartlett_hann_window.rb +15 -0
- data/lib/spcore/windows/bartlett_window.rb +13 -0
- data/lib/spcore/windows/blackman_harris_window.rb +14 -0
- data/lib/spcore/windows/blackman_nuttall_window.rb +14 -0
- data/lib/spcore/windows/blackman_window.rb +18 -0
- data/lib/spcore/windows/cosine_window.rb +13 -0
- data/lib/spcore/windows/flat_top_window.rb +27 -0
- data/lib/spcore/windows/gaussian_window.rb +15 -0
- data/lib/spcore/windows/hamming_window.rb +16 -0
- data/lib/spcore/windows/hann_window.rb +13 -0
- data/lib/spcore/windows/lanczos_window.rb +15 -0
- data/lib/spcore/windows/nuttall_window.rb +14 -0
- data/lib/spcore/windows/rectangular_window.rb +10 -0
- data/lib/spcore/windows/triangular_window.rb +14 -0
- data/spcore.gemspec +11 -3
- data/spec/{lib → core}/circular_buffer_spec.rb +0 -0
- data/spec/{lib → core}/delay_line_spec.rb +1 -1
- data/spec/{lib → core}/envelope_detector_spec.rb +3 -3
- data/spec/{lib → core}/oscillator_spec.rb +0 -0
- data/spec/filters/fir/dual_sinc_filter_spec.rb +64 -0
- data/spec/filters/fir/sinc_filter_spec.rb +57 -0
- data/spec/filters/iir/cookbook_filter_spec.rb +30 -0
- data/spec/interpolation/interpolation_spec.rb +49 -0
- data/spec/resampling/discrete_resampling_spec.rb +81 -0
- data/spec/resampling/hybrid_resampling_spec.rb +31 -0
- data/spec/resampling/polynomial_resampling_spec.rb +30 -0
- data/spec/transforms/dft_spec.rb +71 -0
- data/spec/transforms/fft_spec.rb +84 -0
- data/spec/{lib → util}/gain_spec.rb +2 -2
- data/spec/{core → util}/limiters_spec.rb +0 -0
- data/spec/{lib → util}/saturate_spec.rb +0 -0
- data/spec/util/signal_generator_spec.rb +54 -0
- data/spec/windows/window_spec.rb +33 -0
- metadata +90 -42
- data/lib/spcore/lib/interpolation.rb +0 -15
- data/spec/lib/cookbook_filter_spec.rb +0 -44
- data/spec/lib/interpolation_spec.rb +0 -21
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'gnuplot'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
describe 'cookbook filter' do
|
6
|
+
it 'should produce a nice frequency response graph' do
|
7
|
+
#sample_rate = 4000.0
|
8
|
+
#crit_freq = 400.0
|
9
|
+
#min_test_freq = 10.0
|
10
|
+
#max_test_freq = (sample_rate / 2.0) - 1.0
|
11
|
+
#bw = 0.3
|
12
|
+
#
|
13
|
+
#[SPCore::CookbookLowpassFilter, SPCore::CookbookHighpassFilter, SPCore::CookbookBandpassFilter].each do |filter_class|
|
14
|
+
# filter = filter_class.new sample_rate
|
15
|
+
# filter.set_critical_freq_and_bw crit_freq, bw
|
16
|
+
#
|
17
|
+
# freq_response = {}
|
18
|
+
# Scale.exponential(min_test_freq..max_test_freq, 200).each do |freq|
|
19
|
+
# mag = filter.get_freq_magnitude_response freq
|
20
|
+
# freq_response[freq] = SPCore::Gain.linear_to_db(mag)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# plotter = Plotter.new(
|
24
|
+
# :title => "Frequency Magnitude Response for #{filter_class} with critical freq of #{crit_freq}",
|
25
|
+
# :logscale => "x"
|
26
|
+
# )
|
27
|
+
# plotter.plot_2d "magnitude (dB)" => freq_response
|
28
|
+
#end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'benchmark'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
4
|
+
|
5
|
+
describe SPCore::Interpolation do
|
6
|
+
context '.linear' do
|
7
|
+
it 'should interpolate floating-point values' do
|
8
|
+
result = SPCore::Interpolation.linear 2.0, 4.0, 0.5
|
9
|
+
result.should eq(3.0)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should interpolate integer values' do
|
13
|
+
result = SPCore::Interpolation.linear 20, 40, 0.5
|
14
|
+
result.should eq(30)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context '.cubic_hermite' do
|
19
|
+
it 'should look like...' do
|
20
|
+
y0, y1, y2, y3 = 1.75, 1, 0.75, -1.5
|
21
|
+
|
22
|
+
x_ary = []
|
23
|
+
y_ary = []
|
24
|
+
|
25
|
+
(0.0..1.0).step(0.05) do |x|
|
26
|
+
y = SPCore::Interpolation.cubic_hermite y0, y1, y2, y3, x
|
27
|
+
x_ary << x
|
28
|
+
y_ary << y
|
29
|
+
end
|
30
|
+
|
31
|
+
#Gnuplot.open do |gp|
|
32
|
+
# Gnuplot::Plot.new(gp) do |plot|
|
33
|
+
# plot.title "interpolated values"
|
34
|
+
# plot.xlabel "x"
|
35
|
+
# plot.ylabel "f(x)"
|
36
|
+
#
|
37
|
+
# plot.data = [
|
38
|
+
# Gnuplot::DataSet.new( [ x_ary, y_ary ] ) { |ds|
|
39
|
+
# ds.with = "linespoints"
|
40
|
+
# ds.title = "cubic hermite"
|
41
|
+
# ds.linewidth = 1
|
42
|
+
# }
|
43
|
+
# ]
|
44
|
+
# end
|
45
|
+
#end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'gnuplot'
|
3
|
+
|
4
|
+
describe SPCore::DiscreteResampling do
|
5
|
+
|
6
|
+
context '.upsample' do
|
7
|
+
it 'should produce output signal with the same max frequency (put through forward FFT)' do
|
8
|
+
sample_rate = 400.0
|
9
|
+
test_freq = 10.0
|
10
|
+
size = 64
|
11
|
+
upsample_factor = 4
|
12
|
+
order = (sample_rate / test_freq).to_i
|
13
|
+
|
14
|
+
signal1 = SignalGenerator.new(:sample_rate => sample_rate, :size => size).make_signal [test_freq]
|
15
|
+
signal1 *= BlackmanWindow.new(size).data
|
16
|
+
signal2 = signal1.clone.upsample_discrete upsample_factor, order
|
17
|
+
|
18
|
+
#plotter = Plotter.new(:title => "Discrete upsampling by #{upsample_factor}")
|
19
|
+
#plotter.plot_1d("original signal" => signal1.data, "upsampled signal" => signal2.data)
|
20
|
+
|
21
|
+
signal2.size.should eq(signal1.size * upsample_factor)
|
22
|
+
|
23
|
+
max_freq1 = signal1.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
24
|
+
max_freq2 = signal2.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
25
|
+
|
26
|
+
percent_error = (max_freq1 - max_freq2).abs / max_freq1
|
27
|
+
percent_error.should be_within(0.1).of(0.0)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context '.downsample' do
|
32
|
+
it 'should produce output signal with the same max frequency (put through forward FFT)' do
|
33
|
+
sample_rate = 400.0
|
34
|
+
test_freq = 10.0
|
35
|
+
size = 128
|
36
|
+
downsample_factor = 4
|
37
|
+
order = (sample_rate / test_freq).to_i
|
38
|
+
|
39
|
+
signal1 = SignalGenerator.new(:sample_rate => sample_rate, :size => size).make_signal [test_freq]
|
40
|
+
signal1 *= BlackmanWindow.new(size).data
|
41
|
+
signal2 = signal1.clone.downsample_discrete downsample_factor, order
|
42
|
+
|
43
|
+
#plotter = Plotter.new(:title => "Discrete downsampling by #{downsample_factor}")
|
44
|
+
#plotter.plot_1d("original signal" => signal1.data, "downsampled signal" => signal2.data)
|
45
|
+
|
46
|
+
signal2.size.should eq(signal1.size / downsample_factor)
|
47
|
+
|
48
|
+
max_freq1 = signal1.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
49
|
+
max_freq2 = signal2.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
50
|
+
|
51
|
+
percent_error = (max_freq1 - max_freq2).abs / max_freq1
|
52
|
+
percent_error.should be_within(0.1).of(0.0)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context '.resample' do
|
57
|
+
it 'should produce output signal with the same max frequency (put through forward FFT)' do
|
58
|
+
sample_rate = 400.0
|
59
|
+
test_freq = 10.0
|
60
|
+
size = 64
|
61
|
+
upsample_factor = 4
|
62
|
+
downsample_factor = 4
|
63
|
+
order = (sample_rate / test_freq).to_i
|
64
|
+
|
65
|
+
signal1 = SignalGenerator.new(:sample_rate => sample_rate, :size => size).make_signal [test_freq]
|
66
|
+
signal1 *= BlackmanWindow.new(size).data
|
67
|
+
signal2 = signal1.clone.resample_discrete upsample_factor, downsample_factor, order
|
68
|
+
|
69
|
+
#plotter = Plotter.new(:title => "Discrete resampling, up by #{upsampling_factor}, down by #{downsample_factor}")
|
70
|
+
#plotter.plot_1d("original signal" => signal1.data, "resampled signal" => signal2.data)
|
71
|
+
|
72
|
+
signal2.size.should eq(signal1.size * upsample_factor / downsample_factor)
|
73
|
+
|
74
|
+
max_freq1 = signal1.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
75
|
+
max_freq2 = signal2.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
76
|
+
|
77
|
+
percent_error = (max_freq1 - max_freq2).abs / max_freq1
|
78
|
+
percent_error.should be_within(0.1).of(0.0)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'gnuplot'
|
3
|
+
|
4
|
+
describe SPCore::HybridResampling do
|
5
|
+
|
6
|
+
context '.resample' do
|
7
|
+
it 'should produce output signal with the same max frequency (put through forward FFT)' do
|
8
|
+
sample_rate = 400.0
|
9
|
+
test_freq = 10.0
|
10
|
+
size = 64
|
11
|
+
upsample_factor = 4
|
12
|
+
downsample_factor = 4
|
13
|
+
order = (sample_rate / test_freq).to_i
|
14
|
+
|
15
|
+
signal1 = SignalGenerator.new(:sample_rate => sample_rate, :size => size).make_signal [test_freq]
|
16
|
+
signal1 *= BlackmanWindow.new(size).data
|
17
|
+
signal2 = signal1.clone.resample_hybrid upsample_factor, downsample_factor, order
|
18
|
+
|
19
|
+
#plotter = Plotter.new(:title => "Discrete resampling, up by #{upsampling_factor}, down by #{downsample_factor}")
|
20
|
+
#plotter.plot_1d("original signal" => signal1.data, "resampled signal" => signal2.data)
|
21
|
+
|
22
|
+
signal2.size.should eq(signal1.size * upsample_factor / downsample_factor)
|
23
|
+
|
24
|
+
max_freq1 = signal1.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
25
|
+
max_freq2 = signal2.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
26
|
+
|
27
|
+
percent_error = (max_freq1 - max_freq2).abs / max_freq1
|
28
|
+
percent_error.should be_within(0.1).of(0.0)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'gnuplot'
|
3
|
+
|
4
|
+
describe SPCore::PolynomialResampling do
|
5
|
+
|
6
|
+
context '.upsample' do
|
7
|
+
it 'should produce output signal with the same max frequency (put through forward DFT)' do
|
8
|
+
sample_rate = 400.0
|
9
|
+
test_freq = 10.0
|
10
|
+
size = (sample_rate * 5.0 / test_freq).to_i
|
11
|
+
upsample_factor = 2.5
|
12
|
+
|
13
|
+
generator = SignalGenerator.new :sample_rate => sample_rate, :size => size
|
14
|
+
signal1 = generator.make_signal [test_freq]
|
15
|
+
signal2 = signal1.clone.upsample_polynomial upsample_factor
|
16
|
+
|
17
|
+
#plotter = Plotter.new(:title => "Polynomial upsampling by #{upsample_factor}")
|
18
|
+
#plotter.plot_1d("original signal" => signal1.data, "upsampled signal" => signal2.data)
|
19
|
+
|
20
|
+
signal2.size.should eq(signal1.size * upsample_factor)
|
21
|
+
|
22
|
+
max_freq1 = signal1.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
23
|
+
max_freq2 = signal2.freq_magnitudes.max_by{|freq, mag| mag }[0]
|
24
|
+
|
25
|
+
percent_error = (max_freq1 - max_freq2).abs / max_freq1
|
26
|
+
percent_error.should be_within(0.1).of(0.0)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'pry'
|
3
|
+
require 'gnuplot'
|
4
|
+
|
5
|
+
describe SPCore::DFT do
|
6
|
+
context '.forward' do
|
7
|
+
|
8
|
+
it 'should produce a freq magnitude response peak that is within 10 percent of the test freq' do
|
9
|
+
dft_size = 64
|
10
|
+
sample_rate = 400.0
|
11
|
+
|
12
|
+
test_freqs = [
|
13
|
+
20.0,
|
14
|
+
40.0,
|
15
|
+
]
|
16
|
+
|
17
|
+
test_freqs.each do |freq|
|
18
|
+
signal = SignalGenerator.new(:sample_rate => sample_rate, :size => dft_size).make_signal([freq])
|
19
|
+
signal *= BlackmanHarrisWindow.new(dft_size).data
|
20
|
+
|
21
|
+
output = DFT.forward signal.data
|
22
|
+
output = output[0...(output.size / 2)] # skip second half
|
23
|
+
output = output.map { |x| x.magnitude } # map complex values to magnitude
|
24
|
+
|
25
|
+
freq_magnitudes = {}
|
26
|
+
output.each_index do |i|
|
27
|
+
f = (sample_rate * i) / dft_size
|
28
|
+
freq_magnitudes[f] = output[i]
|
29
|
+
end
|
30
|
+
|
31
|
+
max_freq = freq_magnitudes.max_by {|f,mag| mag}[0]
|
32
|
+
percent_err = (max_freq - freq).abs / freq
|
33
|
+
percent_err.should be_within(0.10).of(0.0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context '.inverse' do
|
39
|
+
|
40
|
+
it 'should produce a near-identical signal to the original sent into the forward DFT (with energy that is within 10 percent error of original signal)' do
|
41
|
+
dft_size = 32
|
42
|
+
sample_rate = 400.0
|
43
|
+
|
44
|
+
test_freqs = [
|
45
|
+
20.0,
|
46
|
+
40.0,
|
47
|
+
]
|
48
|
+
|
49
|
+
test_freqs.each do |freq|
|
50
|
+
input = SignalGenerator.new(:sample_rate => sample_rate, :size => dft_size).make_signal([freq])
|
51
|
+
input *= BlackmanHarrisWindow.new(dft_size).data
|
52
|
+
|
53
|
+
output = DFT.forward input.data
|
54
|
+
input2 = DFT.inverse output
|
55
|
+
|
56
|
+
energy1 = input.energy
|
57
|
+
energy2 = input2.inject(0.0){|sum,x| sum + (x * x)}
|
58
|
+
|
59
|
+
percent_err = (energy2 - energy1).abs / energy1
|
60
|
+
percent_err.should be_within(0.10).of(0.0)
|
61
|
+
|
62
|
+
#Plotter.new(
|
63
|
+
# :title => "#{dft_size}-point DFT on #{freq} Hz sine wave signal",
|
64
|
+
# :xlabel => "frequency (Hz)",
|
65
|
+
# :ylabel => "magnitude response",
|
66
|
+
#).plot_1d("input1" => input.data, "input2" => input2)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'pry'
|
3
|
+
require 'gnuplot'
|
4
|
+
|
5
|
+
describe SPCore::FFT do
|
6
|
+
context '.forward' do
|
7
|
+
it 'should produce a freq magnitude response peak that is within 10 percent of the test freq' do
|
8
|
+
fft_size = 64
|
9
|
+
sample_rate = 400.0
|
10
|
+
|
11
|
+
test_freqs = [
|
12
|
+
20.0,
|
13
|
+
40.0,
|
14
|
+
]
|
15
|
+
|
16
|
+
test_freqs.each do |freq|
|
17
|
+
osc = Oscillator.new(:frequency => freq, :sample_rate => sample_rate)
|
18
|
+
|
19
|
+
input_size = fft_size
|
20
|
+
|
21
|
+
input = Array.new(input_size)
|
22
|
+
window = BlackmanHarrisWindow.new(input_size)
|
23
|
+
|
24
|
+
input_size.times do |i|
|
25
|
+
input[i] = osc.sample * window.data[i]
|
26
|
+
end
|
27
|
+
|
28
|
+
output = FFT.forward input
|
29
|
+
output = output[0...(output.size / 2)]
|
30
|
+
output = output.map { |x| x.magnitude } # map complex values to magnitude
|
31
|
+
|
32
|
+
magn_response = {}
|
33
|
+
output.each_index do |n|
|
34
|
+
f = (sample_rate * n) / (output.size * 2)
|
35
|
+
magn_response[f] = output[n]
|
36
|
+
end
|
37
|
+
|
38
|
+
max_freq = magn_response.max_by {|f,magn| magn }[0]
|
39
|
+
percent_err = (max_freq - freq).abs / freq
|
40
|
+
percent_err.should be_within(0.10).of(0.0)
|
41
|
+
|
42
|
+
#Plotter.new(
|
43
|
+
# :title => "#{input_size}-point FFT on #{freq} Hz sine wave signal",
|
44
|
+
# :xlabel => "frequency (Hz)",
|
45
|
+
# :ylabel => "magnitude response",
|
46
|
+
#).plot_2d("magnitude response" => magn_response)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context '.inverse' do
|
52
|
+
|
53
|
+
it 'should produce a near-identical signal to the original sent into the forward DFT (with energy that is within 10 percent error of original signal)' do
|
54
|
+
fft_size = 32
|
55
|
+
sample_rate = 400.0
|
56
|
+
|
57
|
+
test_freqs = [
|
58
|
+
20.0,
|
59
|
+
40.0,
|
60
|
+
]
|
61
|
+
|
62
|
+
test_freqs.each do |freq|
|
63
|
+
input = SignalGenerator.new(:sample_rate => sample_rate, :size => fft_size).make_signal([freq])
|
64
|
+
input *= BlackmanHarrisWindow.new(fft_size).data
|
65
|
+
|
66
|
+
output = FFT.forward input.data
|
67
|
+
input2 = FFT.inverse output
|
68
|
+
|
69
|
+
energy1 = input.energy
|
70
|
+
energy2 = input2.inject(0.0){|sum,x| sum + (x * x)}
|
71
|
+
|
72
|
+
percent_err = (energy2 - energy1).abs / energy1
|
73
|
+
percent_err.should be_within(0.10).of(0.0)
|
74
|
+
|
75
|
+
#Plotter.new(
|
76
|
+
# :title => "#{fft_size}-point FFT on #{freq} Hz sine wave signal",
|
77
|
+
# :xlabel => "frequency (Hz)",
|
78
|
+
# :ylabel => "magnitude response",
|
79
|
+
#).plot_1d("input1" => input.data, "input2" => input2)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -19,7 +19,7 @@ describe SPCore::Gain do
|
|
19
19
|
|
20
20
|
it 'should prove to be the inverse of .db_to_linear' do
|
21
21
|
20.times do
|
22
|
-
x = SPCore::Interpolation.linear(
|
22
|
+
x = SPCore::Interpolation.linear(-SPCore::Gain::MAX_DB_ABS, SPCore::Gain::MAX_DB_ABS, rand)
|
23
23
|
y = SPCore::Gain::db_to_linear(x)
|
24
24
|
z = SPCore::Gain::linear_to_db(y)
|
25
25
|
((z - x).abs / x).should be_within(1e-5).of(0.0)
|
@@ -38,7 +38,7 @@ describe SPCore::Gain do
|
|
38
38
|
20.times do
|
39
39
|
max_gain_linear = SPCore::Gain::db_to_linear(SPCore::Gain::MAX_DB_ABS)
|
40
40
|
min_gain_linear = SPCore::Gain::db_to_linear(-SPCore::Gain::MAX_DB_ABS)
|
41
|
-
x = SPCore::Interpolation.linear(
|
41
|
+
x = SPCore::Interpolation.linear(min_gain_linear, max_gain_linear, rand)
|
42
42
|
y = SPCore::Gain::linear_to_db(x)
|
43
43
|
z = SPCore::Gain::db_to_linear(y)
|
44
44
|
((z - x).abs / x).should be_within(1e-5).of(0.0)
|
File without changes
|
File without changes
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe SPCore::SignalGenerator do
|
4
|
+
before :all do
|
5
|
+
@sample_rate = 600.0
|
6
|
+
@test_freqs = [
|
7
|
+
65.0, 100.0, 250.0
|
8
|
+
]
|
9
|
+
end
|
10
|
+
|
11
|
+
context '.make_signal' do
|
12
|
+
context 'one freq at a time' do
|
13
|
+
it 'should produce the same output as a plain Oscillator' do
|
14
|
+
size = 60
|
15
|
+
generator = SignalGenerator.new :sample_rate => @sample_rate, :size => size
|
16
|
+
|
17
|
+
@test_freqs.each do |freq|
|
18
|
+
signal = generator.make_signal [freq]
|
19
|
+
|
20
|
+
osc = Oscillator.new(:sample_rate => @sample_rate, :frequency => freq)
|
21
|
+
osc_output = Array.new(size)
|
22
|
+
size.times do |i|
|
23
|
+
osc_output[i] = osc.sample
|
24
|
+
end
|
25
|
+
|
26
|
+
signal.data.should eq(osc_output)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'many freqs at a time' do
|
32
|
+
it 'should produce the same output as equivalent plain Oscillators' do
|
33
|
+
size = 60
|
34
|
+
generator = SignalGenerator.new :sample_rate => @sample_rate, :size => size
|
35
|
+
|
36
|
+
oscs = []
|
37
|
+
@test_freqs.each do |freq|
|
38
|
+
oscs.push Oscillator.new(:sample_rate => @sample_rate, :frequency => freq)
|
39
|
+
end
|
40
|
+
|
41
|
+
signal = generator.make_signal @test_freqs
|
42
|
+
|
43
|
+
osc_output = Array.new(size, 0.0)
|
44
|
+
size.times do |i|
|
45
|
+
oscs.each do |osc|
|
46
|
+
osc_output[i] += osc.sample
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
signal.data.should eq(osc_output)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|