spcore 0.1.0

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.
@@ -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: