Class: SPCore::BiquadFilter

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

Overview

Based on the “simple implementation of Biquad filters” by Tom St Denis, which is based on the work “Cookbook formulae for audio EQ biquad filter coefficients” by Robert Bristow-Johnson, [email protected] a.k.a. [email protected]. Available on the web at www.smartelectronix.com/musicdsp/text/filters005.txt

Constant Summary collapse

LN_2 =

used in subclasses to calculate IIR filter coefficients

Math::log(2)

Instance Method Summary collapse

Constructor Details

#initialize(sample_rate) ⇒ BiquadFilter

A new instance of BiquadFilter.

Parameters:

  • sample_rate (Numeric)

    The sample rate to use in calculating coefficients.



18
19
20
21
22
23
# File 'lib/spcore/filters/iir/biquad_filter.rb', line 18

def initialize sample_rate
  @sample_rate = sample_rate
  @biquad = Struct::BiquadState.new(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0)
  @critical_freq = 0.0
  @bandwidth = 0.0
end

Instance Method Details

#bandwidth=(bandwidth) ⇒ Object

Set the filter bandwidth.



36
37
38
# File 'lib/spcore/filters/iir/biquad_filter.rb', line 36

def bandwidth= bandwidth
  set_critical_freq_and_bw(@critical_freq, bandwidth);
end

#critical_freq=(critical_freq) ⇒ Object

Set the filter critical frequency.



31
32
33
# File 'lib/spcore/filters/iir/biquad_filter.rb', line 31

def critical_freq= critical_freq
  set_critical_freq_and_bw(critical_freq, @bandwidth);
end

#get_freq_magnitude_response(test_freq) ⇒ Object

Calculate the frequency magnitude response for the given frequency.

Parameters:

  • test_freq (Numeric)

    The frequency to calculate magnitude response at.



66
67
68
69
70
71
72
73
74
75
# File 'lib/spcore/filters/iir/biquad_filter.rb', line 66

def get_freq_magnitude_response test_freq
  # Method for determining freq magnitude response is from:
  # http://rs-met.com/documents/dsp/BasicDigitalFilters.pdf
  omega = 2.0 * Math::PI * test_freq / @sample_rate
  b0, b1, b2 = @biquad.b0, @biquad.b1, @biquad.b2
  a0, a1, a2 = 1, @biquad.a1, @biquad.a2
  b = (b0**2) + (b1**2) + (b2**2) + (2 * (b0 * b1 + b1 * b2) * Math::cos(omega)) + (2 * b0 * b2 * Math::cos(2 * omega))
  a = (a0**2) + (a1**2) + (a2**2) + (2 * (a0 * a1 + a1 * a2) * Math::cos(omega)) + (2 * a0 * a2 * Math::cos(2 * omega))
  return Math::sqrt(b/a)
end

#process_sample(sample) ⇒ Object

Calculate biquad output using Direct Form I:

y = (b0/a0)*x + (b1/a0)*x + (b2/a0)*x

- (a1/a0)*y[n-1] - (a2/a0)*y[n-2]

Note: coefficients are already divided by a0 when they are calculated. So that step is left out during processing.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/spcore/filters/iir/biquad_filter.rb', line 48

def process_sample sample
  # compute result
  result = @biquad.b0 * sample + @biquad.b1 * @biquad.x1 + @biquad.b2 * @biquad.x2 -
      @biquad.a1 * @biquad.y1 - @biquad.a2 * @biquad.y2;

  # shift x1 to x2, sample to x1
  @biquad.x2 = @biquad.x1;
  @biquad.x1 = sample;

  # shift y1 to y2, result to y1
  @biquad.y2 = @biquad.y1;
  @biquad.y1 = result;

  return result
end

#set_critical_freq_and_bw(critical_freq, bandwidth) ⇒ Object

Set the filter critical frequency and bandwidth.

Raises:

  • (NotImplementedError)


26
27
28
# File 'lib/spcore/filters/iir/biquad_filter.rb', line 26

def set_critical_freq_and_bw critical_freq, bandwidth
  raise NotImplementedError, "set_critical_freq_and_bW should be implemented in the derived class!"
end