Skip to main content

AudioTap

Struct AudioTap 

Source
pub struct AudioTap { /* private fields */ }
Expand description

Lock-free single-producer/single-consumer sample tap for the audio → UI analyzer path (audio→UI sample ring).

The audio thread pushes raw samples every process() call; the UI/editor thread drains them once per frame. Both sides use plain atomics only - no locks, no allocation on the producer side - so push is safe to call from a realtime audio callback (agal/skills/00-core/audio-thread-boundary.md).

Declare with #[skip] like any other DSP↔UI shared field the derive default-initializes:

#[derive(Params)]
pub struct AnalyzerParams {
    #[skip]
    pub spectrum_tap: AudioTap,
}

The editor reaches it through the concrete Arc<Self::Params> PluginLogic::editor() already receives (capture it into the build/sync closures) - not through the dyn Params trait, since a raw sample ring isn’t part of the host-automatable parameter surface. FFT / spectrum math stays product-side (lx-analysis, see G16); this type only moves raw samples across the thread boundary.

Single-producer / single-consumer is a caller contract, not enforced by the type: only the audio thread may call push, only the UI/editor thread may call drain.

On overflow (producer outruns the consumer), the oldest unread samples are silently overwritten - the tap never blocks and never grows, matching the audio thread’s no-alloc/no-lock constraint. Need a non-default capacity? #[skip] fields only require Default, so wrap in a newtype with its own Default impl calling AudioTap::new.

Implementations§

Source§

impl AudioTap

Source

pub fn new(capacity: usize) -> Self

New tap with the given capacity in samples. 0 is treated as 1 - a zero-length ring can’t hold a sample.

Source

pub fn capacity(&self) -> usize

Ring capacity in samples.

Source

pub fn push(&self, samples: &[f32])

Push samples from the audio thread. Never allocates, never blocks; overwrites the oldest unread samples on overflow.

Source

pub fn drain(&self) -> Vec<f32>

Drain every sample pushed since the last drain, oldest first. Call from the UI/editor thread. Returns fewer samples than were pushed since the last drain if the producer overflowed the ring in the meantime - the overwritten samples are simply gone.

Trait Implementations§

Source§

impl Default for AudioTap

Source§

fn default() -> Self

Returns the “default value” for a type. 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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.