The Audio Helpers
src/audio.zig. Small, dependency-free, and covered by the unit tests.
dBToLinear and linearTodB
pub fn dBToLinear(dB: f32) f32 {
return @exp(dB * 0.11512925464970229); // ln(10)/20
}
pub fn linearTodB(linear: f32) f32 {
if (linear <= 0.0) return -80.0;
return @log(linear) * 8.6858896380650365; // 20/ln(10)
}
Both avoid pow and log10 in favour of a single exp or log and a
multiply. linearTodB floors at -80 dB for non-positive input, so silence
returns a finite number rather than negative infinity.
The constants are worth a test of their own, and they have one. A previous copy
of this file carried a stray factor of ten in the exponent, which turned
dBToLinear(6) into 1000.0 instead of 1.9953. src/tests.zig now checks unity
at 0 dB, the factor of two at +6 dB, the factor of ten at +20 dB, and a full
round trip across -48 to +24 dB.
GainProcessor
A gain stage with a built-in ramp.
var g = danzig.GainProcessor{};
g.setGain(6.0); // dB
g.process(&inputs, &outputs, channels, frames);
setGain converts to a linear target. process interpolates the current gain
toward the target by a fixed 0.001 per sample, so a change takes roughly a
thousand samples to substantially complete. setNormalizedGain maps [0, 1]
onto -48 to +48 dB, which is the range the example plugin exposes.
The interpolation coefficient is fixed and not sample-rate aware. For a
rate-independent ramp, use AtomicParam with a millisecond time constant
instead.
SimpleRamp
A linear ramp over a sample count, for anything that is not a gain.
var r = danzig.SimpleRamp.init(0.0, 8); // start value, ramp length in samples
r.setTarget(1.0);
for (0..8) |_| _ = r.next();
// r.getValue() == 1.0
setTarget restarts the ramp from the current value. A ramp length of zero or
one is treated as instant. The final sample is snapped to the target exactly, so
the ramp does not leave a residue.
AudioBuffer
An owned multi-channel buffer, for offline work and tests. It allocates, so keep it off the audio thread.
var buf = try danzig.AudioBuffer.init(allocator, 2, 512, 48000.0);
defer buf.deinit(allocator);
buf.clear();
init zeroes every channel. clear and its alias silence re-zero.