Skip to main content

BbdDelayLine

Struct BbdDelayLine 

pub struct BbdDelayLine {
    pub model: BbdModel,
    /* private fields */
}
Expand description

BBD delay line processor.

Implements a physically-modeled bucket-brigade delay with:

  • Variable delay time (via clock frequency)
  • Anti-alias filtering (models the BBD’s Nyquist limit)
  • Subtle soft clipping (BBDs clip gently at high levels)
  • Noise injection (characteristic BBD hiss)
  • Compander with proper envelope tracking

The delay buffer uses linear interpolation for fractional-sample delay, modeling the smooth time modulation of chorus/flanger effects.

§Compander Architecture

Real BBD companders (NE570/NE571) work by:

  1. Compressing the input signal using the INPUT envelope
  2. Delaying the compressed signal through the BBD
  3. Expanding using a DELAYED version of the compression envelope
  4. The tracking error between compression and expansion envelopes causes characteristic “breathing” and “pumping” artifacts

The expander must use the delayed compression envelope, NOT an independent envelope of the output signal, to achieve unity gain in steady state while preserving the analog artifacts.

Fields§

§model: BbdModel

Implementations§

§

impl BbdDelayLine

pub fn new(model: BbdModel, sample_rate: f64) -> BbdDelayLine

Create a new BBD delay line.

Buffer size is determined by the maximum delay time at the current sample rate, plus headroom for interpolation.

pub fn set_clock(&mut self, clock_hz: f64)

Set the clock frequency directly (Hz).

This controls the delay time: delay = num_stages / (2 * fclk). Modulating this with an LFO creates chorus/flanger effects.

pub fn set_delay_normalized(&mut self, norm: f64)

Set delay time as a normalized value (0.0 = min delay, 1.0 = max delay).

Maps logarithmically across the clock frequency range.

pub fn set_feedback(&mut self, feedback: f64)

Set feedback amount (0.0 = no feedback, <1.0 for stability).

pub fn process(&mut self, input: f64) -> f64

Process one sample through the BBD delay line.

Signal chain (models real BBD circuit with NE571-style companding):

  1. Compander input stage: compress dynamic range (NE571 compressor)
  2. Store compression envelope in delay buffer
  3. Soft clip to BBD voltage swing limit
  4. Write to delay buffer (with feedback)
  5. Read from buffer with interpolation
  6. Charge leakage LPF (darker at longer delays)
  7. Anti-alias LPF (BBD Nyquist bandwidth limit)
  8. Clock feedthrough injection
  9. Noise injection
  10. Read DELAYED compression envelope for expander
  11. Expand using delayed envelope (restores original dynamics)
  12. Apply tracking error as small modulation artifact

pub fn set_sample_rate(&mut self, sample_rate: f64)

Update sample rate and resize buffer.

pub fn reset(&mut self)

Reset all state.

pub fn delay_time(&self) -> f64

Get current delay time in seconds.

pub fn clock_freq(&self) -> f64

Get current clock frequency.

Trait Implementations§

§

impl Clone for BbdDelayLine

§

fn clone(&self) -> BbdDelayLine

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for BbdDelayLine

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more