Class: Vizcore::Analysis::BandSplitter

Inherits:
Object
  • Object
show all
Defined in:
lib/vizcore/analysis/band_splitter.rb

Overview

Converts FFT magnitudes into normalized sub/low/mid/high band energies.

Constant Summary collapse

BANDS =

Frequency ranges for each named band in Hz.

{
  sub: [20.0, 60.0],
  low: [60.0, 250.0],
  mid: [250.0, 4000.0],
  high: [4000.0, 20_000.0]
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sample_rate: 44_100, fft_size: 1024) ⇒ BandSplitter

Returns a new instance of BandSplitter.

Parameters:

  • sample_rate (Integer) (defaults to: 44_100)

    input sample rate

  • fft_size (Integer) (defaults to: 1024)

    FFT frame size used to compute magnitudes



19
20
21
22
23
# File 'lib/vizcore/analysis/band_splitter.rb', line 19

def initialize(sample_rate: 44_100, fft_size: 1024)
  @sample_rate = Integer(sample_rate)
  @fft_size = Integer(fft_size)
  @bin_hz = @sample_rate.to_f / @fft_size.to_f
end

Instance Attribute Details

#fft_sizeObject (readonly)

Returns the value of attribute fft_size.



15
16
17
# File 'lib/vizcore/analysis/band_splitter.rb', line 15

def fft_size
  @fft_size
end

#sample_rateObject (readonly)

Returns the value of attribute sample_rate.



15
16
17
# File 'lib/vizcore/analysis/band_splitter.rb', line 15

def sample_rate
  @sample_rate
end

Instance Method Details

#call(magnitudes) ⇒ Hash

Returns normalized energy values for ‘:sub/:low/:mid/:high`.

Parameters:

  • magnitudes (Array<Numeric>)

    FFT magnitude bins

Returns:

  • (Hash)

    normalized energy values for ‘:sub/:low/:mid/:high`



27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/vizcore/analysis/band_splitter.rb', line 27

def call(magnitudes)
  values = normalize_magnitudes(magnitudes)
  return BANDS.transform_values { 0.0 } if values.empty?

  scale = [values.max, 1.0e-9].max

  BANDS.transform_values do |(low_hz, high_hz)|
    indices = band_indices(low_hz, high_hz, values.length)
    next 0.0 if indices.empty?

    average = indices.sum { |index| values[index] } / indices.length.to_f
    (average / scale).clamp(0.0, 1.0)
  end
end