Class: RockboxFFI::Dsp

Inherits:
Object
  • Object
show all
Defined in:
lib/rockbox_ffi/dsp.rb

Overview

The DSP pipeline: EQ, tone, surround, compressor, ReplayGain, resampler.

The underlying dsp_config is a process-wide singleton, so only one Dsp may exist at a time and it must be used from one thread. Call #close when done, or use the block form Dsp.open(rate) { |dsp| ... }.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sample_rate) ⇒ Dsp

Returns a new instance of Dsp.



22
23
24
25
26
27
28
# File 'lib/rockbox_ffi/dsp.rb', line 22

def initialize(sample_rate)
  @ptr = Lib.rb_dsp_new(Integer(sample_rate))
  raise "rb_dsp_new returned NULL" if @ptr.null?

  @finalizer = self.class.send(:finalizer, @ptr)
  ObjectSpace.define_finalizer(self, @finalizer)
end

Class Method Details

.open(sample_rate) ⇒ Object

Open a Dsp; if a block is given, close it automatically afterwards.



11
12
13
14
15
16
17
18
19
20
# File 'lib/rockbox_ffi/dsp.rb', line 11

def self.open(sample_rate)
  dsp = new(sample_rate)
  return dsp unless block_given?

  begin
    yield dsp
  ensure
    dsp.close
  end
end

Instance Method Details

#closeObject

-- lifecycle --------------------------------------------------------



31
32
33
34
35
36
37
# File 'lib/rockbox_ffi/dsp.rb', line 31

def close
  return if @ptr.nil?

  ObjectSpace.undefine_finalizer(self)
  Lib.rb_dsp_free(@ptr)
  @ptr = nil
end

#closed?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/rockbox_ffi/dsp.rb', line 39

def closed?
  @ptr.nil?
end

#eq_enable(enable) ⇒ Object



57
58
59
# File 'lib/rockbox_ffi/dsp.rb', line 57

def eq_enable(enable)
  Lib.rb_dsp_eq_enable(@ptr, RockboxFFI.b(enable))
end

#flushObject



53
54
55
# File 'lib/rockbox_ffi/dsp.rb', line 53

def flush
  Lib.rb_dsp_flush(@ptr)
end

#process(samples) ⇒ Object

-- processing ------------------------------------------------------- Run interleaved stereo S16 samples (an Array of Integers) through the pipeline. Returns a new Array of processed samples (length may differ from the input — the resampler buffers).

Raises:

  • (ArgumentError)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/rockbox_ffi/dsp.rb', line 122

def process(samples)
  raise ArgumentError, "input must be interleaved stereo (even length)" if samples.length.odd?

  input = samples.pack("s<*")               # int16 little-endian
  out_len = "\0" * Fiddle::SIZEOF_VOIDP      # size_t* out-param (written in place)
  out_ptr = Lib.rb_dsp_process(@ptr, input, samples.length, out_len)

  produced = out_len.unpack1(Fiddle::SIZEOF_VOIDP == 8 ? "Q" : "L")
  return [] if out_ptr.null? || produced.zero?

  begin
    out_ptr.size = produced * 2
    out_ptr[0, produced * 2].unpack("s<*")
  ensure
    Lib.rb_buffer_free(out_ptr, produced)
  end
end

#set_channel_config(mode) ⇒ Object



82
83
84
# File 'lib/rockbox_ffi/dsp.rb', line 82

def set_channel_config(mode)
  Lib.rb_dsp_set_channel_config(@ptr, Integer(mode))
end

#set_compressor(threshold, makeup_gain, ratio, knee, release_time, attack_time) ⇒ Object



90
91
92
93
94
95
# File 'lib/rockbox_ffi/dsp.rb', line 90

def set_compressor(threshold, makeup_gain, ratio, knee, release_time, attack_time)
  Lib.rb_dsp_set_compressor(
    @ptr, Integer(threshold), Integer(makeup_gain), Integer(ratio),
    Integer(knee), Integer(release_time), Integer(attack_time)
  )
