Class: SPCore::FIR

Inherits:
Object
  • Object
show all
Defined in:
lib/spcore/filters/fir/fir.rb

Overview

convolution.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(kernel, sample_rate) ⇒ FIR

A new instance of FIR. Filter order will by kernel size - 1.

Parameters:

  • kernel (Array)

    Filter kernel values.

  • sample_rate (Numeric)

    The sample rate the filter operates at.



11
12
13
14
15
# File 'lib/spcore/filters/fir/fir.rb', line 11

def initialize kernel, sample_rate
  @kernel = kernel
  @order = kernel.size - 1
  @sample_rate = sample_rate
end

Instance Attribute Details

#kernelObject (readonly)

Returns the value of attribute kernel.



6
7
8
# File 'lib/spcore/filters/fir/fir.rb', line 6

def kernel
  @kernel
end

#orderObject (readonly)

Returns the value of attribute order.



6
7
8
# File 'lib/spcore/filters/fir/fir.rb', line 6

def order
  @order
end

#sample_rateObject (readonly)

Returns the value of attribute sample_rate.



6
7
8
# File 'lib/spcore/filters/fir/fir.rb', line 6

def sample_rate
  @sample_rate
end

Instance Method Details

#convolve(input) ⇒ Object

Convolve the given input data with the filter kernel.

Parameters:

  • input (Array)

    Array of input data to by convolved with filter kernel. The array size must be greater than the filter kernel size.

Raises:

  • (ArgumentError)


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
# File 'lib/spcore/filters/fir/fir.rb', line 20

def convolve input
  kernel_size = @kernel.size
  raise ArgumentError, "input.size #{input.size} is not greater than filter kernel size #{kernel_size}" unless input.size > kernel_size
  
  output = Array.new(input.size, 0.0)

  for i in 0...kernel_size
    sum = 0.0
    # convolve the input with the filter kernel
    for j in 0...i
      sum += (input[j] * @kernel[kernel_size - (1 + i - j)])
    end
    output[i] = sum
  end
  
  for i in kernel_size...input.size
    sum = 0.0
    # convolve the input with the filter kernel
    for j in 0...kernel_size
      sum += (input[i-j] * @kernel[j])
    end
    output[i] = sum
  end
  
  return output
end

#freq_response(use_db = false) ⇒ Object

Calculate the filter frequency magnitude response.

Parameters:

  • use_db (Numeric) (defaults to: false)

    Calculate magnitude in dB.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/spcore/filters/fir/fir.rb', line 49

def freq_response use_db = false

  input = [0.0] + @kernel # make the size even
  output = FFT.forward input
  
  output = output[0...(output.size / 2)]  # ignore second half (mirror image)
  output = output.map {|x| x.magnitude }  # calculate magnitudes from complex values
  
  if use_db
    output = output.map {|x| Gain::linear_to_db x }
  end
  
  response = {}
  output.each_index do |n|
    frequency = (@sample_rate * n) / (output.size * 2.0)
    response[frequency] = output[n]
  end
  
  ## amplitude = 2 * f[j] / size
  #output = output.map {|x| 2 * x / output.size }
  
  return response
end

#plot_freq_response(use_db = true) ⇒ Object

Calculate the filter frequency magnitude response and graph the results.

Parameters:

  • use_db (Numeric) (defaults to: true)

    Calculate magnitude in dB.



76
77
78
79
80
81
82
83
84
85
# File 'lib/spcore/filters/fir/fir.rb', line 76

def plot_freq_response use_db = true
  plotter = Plotter.new(
    :title => "Freq magnitude response of #{@order}-order FIR filter",
    :xlabel => "frequency (Hz)",
    :ylabel => "magnitude#{use_db ? " (dB)" : ""}",
    :logscale => "x"
  )
  
  plotter.plot_2d "" => freq_response(use_db)
end