Class: SPCore::Envelope

Inherits:
Object
  • Object
show all
Defined in:
lib/spcore/analysis/envelope.rb

Overview

Author:

  • James Tunnell

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(samples) ⇒ Envelope

Returns a new instance of Envelope.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/spcore/analysis/envelope.rb', line 11

def initialize samples
  # combine absolute values of positive maxima and negative minima
  extrema = Extrema.new(samples)
  starting_outline = {}
  extrema.minima.each do |idx,val|
    if val <= 0.0
      starting_outline[idx] =val.abs
    end
  end
  
  extrema.maxima.each do |idx,val|
    if val >= 0.0
      starting_outline[idx] = val.abs
    end
  end
  
  # add in first and last samples so the envelope follows entire signal
  starting_outline[0] = samples[0].abs
  starting_outline[samples.count - 1] = samples[samples.count - 1].abs
  
  # the extrema we have now are probably not spaced evenly. Upsampling at
  # this point would lead to a time-distorted signal. So the next step is to
  # interpolate between all the extrema to make a crude but properly sampled
  # envelope.
  
  proper_outline = Array.new(samples.count, 0)
  indices = starting_outline.keys.sort
  
  for i in 1...indices.count
    l_idx = indices[i-1]
    r_idx = indices[i]
    
    l_val = starting_outline[l_idx]
    r_val = starting_outline[r_idx]
    
    proper_outline[l_idx] = l_val
    proper_outline[r_idx] = r_val
    
    idx_span = r_idx - l_idx
    
    for j in (l_idx + 1)...(r_idx)
      x = (j - l_idx).to_f / idx_span
      y = Interpolation.linear l_val, r_val, x
      proper_outline[j] = y
    end
  end
  
  # Now downsample by dropping samples, back to the number of starting_outline we had
  # with just the extrema, but this time with samples properly spaced so as
  # to avoid time distortion after upsampling.
  
  downsample_factor = (samples.count / starting_outline.count).to_i
  downsampled_outline = []

  (0...proper_outline.count).step(downsample_factor) do |n|
    downsampled_outline.push proper_outline[n]
  end
  
  # finally, use polynomial interpolation to upsample to the original sample rate.
  
  upsample_factor = samples.count / downsampled_outline.count.to_f
  @data = PolynomialResampling.upsample(downsampled_outline, upsample_factor)
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



9
10
11
# File 'lib/spcore/analysis/envelope.rb', line 9

def data
  @data
end