end

#set_eq_band(band, cutoff_hz, q, gain_db) ⇒ Object

Configure one EQ band (0..=9). Band 0 low shelf, 9 high shelf.



62
63
64
# File 'lib/rockbox_ffi/dsp.rb', line 62

def set_eq_band(band, cutoff_hz, q, gain_db)
  Lib.rb_dsp_set_eq_band(@ptr, Integer(band), Integer(cutoff_hz), Float(q), Float(gain_db))
end

#set_eq_precut(db) ⇒ Object



66
67
68
# File 'lib/rockbox_ffi/dsp.rb', line 66

def set_eq_precut(db)
  Lib.rb_dsp_set_eq_precut(@ptr, Float(db))
end

#set_input_frequency(hz) ⇒ Object

-- configuration ----------------------------------------------------



49
50
51
# File 'lib/rockbox_ffi/dsp.rb', line 49

def set_input_frequency(hz)
  Lib.rb_dsp_set_input_frequency(@ptr, Integer(hz))
end

#set_replaygain(mode, noclip, preamp_db) ⇒ Object

mode: see DspReplayGainMode (TRACK=0, ALBUM=1, SHUFFLE=2, OFF=3).



98
99
100
# File 'lib/rockbox_ffi/dsp.rb', line 98

def set_replaygain(mode, noclip, preamp_db)
  Lib.rb_dsp_set_replaygain(@ptr, Integer(mode), RockboxFFI.b(noclip), Float(preamp_db))
end

#set_replaygain_gains(track_gain_db: nil, album_gain_db: nil, track_peak: nil, album_peak: nil) ⇒ Object

Per-track gains in plain dB / peaks as linear amplitude (1.0 = full scale). nil for any absent tag (mapped to the ABI's NaN sentinel).



104
105
106
107
108
# File 'lib/rockbox_ffi/dsp.rb', line 104

def set_replaygain_gains(track_gain_db: nil, album_gain_db: nil, track_peak: nil, album_peak: nil)
  Lib.rb_dsp_set_replaygain_gains(
    @ptr, opt(track_gain_db), opt(album_gain_db), opt(track_peak), opt(album_peak)
  )
end

#set_replaygain_gains_raw(track_gain, album_gain, track_peak, album_peak) ⇒ Object

Native Q7.24 linear factors (the raw_* fields from Metadata.read), 0 = not tagged.



112
113
114
115
116
# File 'lib/rockbox_ffi/dsp.rb', line 112

def set_replaygain_gains_raw(track_gain, album_gain, track_peak, album_peak)
  Lib.rb_dsp_set_replaygain_gains_raw(
    @ptr, Integer(track_gain), Integer(album_gain), Integer(track_peak), Integer(album_peak)
  )
end

#set_stereo_width(percent) ⇒ Object



86
87
88
# File 'lib/rockbox_ffi/dsp.rb', line 86

def set_stereo_width(percent)
  Lib.rb_dsp_set_stereo_width(@ptr, Integer(percent))
end

#set_surround(delay_ms, balance, fx1, fx2) ⇒ Object



78
79
80
# File 'lib/rockbox_ffi/dsp.rb', line 78

def set_surround(delay_ms, balance, fx1, fx2)
  Lib.rb_dsp_set_surround(@ptr, Integer(delay_ms), Integer(balance), Integer(fx1), Integer(fx2))
end

#set_tone(bass_db, treble_db) ⇒ Object



70
71
72
# File 'lib/rockbox_ffi/dsp.rb', line 70

def set_tone(bass_db, treble_db)
  Lib.rb_dsp_set_tone(@ptr, Integer(bass_db), Integer(treble_db))
end

#set_tone_cutoffs(bass_hz, treble_hz) ⇒ Object



74
75
76
# File 'lib/rockbox_ffi/dsp.rb', line 74

def set_tone_cutoffs(bass_hz, treble_hz)
  Lib.rb_dsp_set_tone_cutoffs(@ptr, Integer(bass_hz), Integer(treble_hz))
end