Class: SPCore::DualSincFilter

Inherits:
Object
  • Object
show all
Includes:
Hashmake::HashMakeable
Defined in:
lib/spcore/filters/fir/dual_sinc_filter.rb

Overview

Extended windowed sinc filter. Implements bandpass and bandstop using two SincFilterBase objects.

Theoretical source: www.labbookpages.co.uk/audio/firWindowing.html

Author:

  • James Tunnell

Constant Summary collapse

ARG_SPECS =

Use to process hashed args in #initialize.

{
  :order => arg_spec(:reqd => true, :type => Fixnum, :validator => ->(a){ a % 2 == 0 } ),
  :sample_rate => arg_spec(:reqd => true, :type => Fixnum, :validator => ->(a){ a > 0.0 } ),
  :left_cutoff_freq => arg_spec(:reqd => true, :type => Numeric, :validator => ->(a){ a > 0.0 } ),
  :right_cutoff_freq => arg_spec(:reqd => true, :type => Numeric, :validator => ->(a){ a > 0.0 } ),
  :window_class => arg_spec(:reqd => false, :type => Class, :default => BlackmanWindow ),
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ DualSincFilter

Given a filter order, 2 cutoff frequencies, sample rate, and window class, develop a FIR filter kernel that can be used for lowpass filtering.

Raises:

  • (ArgumentError)


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

def initialize args
  hash_make args, DualSincFilter::ARG_SPECS
  
  raise ArgumentError, "left_cutoff_freq is greater than 0.5 * sample_rate" if @left_cutoff_freq > (@sample_rate * 0.5)
  raise ArgumentError, "right_cutoff_freq is greater than 0.5 * sample_rate" if @right_cutoff_freq > (@sample_rate * 0.5)
  raise ArgumentError, "left_cutoff_freq is not less than right_cutoff_freq" unless @left_cutoff_freq < @right_cutoff_freq 
  
  @left_filter = SincFilter.new(
    :sample_rate => @sample_rate,
    :order => @order,
    :cutoff_freq => @left_cutoff_freq,
    :window_class => @window_class,
  )

  @right_filter = SincFilter.new(
    :sample_rate => @sample_rate,
    :order => @order,
    :cutoff_freq => @right_cutoff_freq,
    :window_class => @window_class,
  )
  
  size = @order + 1

  # make FIR filter kernels for bandpass and bandstop
  
  bandpass_kernel = Array.new(size)
  bandstop_kernel = Array.new(size)
  window = @window_class.new(size)
  
  for n in 0...(@order / 2)
    bandpass_kernel[size - 1 - n] = bandpass_kernel[n] = @right_filter.lowpass_fir.kernel[n] + @left_filter.highpass_fir.kernel[n]
    bandstop_kernel[size - 1 - n] = bandstop_kernel[n] = @left_filter.lowpass_fir.kernel[n] + @right_filter.highpass_fir.kernel[n]
  end

  left_transition_freq = @left_cutoff_freq.to_f / @sample_rate
  right_transition_freq = @right_cutoff_freq.to_f / @sample_rate
  bw_times_two = 2.0 * (right_transition_freq - left_transition_freq)
  window_center_val = window.data[@order / 2]
  
  bandpass_kernel[@order / 2] = bw_times_two * window_center_val
  bandstop_kernel[@order / 2] = (1.0 - bw_times_two) * window_center_val
  
  @bandpass_fir = FIR.new bandpass_kernel, @sample_rate
  @bandstop_fir = FIR.new bandstop_kernel, @sample_rate
end

Instance Attribute Details

#bandpass_firObject (readonly)

Returns the value of attribute bandpass_fir.



22
23
24
# File 'lib/spcore/filters/fir/dual_sinc_filter.rb', line 22

def bandpass_fir
  @bandpass_fir
end

#bandstop_firObject (readonly)

Returns the value of attribute bandstop_fir.



22
23
24
# File 'lib/spcore/filters/fir/dual_sinc_filter.rb', line 22

def bandstop_fir
  @bandstop_fir
end

#left_filterObject (readonly)

Returns the value of attribute left_filter.



22
23
24
# File 'lib/spcore/filters/fir/dual_sinc_filter.rb', line 22

def left_filter
  @left_filter
end

#right_filterObject (readonly)

Returns the value of attribute right_filter.



22
23
24
# File 'lib/spcore/filters/fir/dual_sinc_filter.rb', line 22

def right_filter
  @right_filter
end

Instance Method Details

#bandpass(input) ⇒ Array

Process the input with the bandpass FIR.

Returns:

  • (Array)

    containing the filtered input.



74
75
76
# File 'lib/spcore/filters/fir/dual_sinc_filter.rb', line 74

def bandpass input
  return @bandpass_fir.convolve input
end

#bandstop(input) ⇒ Array

Process the input with the bandstop FIR.

Returns:

  • (Array)

    containing the filtered input.



80
81
82
# File 'lib/spcore/filters/fir/dual_sinc_filter.rb', line 80

def bandstop input
  return @bandstop_fir.convolve input
end