Struct DelayLine
pub struct DelayLine { /* private fields */ }Expand description
Generic delay line: a ring buffer with WDF-compatible ports.
This is a two-port element that splits the WDF tree into separate subtrees coupled by an implicit one-sample delay. The write side accepts signal from the “record” subtree; the read side feeds the “playback” subtree(s).
The delay time is continuously modulatable — changing it at audio rate moves the read pointer smoothly, creating pitch bending effects.
§WDF integration
The compiler detects delay_line() in a netlist and automatically
splits the WDF tree at that point. Trees are processed in order:
write tree first (fills buffer), then read tree(s) consume from it.
The implicit one-sample delay between write and read ensures causality.
§Multi-tap
Multiple Tap elements can read from the same DelayLine at
different positions (ratios of the base delay time). This models
multi-head tape machines (RE-201) and multi-tap digital delays.
Implementations§
§impl DelayLine
impl DelayLine
pub fn new(
min_delay_sec: f64,
max_delay_sec: f64,
sample_rate: f64,
interpolation: Interpolation,
) -> DelayLine
pub fn new( min_delay_sec: f64, max_delay_sec: f64, sample_rate: f64, interpolation: Interpolation, ) -> DelayLine
Create a new delay line.
min_delay_sec— minimum delay in seconds (e.g., 0.001 for 1ms)max_delay_sec— maximum delay in seconds (e.g., 1.2 for 1200ms)sample_rate— audio sample rate in Hzinterpolation— fractional-sample interpolation mode
pub fn write(&mut self, input: f64)
pub fn write(&mut self, input: f64)
Write a sample into the delay buffer, process medium zones, and advance the write pointer.
The input signal is mixed with the feedback sample before writing. After writing, zone-based medium processing runs on any samples that have crossed zone boundaries since the last tick. Call this once per audio sample, before reading any taps.
pub fn read(&mut self) -> f64
pub fn read(&mut self) -> f64
Read from the delay buffer at the current base delay time.
Returns the interpolated sample at write_pos - current_delay_samples.
This is equivalent to reading from tap ratio 1.0.
pub fn read_at_ratio(&mut self, ratio: f64, tap_index: usize) -> f64
pub fn read_at_ratio(&mut self, ratio: f64, tap_index: usize) -> f64
Read from the delay buffer at a specific ratio of the base delay.
ratio— multiplier for the base delay (e.g., 2.0 = twice the delay)tap_index— index for allpass state tracking (0 = base, 1+ = taps)
The effective delay in samples is:
current_delay_samples * speed_mod * ratio
pub fn set_delay_normalized(&mut self, norm: f64)
pub fn set_delay_normalized(&mut self, norm: f64)
Set the delay time as a normalized value (0.0 = min, 1.0 = max).
Uses logarithmic interpolation for a natural feel — small changes at short delays, larger changes at long delays.
pub fn set_delay_seconds(&mut self, seconds: f64)
pub fn set_delay_seconds(&mut self, seconds: f64)
Set the delay time in seconds directly.
pub fn set_speed_mod(&mut self, factor: f64)
pub fn set_speed_mod(&mut self, factor: f64)
Set the speed modulation factor.
A value of 1.0 means no modulation. Values > 1.0 slow the “tape” (longer delay, lower pitch). Values < 1.0 speed it up. Typically modulated by an LFO for wow/flutter effects.
pub fn add_speed_mod(&mut self, offset: f64)
pub fn add_speed_mod(&mut self, offset: f64)
Add a speed modulation offset (additive, for multiple LFO sources).
The total speed_mod = 1.0 + sum of all modulation offsets.
pub fn reset_speed_mod(&mut self)
pub fn reset_speed_mod(&mut self)
Reset speed modulation to 1.0 (called at start of each sample).
pub fn set_feedback(&mut self, feedback: f64)
pub fn set_feedback(&mut self, feedback: f64)
Set the feedback amount.
pub fn set_feedback_sample(&mut self, sample: f64)
pub fn set_feedback_sample(&mut self, sample: f64)
Store the feedback sample (called after downstream processing).
pub fn delay_time(&self) -> f64
pub fn delay_time(&self) -> f64
Get the current delay time in seconds.
pub fn effective_delay_samples(&self) -> f64
pub fn effective_delay_samples(&self) -> f64
Get the current delay time in samples (with speed modulation).
pub fn set_sample_rate(&mut self, sample_rate: f64)
pub fn set_sample_rate(&mut self, sample_rate: f64)
Update for a new sample rate.
pub fn ensure_tap_capacity(&mut self, max_ratio: f64)
pub fn ensure_tap_capacity(&mut self, max_ratio: f64)
Grow the ring buffer so a tap at max_ratio × the base delay can be
read without clamping. DelayLine::new sizes the buffer for the base
(head-1) max_delay only; a multi-head tape (RE-201 heads at 2x/3x)
reads up to max_ratio × max_delay, which would otherwise clamp at the
buffer end (heads 2/3 collapse onto the buffer-max position). The base
max_delay_sec — and thus the set_delay_normalized log law — is
unchanged; only the storage grows. No-op when max_ratio <= 1.0 or the
buffer already fits.
pub fn reset(&mut self)
pub fn reset(&mut self)
Reset all state (buffer, allpass states, feedback).
pub fn min_delay_sec(&self) -> f64
pub fn min_delay_sec(&self) -> f64
Minimum delay in seconds.
pub fn max_delay_sec(&self) -> f64
pub fn max_delay_sec(&self) -> f64
Maximum delay in seconds.
pub fn set_medium(&mut self, medium: Medium)
pub fn set_medium(&mut self, medium: Medium)
Set the physical storage medium model.
pub fn sample_rate(&self) -> f64
pub fn sample_rate(&self) -> f64
Get the current sample rate.
pub fn write_direct(&mut self, sample: f64)
pub fn write_direct(&mut self, sample: f64)
Write a sample directly to the buffer without feedback mixing.
Does NOT advance the write position — call [advance_write] after
reading to complete the tick. This is used by BbdDelayLine which
manages its own feedback path (with soft-clipping between mix and write).
pub fn buffer_read(&mut self, delay_samples: f64, tap_slot: usize) -> f64
pub fn buffer_read(&mut self, delay_samples: f64, tap_slot: usize) -> f64
Read from the buffer at the given delay (in samples), using the current interpolation mode.
Lower-level than [read]/[read_at_ratio]: the caller supplies the
exact fractional-sample delay instead of using the stored delay time.
pub fn advance_write(&mut self)
pub fn advance_write(&mut self)
Advance the write position by one sample and run medium processing.
Must be called exactly once per tick, after [write_direct] and
any reads are complete.
pub fn configure_zones_from_taps(
&mut self,
tap_ratios: &[f64],
coefficients: Option<&[f64]>,
)
pub fn configure_zones_from_taps( &mut self, tap_ratios: &[f64], coefficients: Option<&[f64]>, )
Configure zone boundaries from tap ratios.
Creates one zone boundary at each tap position, with coefficients that increase with distance (modeling progressive signal degradation). An additional zone is placed at the end of the buffer for the feedback path.
tap_ratios— tap positions as ratios of base delay (e.g., [1.0, 2.0, 4.0])coefficients— optional per-zone LP coefficients; ifNone, uses defaults based on medium type and tap count