spcore 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ require 'pry'
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ describe SPCore::Gain do
5
+ before :all do
6
+ @conversions = [
7
+ { :linear => Math::sqrt(2.0), :db => 3.01 },
8
+ { :linear => 2.0, :db => 6.02 },
9
+ { :linear => 4.0, :db => 12.04 },
10
+ ]
11
+ end
12
+
13
+ describe '.db_to_linear' do
14
+ it 'should convert decibel (logarithmic) unit to linear' do
15
+ @conversions.each do |conversion|
16
+ SPCore::Gain::db_to_linear(conversion[:db]).should be_within(0.01).of(conversion[:linear])
17
+ end
18
+ end
19
+
20
+ it 'should prove to be the inverse of .db_to_linear' do
21
+ 20.times do
22
+ x = SPCore::Interpolation.linear(0.0, -SPCore::Gain::MAX_DB_ABS, 1.0, SPCore::Gain::MAX_DB_ABS, rand)
23
+ y = SPCore::Gain::db_to_linear(x)
24
+ z = SPCore::Gain::linear_to_db(y)
25
+ ((z - x).abs / x).should be_within(1e-5).of(0.0)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '.linear_to_db' do
31
+ it 'should convert linear unit to decibel (logarithmic)' do
32
+ @conversions.each do |conversion|
33
+ SPCore::Gain::linear_to_db(conversion[:linear]).should be_within(0.01).of(conversion[:db])
34
+ end
35
+ end
36
+
37
+ it 'should prove to be the inverse of .db_to_linear' do
38
+ 20.times do
39
+ max_gain_linear = SPCore::Gain::db_to_linear(SPCore::Gain::MAX_DB_ABS)
40
+ min_gain_linear = SPCore::Gain::db_to_linear(-SPCore::Gain::MAX_DB_ABS)
41
+ x = SPCore::Interpolation.linear(0.0, min_gain_linear, 1.0, max_gain_linear, rand)
42
+ y = SPCore::Gain::linear_to_db(x)
43
+ z = SPCore::Gain::db_to_linear(y)
44
+ ((z - x).abs / x).should be_within(1e-5).of(0.0)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SPCore::Interpolation do
4
+ context '.interpolate_linear' do
5
+ it 'should interpolate floating-point values' do
6
+ x1, y1 = 0.0, 2.0
7
+ x2, y2 = 1.0, 4.0
8
+ x3, y3 = 0.5, 3.0
9
+ result = SPCore::Interpolation.linear x1, y1, x2, y2, x3
10
+ result.should eq(y3)
11
+ end
12
+
13
+ it 'should interpolate integer values' do
14
+ x1, y1 = 0, 20
15
+ x2, y2 = 10, 40
16
+ x3, y3 = 5, 30
17
+ result = SPCore::Interpolation.linear x1, y1, x2, y2, x3
18
+ result.should eq(y3)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,146 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'gnuplot'
3
+ require 'pry'
4
+
5
+ describe SPCore::Oscillator do
6
+ #it 'should look like a ...' do
7
+ # sample_rate = 44000.0
8
+ # test_freq = 100.0
9
+ # osc = SPCore::Oscillator.new :sample_rate => sample_rate, :frequency => test_freq, :wave_type => SPCore::Oscillator::WAVE_SQUARE
10
+ # N = (5 * sample_rate / test_freq).to_i
11
+ # period = 1.0 / N
12
+ #
13
+ # x, y = [], []
14
+ # N.times do |n|
15
+ # x << (n * period)
16
+ # y << osc.sample
17
+ # end
18
+ #
19
+ # Gnuplot.open do |gp|
20
+ # Gnuplot::Plot.new(gp) do |plot|
21
+ # plot.title "#{osc.frequency} Hz #{osc.wave_type} oscillator"
22
+ # plot.xlabel "time (x)"
23
+ # plot.ylabel "f(x)"
24
+ #
25
+ # plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds|
26
+ # ds.with = "linespoints"
27
+ # #ds.linewidth = 4
28
+ # end
29
+ # end
30
+ # end
31
+ #
32
+ #end
33
+
34
+ before :each do
35
+ @sample_rate = 40000.0
36
+ @freqs = [ 20.0, 200.0, 400.0 ]
37
+ end
38
+
39
+ describe '#triangle' do
40
+ it "should produce increasing samples during first half-period, and decreasing samples during the second half-period" do
41
+ @freqs.each do |freq|
42
+ wave = SPCore::Oscillator.new(
43
+ :sample_rate => @sample_rate,
44
+ :frequency => freq,
45
+ :wave_type => SPCore::Oscillator::WAVE_TRIANGLE
46
+ )
47
+
48
+ samples_in_half_period = @sample_rate / (2.0 * freq)
49
+
50
+ prev = wave.sample
51
+ prev.should eq(-1)
52
+
53
+ (samples_in_half_period - 1).to_i.times do
54
+ current = wave.sample
55
+ current.should be > prev
56
+ prev = current
57
+ end
58
+
59
+ prev = wave.sample
60
+ prev.should be_within(0.01).of(1)
61
+
62
+ (samples_in_half_period - 1).to_i.times do
63
+ current = wave.sample
64
+ current.should be < prev
65
+ prev = current
66
+ end
67
+
68
+ wave.sample.should be_within(0.01).of(-1)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe '#square' do
74
+ it "should produce 1 during first half-period, and -1 during second half-period" do
75
+ @freqs.each do |freq|
76
+ wave = SPCore::Oscillator.new(
77
+ :sample_rate => @sample_rate,
78
+ :frequency => freq,
79
+ :wave_type => SPCore::Oscillator::WAVE_SQUARE
80
+ )
81
+
82
+ samples_in_half_period = @sample_rate / (2.0 * freq)
83
+ fails = 0
84
+
85
+ samples_in_half_period.to_i.times do
86
+ if wave.sample != 1.0 then fails += 1 end
87
+ end
88
+
89
+ samples_in_half_period.to_i.times do
90
+ if wave.sample != -1.0 then fails += 1 end
91
+ end
92
+
93
+ (fails <= 2).should be_true
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '#sawtooth' do
99
+ it "should produce increasing samples" do
100
+
101
+ @freqs.each do |freq|
102
+ wave = SPCore::Oscillator.new(
103
+ :sample_rate => @sample_rate,
104
+ :frequency => freq,
105
+ :wave_type => SPCore::Oscillator::WAVE_SAWTOOTH
106
+ )
107
+
108
+ samples_in_period = (@sample_rate / freq).to_i
109
+ fails = 0
110
+
111
+ prev = wave.sample
112
+ (samples_in_period - 1).times do
113
+ current = wave.sample
114
+ if current < prev
115
+ fails += 1
116
+ end
117
+ prev = current
118
+ end
119
+
120
+ fails.should be <= 3
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#sine' do
126
+ it "should produce zero during every half-period, and non-zeros between" do
127
+ @freqs.each do |freq|
128
+ wave = SPCore::Oscillator.new(
129
+ :sample_rate => @sample_rate,
130
+ :frequency => freq,
131
+ :wave_type => SPCore::Oscillator::WAVE_SINE
132
+ )
133
+
134
+ samples_in_half_period = @sample_rate / (2.0 * freq)
135
+
136
+ wave.sample.should be_within(0.01).of(0.0)
137
+ (samples_in_half_period - 1).to_i.times do
138
+ wave.sample.should_not eq(0)
139
+ end
140
+ wave.sample.should be_within(0.01).of(0.0)
141
+
142
+ end
143
+ end
144
+ end
145
+
146
+ end
@@ -0,0 +1,100 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'gnuplot'
3
+
4
+ describe SPCore::Saturation do
5
+ describe '.tanh' do
6
+ it 'should not saturate below the threshold' do
7
+ t = 1.0 # threshold
8
+
9
+ x_data = []
10
+ y_data = []
11
+ z_data = []
12
+
13
+ osc = SPCore::Oscillator.new(
14
+ :sample_rate => 100.0,
15
+ :frequency => 1.0,
16
+ :wave_type => SPCore::Oscillator::WAVE_SINE,
17
+ :amplitude => 2.5
18
+ )
19
+
20
+ (4 * osc.sample_rate / osc.frequency).to_i.times do |n|
21
+ x = n / osc.sample_rate
22
+ y = osc.sample
23
+ z = SPCore::Saturation.sigmoid y, t
24
+
25
+ if y.abs < t
26
+ z.should eq(y)
27
+ end
28
+
29
+ x_data << x
30
+ y_data << y
31
+ z_data << z
32
+ end
33
+
34
+ #Gnuplot.open do |gp|
35
+ # Gnuplot::Plot.new(gp) do |plot|
36
+ # plot.title "signal and saturated signal"
37
+ # plot.xlabel "input"
38
+ # plot.ylabel "output"
39
+ #
40
+ # plot.data = [
41
+ # Gnuplot::DataSet.new( [x_data, y_data] ){ |ds|
42
+ # ds.with = "lines"
43
+ # ds.title = "Signal"
44
+ # #ds.linewidth = 4
45
+ # },
46
+ # Gnuplot::DataSet.new( [x_data, z_data] ){ |ds|
47
+ # ds.with = "lines"
48
+ # ds.title = "Saturated signal"
49
+ # #ds.linewidth = 4
50
+ # }
51
+ # ]
52
+ # end
53
+ #end
54
+ end
55
+ end
56
+
57
+ describe '.gompertz' do
58
+ it 'should...saturate' do
59
+ t = 1.0 # threshold
60
+
61
+ x_data = []
62
+ y_data = []
63
+ z_data = []
64
+
65
+ osc = SPCore::Oscillator.new :sample_rate => 100.0, :frequency => 1.0, :wave_type => SPCore::Oscillator::WAVE_SINE, :amplitude => 2.5
66
+ (4 * osc.sample_rate / osc.frequency).to_i.times do |n|
67
+ x = n / osc.sample_rate
68
+ y = osc.sample
69
+ z = SPCore::Saturation.gompertz y, t
70
+
71
+ #z.should ???
72
+
73
+ x_data << x
74
+ y_data << y
75
+ z_data << z
76
+ end
77
+
78
+ #Gnuplot.open do |gp|
79
+ # Gnuplot::Plot.new(gp) do |plot|
80
+ # plot.title "signal and saturated signal"
81
+ # plot.xlabel "input"
82
+ # plot.ylabel "output"
83
+ #
84
+ # plot.data = [
85
+ # Gnuplot::DataSet.new( [x_data, y_data] ){ |ds|
86
+ # ds.with = "lines"
87
+ # ds.title = "Signal"
88
+ # #ds.linewidth = 4
89
+ # },
90
+ # Gnuplot::DataSet.new( [x_data, z_data] ){ |ds|
91
+ # ds.with = "lines"
92
+ # ds.title = "Saturated signal"
93
+ # #ds.linewidth = 4
94
+ # }
95
+ # ]
96
+ # end
97
+ #end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'spcore'
3
+
4
+ describe SPCore do
5
+ it "should have a VERSION constant" do
6
+ subject.const_get('VERSION').should_not be_empty
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ require 'rspec'
2
+ require 'spcore'
3
+
4
+ include SPCore
metadata ADDED
@@ -0,0 +1,217 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spcore
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - James Tunnell
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hashmake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.8'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.8'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '2.4'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '2.4'
78
+ - !ruby/object:Gem::Dependency
79
+ name: yard
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '0.8'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '0.8'
94
+ - !ruby/object:Gem::Dependency
95
+ name: pry
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: gnuplot
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: ! "Contains core signal processing functions, including:\n Delay line\n
127
+ \ Biquad filters\n Envelope detector\n Conversion from dB-linear and linear-dB\n
128
+ \ Linear interpolation\n Oscillator with selectable wave type (sine, square, triangle,
129
+ sawtooth)\n\n"
130
+ email: jamestunnell@lavabit.com
131
+ executables: []
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - .document
136
+ - .gitignore
137
+ - .rspec
138
+ - .yardopts
139
+ - ChangeLog.rdoc
140
+ - Gemfile
141
+ - LICENSE.txt
142
+ - README.rdoc
143
+ - Rakefile
144
+ - lib/spcore.rb
145
+ - lib/spcore/core/constants.rb
146
+ - lib/spcore/core/limiters.rb
147
+ - lib/spcore/lib/biquad_filter.rb
148
+ - lib/spcore/lib/circular_buffer.rb
149
+ - lib/spcore/lib/cookbook_allpass_filter.rb
150
+ - lib/spcore/lib/cookbook_bandpass_filter.rb
151
+ - lib/spcore/lib/cookbook_highpass_filter.rb
152
+ - lib/spcore/lib/cookbook_lowpass_filter.rb
153
+ - lib/spcore/lib/cookbook_notch_filter.rb
154
+ - lib/spcore/lib/delay_line.rb
155
+ - lib/spcore/lib/envelope_detector.rb
156
+ - lib/spcore/lib/gain.rb
157
+ - lib/spcore/lib/interpolation.rb
158
+ - lib/spcore/lib/oscillator.rb
159
+ - lib/spcore/lib/saturation.rb
160
+ - lib/spcore/version.rb
161
+ - spcore.gemspec
162
+ - spec/core/limiters_spec.rb
163
+ - spec/lib/circular_buffer_spec.rb
164
+ - spec/lib/cookbook_filter_spec.rb
165
+ - spec/lib/delay_line_spec.rb
166
+ - spec/lib/envelope_detector_spec.rb
167
+ - spec/lib/gain_spec.rb
168
+ - spec/lib/interpolation_spec.rb
169
+ - spec/lib/oscillator_spec.rb
170
+ - spec/lib/saturate_spec.rb
171
+ - spec/sigproc_spec.rb
172
+ - spec/spec_helper.rb
173
+ homepage: https://rubygems.org/gems/spcore
174
+ licenses:
175
+ - MIT
176
+ post_install_message:
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ none: false
182
+ requirements:
183
+ - - ! '>='
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ segments:
187
+ - 0
188
+ hash: 324932257
189
+ required_rubygems_version: !ruby/object:Gem::Requirement
190
+ none: false
191
+ requirements:
192
+ - - ! '>='
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ segments:
196
+ - 0
197
+ hash: 324932257
198
+ requirements: []
199
+ rubyforge_project:
200
+ rubygems_version: 1.8.23
201
+ signing_key:
202
+ specification_version: 3
203
+ summary: Perform basic signal processing functions (delay line, filters, envelope
204
+ detection, etc...).
205
+ test_files:
206
+ - spec/core/limiters_spec.rb
207
+ - spec/lib/circular_buffer_spec.rb
208
+ - spec/lib/cookbook_filter_spec.rb
209
+ - spec/lib/delay_line_spec.rb
210
+ - spec/lib/envelope_detector_spec.rb
211
+ - spec/lib/gain_spec.rb
212
+ - spec/lib/interpolation_spec.rb
213
+ - spec/lib/oscillator_spec.rb
214
+ - spec/lib/saturate_spec.rb
215
+ - spec/sigproc_spec.rb
216
+ - spec/spec_helper.rb
217
+ has_rdoc: