spcore 0.1.7 → 0.1.8

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.
@@ -37,6 +37,10 @@ Adjust project documentation.
37
37
 
38
38
  Update to be compatible with hashmake-0.1.6.
39
39
 
40
- === 0.1.7 2013-04-18
40
+ === 0.1.7 / 2013-04-18
41
41
 
42
- Require all sample rate args to be Fixnum.
42
+ Require all sample rate args to be Fixnum.
43
+
44
+ === 0.1.8 / 2013-05-03
45
+
46
+ Add Envelope and Extrema classes, for signal analysis.
@@ -24,6 +24,7 @@ A library of signal processing methods and classes.
24
24
  * Conversion from dB-linear and linear-dB
25
25
  * Oscillator with selectable wave type (sine, square, triangle, sawtooth)
26
26
  * Signal abstraction class
27
+ * Extrema & Envelope measurement
27
28
 
28
29
  == Examples
29
30
 
@@ -4,9 +4,10 @@ require 'spcore/version'
4
4
  require 'spcore/core/circular_buffer'
5
5
  require 'spcore/core/constants'
6
6
  require 'spcore/core/delay_line'
7
- require 'spcore/core/envelope_detector'
8
7
  require 'spcore/core/oscillator'
9
8
  require 'spcore/core/signal'
9
+ require 'spcore/core/extrema'
10
+ require 'spcore/core/envelope'
10
11
 
11
12
  require 'spcore/windows/bartlett_hann_window'
12
13
  require 'spcore/windows/bartlett_window'
@@ -48,3 +49,4 @@ require 'spcore/util/plotter'
48
49
  require 'spcore/util/saturation'
49
50
  require 'spcore/util/scale'
50
51
  require 'spcore/util/signal_generator'
52
+ require 'spcore/util/envelope_detector'
@@ -0,0 +1,58 @@
1
+ module SPCore
2
+ # Determines the envelope of given samples. Unlike the EnvelopeDetector, this
3
+ # operates on a signal (time-series data) after it is recieved, not
4
+ # sample-by-sample. As a result, it provides the envelope as an entire signal.
5
+ #
6
+ # @author James Tunnell
7
+ class Envelope < Signal
8
+
9
+ attr_reader :data
10
+
11
+ def initialize samples
12
+ # combine absolute values of positive maxima and negative minima
13
+ extrema = Extrema.new(samples)
14
+ points = {}
15
+ extrema.minima.each do |idx,val|
16
+ if val <= 0.0
17
+ points[idx] = val.abs
18
+ end
19
+ end
20
+
21
+ extrema.maxima.each do |idx,val|
22
+ if val >= 0.0
23
+ points[idx] = val.abs
24
+ end
25
+ end
26
+
27
+ # add in first and last samples so the envelope follows entire signal
28
+ points[0] = samples[0].abs
29
+ points[samples.count - 1] = samples[samples.count - 1].abs
30
+
31
+ indices = points.keys.sort
32
+ @data = Array.new(samples.count, 0)
33
+
34
+ # interpolate between all the extrema for the rest of the values. We
35
+ # manually added first/last index so the whole signal should be covered
36
+ # by this
37
+ for i in 1...indices.count
38
+ l_idx = indices[i-1]
39
+ r_idx = indices[i]
40
+
41
+ l_val = points[l_idx]
42
+ r_val = points[r_idx]
43
+
44
+ @data[l_idx] = l_val
45
+ @data[r_idx] = r_val
46
+
47
+ idx_span = r_idx - l_idx
48
+
49
+ for j in (l_idx + 1)...(r_idx)
50
+ x = (j - l_idx).to_f / idx_span
51
+ y = Interpolation.linear l_val, r_val, x
52
+ @data[j] = y
53
+ end
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,55 @@
1
+ module SPCore
2
+ # Finds extrema (minima and maxima).
3
+ class Extrema
4
+
5
+ attr_reader :minima, :maxima, :extrema
6
+
7
+ def initialize samples
8
+ @minima = {}
9
+ @maxima = {}
10
+
11
+ global_min_idx = 0
12
+ global_min_val = samples[0]
13
+ global_max_idx = 0
14
+ global_max_val = samples[0]
15
+
16
+ diffs = []
17
+ for i in (1...samples.count)
18
+ diffs.push(samples[i] - samples[i-1])
19
+
20
+ if samples[i] < global_min_val
21
+ global_min_idx = i
22
+ global_min_val = samples[i]
23
+ end
24
+
25
+ if samples[i] > global_max_val
26
+ global_max_idx = i
27
+ global_max_val = samples[i]
28
+ end
29
+ end
30
+ @minima[global_min_idx] = global_min_val
31
+ @maxima[global_max_idx] = global_max_val
32
+
33
+ is_positive = diffs.first > 0.0 # starting off with positive difference?
34
+
35
+ # at zero crossings there is a local maxima/minima
36
+ for i in (1...diffs.count)
37
+ if is_positive
38
+ # at positive-to-negative transition there is a local maxima
39
+ if diffs[i] <= 0.0
40
+ @maxima[i] = samples[i]
41
+ is_positive = false
42
+ end
43
+ else
44
+ # at negative-to-positive transition there is a local minima
45
+ if diffs[i] > 0.0
46
+ @minima[i] = samples[i]
47
+ is_positive = true
48
+ end
49
+ end
50
+ end
51
+
52
+ @extrema = @minima.merge(@maxima)
53
+ end
54
+ end
55
+ end
@@ -89,7 +89,7 @@ class Signal
89
89
  # polynomial interpolation.
90
90
  # @param [Fixnum] upsample_factor Increase the sample rate by this factor.
91
91
  def upsample_polynomial upsample_factor
92
- @data = PolynomialResampling.upsample @data, @sample_rate, upsample_factor
92
+ @data = PolynomialResampling.upsample @data, upsample_factor
93
93
  @sample_rate *= upsample_factor
94
94
  return self
95
95
  end
@@ -134,24 +134,14 @@ class Signal
134
134
  return @data.inject(0.0){|sum,x| sum + (x * x)}
135
135
  end
136
136
 
137
- # Return a
138
- def envelope attack_time, release_time
139
- raise ArgumentError, "attack_time #{attack_time } is less than or equal to zero" if attack_time <= 0.0
140
- raise ArgumentError, "release_time #{release_time} is less than or equal to zero" if release_time <= 0.0
141
-
142
- env_detector = EnvelopeDetector.new(:attack_time => attack_time, :release_time => release_time, :sample_rate => @sample_rate)
143
-
144
- envelope = Array.new(@data.count)
145
-
146
- for i in 0...@data.count do
147
- envelope[i] = env_detector.process_sample @data[i]
148
- end
149
-
150
- return envelope
137
+ # Determine the envelope of the current Signal and return the resulting data
138
+ # in a new Signal object.
139
+ def envelope
140
+ return Envelope.new(@data)
151
141
  end
152
142
 
153
143
  # Add data in array or other signal to the beginning of current data.
154
- def prepend other
144
+ def prepend! other
155
145
  if other.is_a?(Array)
156
146
  @data = other.concat @data
157
147
  elsif other.is_a?(Signal)
@@ -161,7 +151,7 @@ class Signal
161
151
  end
162
152
 
163
153
  # Add data in array or other signal to the end of current data.
164
- def append other
154
+ def append! other
165
155
  if other.is_a?(Array)
166
156
  @data = @data.concat other
167
157
  elsif other.is_a?(Signal)
@@ -173,7 +163,7 @@ class Signal
173
163
  # Add value, values in array, or values in other signal to the current
174
164
  # data values, and update the current data with the results.
175
165
  # @param other Can be Numeric (add same value to all data values), Array, or Signal.
176
- def +(other)
166
+ def add!(other)
177
167
  if other.is_a?(Numeric)
178
168
  @data.each_index do |i|
179
169
  @data[i] += other
@@ -193,11 +183,37 @@ class Signal
193
183
  end
194
184
  return self
195
185
  end
186
+
187
+ # Add value, values in array, or values in other signal to the current
188
+ # data values, and return a new Signal object with the results.
189
+ # @param other Can be Numeric (add same value to all data values), Array, or Signal.
190
+ def add(other)
191
+ new_data = Array.new(@data.size)
192
+
193
+ if other.is_a?(Numeric)
194
+ @data.each_index do |i|
195
+ new_data[i] = @data[i] + other
196
+ end
197
+ elsif other.is_a?(Signal)
198
+ raise ArgumentError, "other.data.size #{other.size} is not equal to data.size #{@data.size}" if other.data.size != @data.size
199
+ @data.each_index do |i|
200
+ new_data[i] = @data[i] + other.data[i]
201
+ end
202
+ elsif other.is_a?(Array)
203
+ raise ArgumentError, "other.size #{other.size} is not equal to data.size #{@data.size}" if other.size != @data.size
204
+ @data.each_index do |i|
205
+ new_data[i] = @data[i] + other[i]
206
+ end
207
+ else
208
+ raise ArgumentError, "other is not a Numeric, Signal, or Array"
209
+ end
210
+ return Signal.new(:data => new_data, :sample_rate => @sample_rate)
211
+ end
196
212
 
197
213
  # Subtract value, values in array, or values in other signal from the current
198
214
  # data values, and update the current data with the results.
199
215
  # @param other Can be Numeric (subtract same value from all data values), Array, or Signal.
200
- def -(other)
216
+ def subtract!(other)
201
217
  if other.is_a?(Numeric)
202
218
  @data.each_index do |i|
203
219
  @data[i] -= other
@@ -218,11 +234,37 @@ class Signal
218
234
  return self
219
235
  end
220
236
 
237
+ # Subtract value, values in array, or values in other signal from the current
238
+ # data values, and return a new Signal object with the results.
239
+ # @param other Can be Numeric (subtract same value from all data values), Array, or Signal.
240
+ def subtract(other)
241
+ new_data = Array.new(@data.size)
242
+
243
+ if other.is_a?(Numeric)
244
+ @data.each_index do |i|
245
+ new_data[i] = @data[i] - other
246
+ end
247
+ elsif other.is_a?(Signal)
248
+ raise ArgumentError, "other.data.size #{other.size} is not equal to data.size #{@data.size}" if other.data.size != @data.size
249
+ @data.each_index do |i|
250
+ new_data[i] = @data[i] - other.data[i]
251
+ end
252
+ elsif other.is_a?(Array)
253
+ raise ArgumentError, "other.size #{other.size} is not equal to data.size #{@data.size}" if other.size != @data.size
254
+ @data.each_index do |i|
255
+ new_data[i] = @data[i] - other[i]
256
+ end
257
+ else
258
+ raise ArgumentError, "other is not a Numeric, Signal, or Array"
259
+ end
260
+ return Signal.new(:data => new_data, :sample_rate => @sample_rate)
261
+ end
262
+
221
263
  # Multiply value, values in array, or values in other signal with the current
222
264
  # data values, and update the current data with the results.
223
265
  # @param other Can be Numeric (multiply all data values by the same value),
224
266
  # Array, or Signal.
225
- def *(other)
267
+ def multiply!(other)
226
268
  if other.is_a?(Numeric)
227
269
  @data.each_index do |i|
228
270
  @data[i] *= other
@@ -243,11 +285,38 @@ class Signal
243
285
  return self
244
286
  end
245
287
 
288
+ # Multiply value, values in array, or values in other signal with the current
289
+ # data values, and return a new Signal object with the results.
290
+ # @param other Can be Numeric (multiply all data values by the same value),
291
+ # Array, or Signal.
292
+ def multiply(other)
293
+ new_data = Array.new(@data.size)
294
+
295
+ if other.is_a?(Numeric)
296
+ @data.each_index do |i|
297
+ new_data[i] = @data[i] * other
298
+ end
299
+ elsif other.is_a?(Signal)
300
+ raise ArgumentError, "other.data.size #{other.size} is not equal to data.size #{@data.size}" if other.data.size != @data.size
301
+ @data.each_index do |i|
302
+ new_data[i] = @data[i] * other.data[i]
303
+ end
304
+ elsif other.is_a?(Array)
305
+ raise ArgumentError, "other.size #{other.size} is not equal to data.size #{@data.size}" if other.size != @data.size
306
+ @data.each_index do |i|
307
+ new_data[i] = @data[i] * other[i]
308
+ end
309
+ else
310
+ raise ArgumentError, "other is not a Numeric, Signal, or Array"
311
+ end
312
+ return Signal.new(:data => new_data, :sample_rate => @sample_rate)
313
+ end
314
+
246
315
  # Divide value, values in array, or values in other signal into the current
247
316
  # data values, and update the current data with the results.
248
317
  # @param other Can be Numeric (divide same all data values by the same value),
249
318
  # Array, or Signal.
250
- def /(other)
319
+ def divide!(other)
251
320
  if other.is_a?(Numeric)
252
321
  @data.each_index do |i|
253
322
  @data[i] /= other
@@ -268,10 +337,37 @@ class Signal
268
337
  return self
269
338
  end
270
339
 
271
- alias_method :add, :+
272
- alias_method :subtract, :-
273
- alias_method :multiply, :*
274
- alias_method :divide, :/
340
+ # Divide value, values in array, or values in other signal into the current
341
+ # data values, and return a new Signal object with the results.
342
+ # @param other Can be Numeric (divide same all data values by the same value),
343
+ # Array, or Signal.
344
+ def divide(other)
345
+ new_data = Array.new(@data.size)
346
+
347
+ if other.is_a?(Numeric)
348
+ @data.each_index do |i|
349
+ new_data[i] = @data[i] / other
350
+ end
351
+ elsif other.is_a?(Signal)
352
+ raise ArgumentError, "other.data.size #{other.size} is not equal to data.size #{@data.size}" if other.data.size != @data.size
353
+ @data.each_index do |i|
354
+ new_data[i] = @data[i] / other.data[i]
355
+ end
356
+ elsif other.is_a?(Array)
357
+ raise ArgumentError, "other.size #{other.size} is not equal to data.size #{@data.size}" if other.size != @data.size
358
+ @data.each_index do |i|
359
+ new_data[i] = @data[i] / other[i]
360
+ end
361
+ else
362
+ raise ArgumentError, "other is not a Numeric, Signal, or Array"
363
+ end
364
+ return Signal.new(:data => new_data, :sample_rate => @sample_rate)
365
+ end
366
+
367
+ alias_method :+, :add
368
+ alias_method :-, :subtract
369
+ alias_method :*, :multiply
370
+ alias_method :/, :divide
275
371
 
276
372
  # Determine how well the another signal (g) correlates to the current signal (f).
277
373
  # Correlation is determined at every point in f. The signal g must not be
@@ -1,17 +1,17 @@
1
1
  module SPCore
2
2
  # Provide interpolation methods, including linear and polynomial.
3
3
  class Interpolation
4
- # Linear Interpolation Equation:
5
- #
6
- # (x3 - x1)(y2 - y1)
7
- # y3 = ------------------ + y1
8
- # (x2 - x1)
9
- #
10
- def self.linear x1, y1, x2, y2, x3
11
- y3 = ((x3 - x1) * (y2 - y1)) / (x2 - x1);
12
- y3 += y1;
13
- return y3;
14
- end
4
+ ## Linear Interpolation Equation:
5
+ ##
6
+ ## (x3 - x1)(y2 - y1)
7
+ ## y3 = ------------------ + y1
8
+ ## (x2 - x1)
9
+ ##
10
+ #def self.linear x1, y1, x2, y2, x3
11
+ # y3 = ((x3 - x1) * (y2 - y1)) / (x2 - x1);
12
+ # y3 += y1;
13
+ # return y3;
14
+ #end
15
15
 
16
16
  # Linear interpolator
17
17
  # Given 2 sample points, interpolates a value anywhere between the two points.
@@ -9,7 +9,7 @@ class HybridResampling
9
9
  raise ArgumentError, "downsample_factor is not greater than 1" unless downsample_factor > 1
10
10
  raise ArgumentError, "sample_rate is not greater than 0" unless sample_rate > 0
11
11
 
12
- upsampled = PolynomialResampling.upsample input, sample_rate, upsample_factor
12
+ upsampled = PolynomialResampling.upsample input, upsample_factor
13
13
 
14
14
  needed_samples = upsampled.size % downsample_factor
15
15
  if needed_samples == 0
@@ -3,10 +3,9 @@ module SPCore
3
3
  # polynomial interpolation.
4
4
  class PolynomialResampling
5
5
 
6
- def self.upsample input, sample_rate, upsample_factor
6
+ def self.upsample input, upsample_factor
7
7
  raise ArgumentError, "input.size is less than four" unless input.size >= 4
8
8
  raise ArgumentError, "upsample_factor is not greater than 1" unless upsample_factor > 1
9
- raise ArgumentError, "sample_rate is not greater than 0" unless sample_rate > 0
10
9
 
11
10
  output = Array.new((upsample_factor * input.size).to_i)
12
11
 
@@ -33,7 +33,14 @@ class Plotter
33
33
  def plot_2d titled_hashes
34
34
  datasets = []
35
35
  titled_hashes.each do |title, hash|
36
- dataset = Gnuplot::DataSet.new( [hash.keys, hash.values] ){ |ds|
36
+ # sort the data
37
+
38
+ sorted = {}
39
+ hash.keys.sort.each do |key|
40
+ sorted[key] = hash[key]
41
+ end
42
+
43
+ dataset = Gnuplot::DataSet.new( [sorted.keys, sorted.values] ){ |ds|
37
44
  ds.with = @linestyle
38
45
  ds.title = title
39
46
  ds.linewidth = @linewidth
@@ -35,8 +35,8 @@ class SignalGenerator
35
35
  oscs.push Oscillator.new args.merge(:frequency => freq)
36
36
  end
37
37
 
38
- output = Array.new(size, 0.0)
39
- size.times do |n|
38
+ output = Array.new(@size, 0.0)
39
+ @size.times do |n|
40
40
  oscs.each do |osc|
41
41
  output[n] += osc.sample
42
42
  end
@@ -1,5 +1,5 @@
1
1
  # A library of signal processing methods and classes.
2
2
  module SPCore
3
3
  # spcore version
4
- VERSION = "0.1.7"
4
+ VERSION = "0.1.8"
5
5
  end
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SPCore::Envelope do
4
+ it 'should produce an output that follows the amplitude of the input' do
5
+ sample_rate = 400
6
+ sample_count = sample_rate
7
+ generator = SignalGenerator.new(:size => sample_count, :sample_rate => sample_rate)
8
+ base_signal = generator.make_signal [sample_rate / 5.0]
9
+ modulation_signal = generator.make_signal [sample_rate / 80.0]
10
+ base_signal.multiply! modulation_signal
11
+
12
+ envelope = base_signal.envelope
13
+
14
+ Plotter.new(
15
+ :title => "signal and envelope",
16
+ :xlabel => "sample",
17
+ :ylabel => "values",
18
+ ).plot_1d(
19
+ "signal" => base_signal.data,
20
+ "modulation" => modulation_signal.data,
21
+ "envelope" => envelope.data,
22
+ )
23
+
24
+ max_diff = 0.1
25
+ sample_count.times do |n|
26
+ envelope.data[n].should be_within(max_diff).of(modulation_signal.data[n].abs)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SPCore::Extrema do
4
+ context '#minima' do
5
+ it 'should return points where local and global minima occur' do
6
+ cases = {
7
+ [3.8, 3.0, 2.9, 2.95, 3.6, 3.4, 2.8, 2.3, 2.1, 2.0, 2.5] => { 2 => 2.9, 9 => 2.0 },
8
+ [3.2, 3.5, 2.9, 2.7, 2.8, 2.7, 2.5, 2.2, 2.4, 2.3, 2.0] => { 3 => 2.7, 7 => 2.2, 10 => 2.0 },
9
+ }
10
+
11
+ cases.each do |samples, minima|
12
+ Extrema.new(samples).minima.should eq minima
13
+ end
14
+ end
15
+ end
16
+
17
+ context '#maxima' do
18
+ it 'should return points where local and global maxima occur' do
19
+ cases = {
20
+ [3.8, 3.0, 2.9, 2.95, 3.6, 3.4, 2.8, 2.3, 2.1, 2.0, 2.5] => { 0 => 3.8, 4 => 3.6 },
21
+ [3.2, 3.5, 2.9, 2.7, 2.8, 2.7, 2.5, 2.2, 2.4, 2.3, 2.0] => { 1 => 3.5, 4 => 2.8, 8 => 2.4},
22
+ }
23
+
24
+ cases.each do |samples, maxima|
25
+ Extrema.new(samples).maxima.should eq maxima
26
+ end
27
+ end
28
+ end
29
+
30
+ context '#extrema' do
31
+ it 'should return points where local and global extrema occur' do
32
+ cases = {
33
+ [3.8, 3.0, 2.9, 2.95, 3.6, 3.4, 2.8, 2.3, 2.1, 2.0, 2.5] => { 0 => 3.8, 2 => 2.9, 4 => 3.6, 9 => 2.0},
34
+ [3.2, 3.5, 2.9, 2.7, 2.8, 2.7, 2.5, 2.2, 2.4, 2.3, 2.0] => { 1 => 3.5, 3 => 2.7, 4 => 2.8, 7 => 2.2, 8 => 2.4, 10 => 2.0},
35
+ }
36
+
37
+ cases.each do |samples, extrema|
38
+ Extrema.new(samples).extrema.should eq extrema
39
+ end
40
+ end
41
+ end
42
+ end
@@ -8,7 +8,7 @@ describe SPCore::HybridResampling do
8
8
  sample_rate = 400
9
9
  test_freq = 10.0
10
10
  size = 64
11
- upsample_factor = 4
11
+ upsample_factor = 10
12
12
  downsample_factor = 4
13
13
  order = (sample_rate / test_freq).to_i
14
14
 
@@ -16,7 +16,7 @@ describe SPCore::HybridResampling do
16
16
  signal1 *= BlackmanWindow.new(size).data
17
17
  signal2 = signal1.clone.resample_hybrid upsample_factor, downsample_factor, order
18
18
 
19
- #plotter = Plotter.new(:title => "Discrete resampling, up by #{upsampling_factor}, down by #{downsample_factor}")
19
+ #plotter = Plotter.new(:title => "Discrete resampling, up by #{upsample_factor}, down by #{downsample_factor}")
20
20
  #plotter.plot_1d("original signal" => signal1.data, "resampled signal" => signal2.data)
21
21
 
22
22
  signal2.size.should eq(signal1.size * upsample_factor / downsample_factor)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spcore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-18 00:00:00.000000000 Z
12
+ date: 2013-05-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hashmake
@@ -147,7 +147,8 @@ files:
147
147
  - lib/spcore/core/circular_buffer.rb
148
148
  - lib/spcore/core/constants.rb
149
149
  - lib/spcore/core/delay_line.rb
150
- - lib/spcore/core/envelope_detector.rb
150
+ - lib/spcore/core/envelope.rb
151
+ - lib/spcore/core/extrema.rb
151
152
  - lib/spcore/core/oscillator.rb
152
153
  - lib/spcore/core/signal.rb
153
154
  - lib/spcore/filters/fir/dual_sinc_filter.rb
@@ -165,6 +166,7 @@ files:
165
166
  - lib/spcore/resampling/polynomial_resampling.rb
166
167
  - lib/spcore/transforms/dft.rb
167
168
  - lib/spcore/transforms/fft.rb
169
+ - lib/spcore/util/envelope_detector.rb
168
170
  - lib/spcore/util/gain.rb
169
171
  - lib/spcore/util/limiters.rb
170
172
  - lib/spcore/util/plotter.rb
@@ -189,7 +191,8 @@ files:
189
191
  - spcore.gemspec
190
192
  - spec/core/circular_buffer_spec.rb
191
193
  - spec/core/delay_line_spec.rb
192
- - spec/core/envelope_detector_spec.rb
194
+ - spec/core/envelope_spec.rb
195
+ - spec/core/extrema_spec.rb
193
196
  - spec/core/oscillator_spec.rb
194
197
  - spec/filters/fir/dual_sinc_filter_spec.rb
195
198
  - spec/filters/fir/sinc_filter_spec.rb
@@ -202,6 +205,7 @@ files:
202
205
  - spec/spec_helper.rb
203
206
  - spec/transforms/dft_spec.rb
204
207
  - spec/transforms/fft_spec.rb
208
+ - spec/util/envelope_detector_spec.rb
205
209
  - spec/util/gain_spec.rb
206
210
  - spec/util/limiters_spec.rb
207
211
  - spec/util/saturate_spec.rb
@@ -222,7 +226,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
222
226
  version: '0'
223
227
  segments:
224
228
  - 0
225
- hash: 407745007
229
+ hash: -1351761362878137001
226
230
  required_rubygems_version: !ruby/object:Gem::Requirement
227
231
  none: false
228
232
  requirements:
@@ -231,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
235
  version: '0'
232
236
  segments:
233
237
  - 0
234
- hash: 407745007
238
+ hash: -1351761362878137001
235
239
  requirements: []
236
240
  rubyforge_project:
237
241
  rubygems_version: 1.8.23
@@ -241,7 +245,8 @@ summary: A library of signal processing methods and classes.
241
245
  test_files:
242
246
  - spec/core/circular_buffer_spec.rb
243
247
  - spec/core/delay_line_spec.rb
244
- - spec/core/envelope_detector_spec.rb
248
+ - spec/core/envelope_spec.rb
249
+ - spec/core/extrema_spec.rb
245
250
  - spec/core/oscillator_spec.rb
246
251
  - spec/filters/fir/dual_sinc_filter_spec.rb
247
252
  - spec/filters/fir/sinc_filter_spec.rb
@@ -254,6 +259,7 @@ test_files:
254
259
  - spec/spec_helper.rb
255
260
  - spec/transforms/dft_spec.rb
256
261
  - spec/transforms/fft_spec.rb
262
+ - spec/util/envelope_detector_spec.rb
257
263
  - spec/util/gain_spec.rb
258
264
  - spec/util/limiters_spec.rb
259
265
  - spec/util/saturate_spec.rb