Class: DSP::Decimator

Inherits:
Object
  • Object
show all
Extended by:
Prepared
Defined in:
lib/dsprb/decimator.rb,
sig/dsprb.rbs

Constant Summary collapse

DEFAULT_TAPS =

An odd tap count keeps the FIR linear phase, so decimation adds no group delay skew.

Returns:

  • (::Integer)
31
CUTOFF_RATIO =

Cutoff as a fraction of the decimated rate, leaving a transition margin below Nyquist.

Returns:

  • (::Float)
0.45

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Prepared

extended, prepared, prepared_count

Constructor Details

#initialize(factor, taps: DEFAULT_TAPS) ⇒ Decimator

Returns a new instance of Decimator.

Parameters:

  • (::Integer)
  • taps: (::Integer) (defaults to: DEFAULT_TAPS)

Raises:

  • (ArgumentError)


23
24
25
26
27
28
29
30
31
32
# File 'lib/dsprb/decimator.rb', line 23

def initialize(factor, taps: DEFAULT_TAPS)
  @factor = Check.at_least!(Integer(factor), 1, "factor")
  @taps = Integer(taps)

  raise ArgumentError, "taps must be a positive odd number, got #{@taps}" unless @taps.positive? && @taps.odd?

  @middle = (@taps - 1) / 2
  @kernel = build_kernel.freeze
  freeze
end

Instance Attribute Details

#factor::Integer (readonly)

Returns the value of attribute factor.

Returns:

  • (::Integer)


13
14
15
# File 'lib/dsprb/decimator.rb', line 13

def factor
  @factor
end

#kernel::Array[::Float] (readonly)

Returns the value of attribute kernel.

Returns:

  • (::Array[::Float])


13
14
15
# File 'lib/dsprb/decimator.rb', line 13

def kernel
  @kernel
end

#taps::Integer (readonly)

Returns the value of attribute taps.

Returns:

  • (::Integer)


13
14
15
# File 'lib/dsprb/decimator.rb', line 13

def taps
  @taps
end

Class Method Details

.factor_for(sample_rate, target) ⇒ ::Integer

Parameters:

  • (::Numeric)
  • (::Numeric)

Returns:

  • (::Integer)


15
# File 'lib/dsprb/decimator.rb', line 15

def self.factor_for(sample_rate, target) = [(sample_rate / target).floor, 1].max

.for(factor, taps: DEFAULT_TAPS) ⇒ Decimator

Parameters:

  • (::Integer)
  • taps: (::Integer) (defaults to: DEFAULT_TAPS)

Returns:



17
# File 'lib/dsprb/decimator.rb', line 17

def self.for(factor, taps: DEFAULT_TAPS) = prepared([factor, taps]) { new(factor, taps: taps) }

.to(waveform, target, taps: DEFAULT_TAPS) ⇒ Waveform

Parameters:

  • (Waveform)
  • (::Numeric)
  • taps: (::Integer) (defaults to: DEFAULT_TAPS)

Returns:



19
20
21
# File 'lib/dsprb/decimator.rb', line 19

def self.to(waveform, target, taps: DEFAULT_TAPS)
  self.for(factor_for(waveform.sample_rate, target), taps: taps).call(waveform)
end

Instance Method Details

#call(waveform) ⇒ Waveform

Parameters:

Returns:



34
35
36
37
38
# File 'lib/dsprb/decimator.rb', line 34

def call(waveform)
  return waveform if @factor == 1

  Waveform.new(samples: filter(waveform.samples), sample_rate: waveform.sample_rate / @factor)
end