Skip to main content

sim_lib_audio_graph_core/
block.rs

1use sim_kernel::{Error, Result};
2
3use crate::{BlockArena, BlockEvent, EventSink, Transport};
4
5/// One processing block handed to a [`Processor`](crate::Processor): input and
6/// output audio lanes, event streams, transport state, and a scratch arena.
7pub struct ProcessBlock<'a> {
8    /// Number of valid frames in each audio lane for this block.
9    pub frames: u32,
10    /// Input audio lanes, one slice per input channel.
11    pub in_audio: &'a [&'a [f32]],
12    /// Output audio lanes, one mutable slice per output channel.
13    pub out_audio: &'a mut [&'a mut [f32]],
14    /// Input events delivered to the processor for this block.
15    pub in_events: &'a [BlockEvent<'a>],
16    /// Sink the processor pushes outgoing events into.
17    pub out_events: &'a mut dyn EventSink,
18    /// Transport state (playhead, tempo, play flag) for this block.
19    pub transport: Transport,
20    /// Per-block scratch allocator for temporary buffers.
21    pub scratch: &'a mut BlockArena,
22}
23
24impl ProcessBlock<'_> {
25    /// Validates that every input and output audio lane holds at least
26    /// [`frames`](Self::frames) samples.
27    pub fn validate_audio_lanes(&self) -> Result<()> {
28        let frames = self.frames as usize;
29        if let Some(len) = self
30            .in_audio
31            .iter()
32            .find_map(|lane| (lane.len() < frames).then_some(lane.len()))
33        {
34            return Err(Error::Eval(format!(
35                "input audio lane has {len} frames, expected at least {frames}"
36            )));
37        }
38        if let Some(len) = self
39            .out_audio
40            .iter()
41            .find_map(|lane| (lane.len() < frames).then_some(lane.len()))
42        {
43            return Err(Error::Eval(format!(
44                "output audio lane has {len} frames, expected at least {frames}"
45            )));
46        }
47        Ok(())
48    }
49}