Skip to main content

PairedIo

Struct PairedIo 

Source
pub struct PairedIo<'a> { /* private fields */ }
Expand description

A single borrow over one domain’s whole-block input and this view’s output range.

Audio comes from audio_io / RenderContext::audio_io, analog from analog_io / RenderContext::analog_io.

input always covers the whole block, the same as audio_in(). output and frames are confined to output_range instead: the whole block from a BlockContext, this thread’s share from a RenderContext — the same range audio_frame_range() and its analog counterpart already describe there. That asymmetry is RenderContext’s, not this type’s; on a BlockContext input and output cover the same frames.

There is no digital_io. BelaContext::digital is one combined input/output word buffer — the pin directions and values share it — so a paired view over it would be two aliasing references to the same memory, which is exactly what this type exists to avoid handing out. BlockContext::digital / BlockContext::digital_mut (and their RenderContext counterparts) already reach that buffer.

Implementations§

Source§

impl<'a> PairedIo<'a>

Source

pub const fn input(&self) -> &[f32]

The whole block’s input samples, interleaved. Length is frames * in_channels(), where frames is whichever of audio_frames() / analog_frames() matches this view’s domain.

Source

pub const fn in_channels(&self) -> usize

Number of input channels; see input for the layout it multiplies into.

Source

pub const fn output(&mut self) -> &mut [f32]

This view’s output samples, interleaved — the frames of output_range, so index 0 is channel 0 of output_range().start, not of block frame 0.

Source

pub const fn out_channels(&self) -> usize

Number of output channels; see output for the layout it multiplies into.

Source

pub const fn output_range(&self) -> Range<usize>

The block frames output and frames cover.

Source

pub fn frames(&mut self) -> impl Iterator<Item = (&[f32], &mut [f32])> + '_

Reads and writes one frame at a time: for each frame in output_range, the input channels at that same block frame paired with the output channels to fill in.

This is the aligned path the module documentation promises: input() indexes from block frame 0 and output() from output_range().start, and frames() walks both origins together so a caller never subtracts the offset by hand — the mistake a RenderContext view invites, since its input and output do not start at the same block frame.

let mut io = context.audio_io();
for (input, output) in io.frames() {
    for (sample, value) in output.iter_mut().zip(input) {
        *sample = *value;
    }
}
Examples found in repository?
examples/paired_io_check.rs (line 72)
54    fn render(&self, _state: &mut (), context: &mut RenderContext) {
55        let channels = context
56            .audio_in_channels()
57            .min(context.audio_out_channels());
58        let range = context.audio_frame_range();
59
60        // Ground truth: the indexed path, exactly as `passthrough.rs`
61        // uses it.
62        for frame in range {
63            for channel in 0..channels {
64                let sample = context.audio_read(frame, channel);
65                context.audio_write(frame, channel, sample);
66            }
67        }
68
69        // The paired path, over the same channels — compared against
70        // what the indexed path already wrote, before it overwrites it.
71        let mut io = context.audio_io();
72        for (input, output) in io.frames() {
73            for channel in 0..channels {
74                let expected = output[channel];
75                let paired = input[channel];
76                self.checked.fetch_add(1, Ordering::Relaxed);
77                if paired.to_bits() != expected.to_bits() {
78                    self.mismatches.fetch_add(1, Ordering::Relaxed);
79                }
80                output[channel] = paired;
81            }
82        }
83    }

Trait Implementations§

Source§

impl Debug for PairedIo<'_>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> !UnwindSafe for PairedIo<'a>

§

impl<'a> Freeze for PairedIo<'a>

§

impl<'a> RefUnwindSafe for PairedIo<'a>

§

impl<'a> Send for PairedIo<'a>

§

impl<'a> Sync for PairedIo<'a>

§

impl<'a> Unpin for PairedIo<'a>

§

impl<'a> UnsafeUnpin for PairedIo<'a>

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 = 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.