Bounded live audio adapter
examples/tutorials/src/ui/audio.rs · 561 source lines
Read the chapters in source order. Select a numbered source line to expand its explanation; the line numbers and code match this snapshot exactly.
cargo test -p ravet-examples --lib --lockedChapters
- Define routing and bounded shared state lines 1–44
- Commands and engine ownership lines 45–70
- Construct the audio owner before callbacks lines 71–104
- Adapt the stereo scratch into a portable block lines 105–118
- Apply MIDI without advancing samples lines 119–134
- Prepare routing and scratch storage lines 135–179
- Validate and honor panic requests lines 180–207
- Consume bounded control commands lines 208–228
- Detect dropped native MIDI packets lines 229–247
- Poll MIDI fairly with a fixed budget lines 248–267
- Fill effect input and input meters lines 268–307
- Render and distribute selected output pairs lines 308–336
- Publish coherent meters and voice telemetry lines 337–377
- Reset or deactivate the inner engine lines 378–390
- Test the adapter without native devices lines 391–561
Define routing and bounded shared state
MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
1//! Bounded example-level command handoff; device adapters remain unchanged.
Source note: Bounded example-level command handoff; device adapters remain unchanged.
Link to line 12use crate::delay::DelayProcessor;
Bring these module/type names into scope for “Define routing and bounded shared state”; the surrounding chapter explains their responsibilities.
Link to line 23use crate::synth::{SubtractiveSynth, SynthPatch};
Bring these module/type names into scope for “Define routing and bounded shared state”; the surrounding chapter explains their responsibilities.
Link to line 34use ravet_foundation::{
Bring these module/type names into scope for “Define routing and bounded shared state”; the surrounding chapter explains their responsibilities.
Link to line 45 AudioBuffer, AudioLayout, Event, EventData, MidiMessage, PrepareError, ProcessBlock,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 56 ProcessConfig, ProcessError, ProcessStatus, Processor, SnapshotMailbox, Transport,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 67};
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 78use ravet_signal::PeakRmsMeter;
Bring these module/type names into scope for “Define routing and bounded shared state”; the surrounding chapter explains their responsibilities.
Link to line 89use std::sync::{
Bring these module/type names into scope for “Define routing and bounded shared state”; the surrounding chapter explains their responsibilities.
Link to line 910 Arc,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 1011 atomic::{AtomicBool, Ordering},
Define or initialize atomic with the displayed type/value. Its ownership and use are described in “Define routing and bounded shared state”.
Link to line 1112};
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 1213
Blank line separating the surrounding statements.
Link to line 1314pub const MAX_FRAMES: usize = 512;
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 1415pub const QUEUE: usize = 16;
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 1516const MIDI_BUDGET: usize = 64;
Declare this compile-time constant or fixed array. The value and physical/capacity meaning are given by its source comment and this chapter.
Link to line 1617pub struct Routing {
Declare the state/type or implementation used by this chapter. MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
Link to line 1718 pub input: u64,
Define or initialize input with the displayed type/value. Its ownership and use are described in “Define routing and bounded shared state”.
Link to line 1819 pub output: u64,
Define or initialize output with the displayed type/value. Its ownership and use are described in “Define routing and bounded shared state”.
Link to line 1920}
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 2021impl Default for Routing {
Declare the state/type or implementation used by this chapter. MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
Link to line 2122 fn default() -> Self {
Define default. MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
Link to line 2223 Self {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Define routing and bounded shared state” explanation above.
Link to line 2324 input: 3,
Select input channels zero and one: bitmask 3 is binary 11.
Link to line 2425 output: 3,
Select output channels zero and one using the same two-bit default mask.
Link to line 2526 }
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 2627 }
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 2728}
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 2829struct MidiSource {
Declare the state/type or implementation used by this chapter. MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
Link to line 2930 receiver: ravet_midi_device::MidiReceiver,
Define or initialize receiver with the displayed type/value. Its ownership and use are described in “Define routing and bounded shared state”.
Link to line 3031 dropped: u64,
Cumulative MIDI packet-loss count retained for the UI.
Link to line 3132}
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 3233pub struct Shared {
Declare the state/type or implementation used by this chapter. MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
Link to line 3334 pub telemetry: SnapshotMailbox<80>,
An 80-word coherent snapshot mailbox; it carries latest state rather than an ordered event stream.
Link to line 3435 pub panic: AtomicBool,
Atomic reset request set by UI cancellation or queue overflow.
Link to line 3536}
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 3637impl Shared {
Declare the state/type or implementation used by this chapter. MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
Link to line 3738 pub fn new() -> Arc<Self> {
Define new. MAX_FRAMES=512 limits prepared sub-blocks; QUEUE=16 limits control handoff; MIDI_BUDGET=64 bounds polling. Routing bitmasks choose input/output channel pairs. Shared owns an 80-word coherent mailbox and an atomic panic request. Native MIDI sources retain a previous drop count.
Link to line 3839 Arc::new(Self {
Define or initialize Arc with the displayed type/value. Its ownership and use are described in “Define routing and bounded shared state”.
Link to line 3940 telemetry: SnapshotMailbox::new([0; 80]),
Initialize the coherent fixed-size telemetry mailbox with an all-zero record.
Link to line 4041 panic: AtomicBool::new(false),
Initialize the shared panic/reset request flag as clear.
Link to line 4142 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 4243 }
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 4344}
Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.
Link to line 44Commands and engine ownership
Commands carry a fixed SynthPatch, five delay controls, a demo flag or typed MIDI. The enum deliberately avoids heap-owned patch destruction in callbacks. Engine boxes the synth or delay outside processing. Audio owns the consumer, native receivers, routing, stereo scratch, configuration and counters.
45// Fixed storage deliberately avoids heap-owned patch destruction in the callback.
Source note: Fixed storage deliberately avoids heap-owned patch destruction in the callback.
Link to line 4546#[allow(clippy::large_enum_variant)]
Apply this Rust attribute to the following item. cfg selects which target/feature/test build contains it; derive generates the named trait implementations.
Link to line 4647pub enum Command {
Declare the state/type or implementation used by this chapter. Commands carry a fixed SynthPatch, five delay controls, a demo flag or typed MIDI. The enum deliberately avoids heap-owned patch destruction in callbacks. Engine boxes the synth or delay outside processing. Audio owns the consumer, native receivers, routing, stereo scratch, configuration and counters.
Link to line 4748 Patch(SynthPatch),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Commands and engine ownership” explanation above.
Link to line 4849 Delay([f32; 5]),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Commands and engine ownership” explanation above.
Link to line 4950 Demo(bool),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Commands and engine ownership” explanation above.
Link to line 5051 Midi(MidiMessage),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Commands and engine ownership” explanation above.
Link to line 5152}
Close the surrounding scope, value or argument list in “Commands and engine ownership”.
Link to line 5253enum Engine {
Declare the state/type or implementation used by this chapter. Commands carry a fixed SynthPatch, five delay controls, a demo flag or typed MIDI. The enum deliberately avoids heap-owned patch destruction in callbacks. Engine boxes the synth or delay outside processing. Audio owns the consumer, native receivers, routing, stereo scratch, configuration and counters.
Link to line 5354 Synth(Box<SubtractiveSynth>),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Commands and engine ownership” explanation above.
Link to line 5455 Effect(Box<DelayProcessor>),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Commands and engine ownership” explanation above.
Link to line 5556}
Close the surrounding scope, value or argument list in “Commands and engine ownership”.
Link to line 5657pub struct Audio {
Declare the state/type or implementation used by this chapter. Commands carry a fixed SynthPatch, five delay controls, a demo flag or typed MIDI. The enum deliberately avoids heap-owned patch destruction in callbacks. Engine boxes the synth or delay outside processing. Audio owns the consumer, native receivers, routing, stereo scratch, configuration and counters.
Link to line 5758 engine: Engine,
Define or initialize engine with the displayed type/value. Its ownership and use are described in “Commands and engine ownership”.
Link to line 5859 commands: rtrb::Consumer<Command>,
The audio-side consumer of the bounded UI command ring.
Link to line 5960 midi: Vec<MidiSource>,
Prepared native input receivers and their last observed loss counts.
Link to line 6061 routing: Routing,
Channel-selection bitmasks validated during preparation.
Link to line 6162 midi_cursor: usize,
Retained round-robin cursor for fair native MIDI polling.
Link to line 6263 shared: Arc<Shared>,
Reference-counted mailbox and reset flag shared with the main-thread owner.
Link to line 6364 scratch: [Vec<f32>; 2],
Prepared planar stereo scratch; callbacks borrow only the active prefix.
Link to line 6465 config: Option<ProcessConfig>,
Processing limits. An optional configuration in processor-owned state is None until preparation succeeds.
Link to line 6566 demo: bool,
Whether the effect input uses the synthetic demonstration source.
Link to line 6667 phase: [f64; 2],
Retained oscillator phases for the demo input.
Link to line 6768 frames: u64,
Cumulative rendered frame count for telemetry.
Link to line 6869 dropped: u64,
Cumulative MIDI packet-loss count retained for the UI.
Link to line 6970}
Close the surrounding scope, value or argument list in “Commands and engine ownership”.
Link to line 70Construct the audio owner before callbacks
Choose the engine and transform native receivers into tracked sources. Allocate ownership structures outside the callback; scratch is initially empty and configuration inactive. Store shared telemetry and selected routing.
71impl Audio {
Declare the state/type or implementation used by this chapter. Choose the engine and transform native receivers into tracked sources. Allocate ownership structures outside the callback; scratch is initially empty and configuration inactive. Store shared telemetry and selected routing.
Link to line 7172 pub fn new(
Define new. Choose the engine and transform native receivers into tracked sources. Allocate ownership structures outside the callback; scratch is initially empty and configuration inactive. Store shared telemetry and selected routing.
Link to line 7273 synth: bool,
Define or initialize synth with the displayed type/value. Its ownership and use are described in “Construct the audio owner before callbacks”.
Link to line 7374 demo: bool,
Whether the effect input uses the synthetic demonstration source.
Link to line 7475 commands: rtrb::Consumer<Command>,
The audio-side consumer of the bounded UI command ring.
Link to line 7576 midi: Vec<ravet_midi_device::MidiReceiver>,
Prepared native input receivers and their last observed loss counts.
Link to line 7677 shared: Arc<Shared>,
Reference-counted mailbox and reset flag shared with the main-thread owner.
Link to line 7778 routing: Routing,
Channel-selection bitmasks validated during preparation.
Link to line 7879 ) -> Self {
Complete the function’s parameter list and specify the return type. A Result preserves the explicit success/error distinction.
Link to line 7980 Self {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Construct the audio owner before callbacks” explanation above.
Link to line 8081 engine: if synth {
Define or initialize engine with the displayed type/value. Its ownership and use are described in “Construct the audio owner before callbacks”.
Link to line 8182 Engine::Synth(Box::default())
Define or initialize Engine with the displayed type/value. Its ownership and use are described in “Construct the audio owner before callbacks”.
Link to line 8283 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Construct the audio owner before callbacks” explanation above.
Link to line 8384 Engine::Effect(Box::default())
Define or initialize Engine with the displayed type/value. Its ownership and use are described in “Construct the audio owner before callbacks”.
Link to line 8485 },
Close the surrounding scope, value or argument list in “Construct the audio owner before callbacks”.
Link to line 8586 commands,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 8687 midi: midi
Prepared native input receivers and their last observed loss counts.
Link to line 8788 .into_iter()
Consume the collection into an owning iterator; its elements are moved into the following transformation.
Link to line 8889 .map(|receiver| MidiSource {
Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.
Link to line 8990 receiver,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 9091 dropped: 0,
Cumulative MIDI packet-loss count retained for the UI.
Link to line 9192 })
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 9293 .collect(),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Construct the audio owner before callbacks” explanation above.
Link to line 9394 routing,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 9495 midi_cursor: 0,
Retained round-robin cursor for fair native MIDI polling.
Link to line 9596 shared,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 9697 scratch: [Vec::new(), Vec::new()],
Start with empty stereo scratch; prepare allocates the required capacities later.
Link to line 9798 config: None,
Processing limits. An optional configuration in processor-owned state is None until preparation succeeds.
Link to line 9899 demo,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 99100 phase: [0.; 2],
Retained oscillator phases for the demo input.
Link to line 100101 frames: 0,
Cumulative rendered frame count for telemetry.
Link to line 101102 dropped: 0,
Cumulative MIDI packet-loss count retained for the UI.
Link to line 102103 }
Close the surrounding scope, value or argument list in “Construct the audio owner before callbacks”.
Link to line 103104 }
Close the surrounding scope, value or argument list in “Construct the audio owner before callbacks”.
Link to line 104Adapt the stereo scratch into a portable block
Instruments have empty input and separate output; effects use in-place stereo scratch. Borrow exactly the active frames, build a default-transport block and dispatch to the chosen engine. The prepared bounds justify expect.
105 fn process_inner(&mut self, frames: usize, events: &[Event]) -> ProcessStatus {
Define process_inner. Instruments have empty input and separate output; effects use in-place stereo scratch. Borrow exactly the active frames, build a default-transport block and dispatch to the chosen engine. The prepared bounds justify expect.
Link to line 105106 let [left, right] = &mut self.scratch;
Borrow the two owned scratch vectors separately for channel views.
Link to line 106107 let mut views = [&mut left[..frames], &mut right[..frames]];
Restrict both mutable channel views to this callback’s active frame prefix.
Link to line 107108 let audio = match self.engine {
Bind audio to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 108109 Engine::Synth(_) => AudioBuffer::separate(&[], &mut views, frames),
Borrow distinct input/output slices. An instrument supplies an empty input slice; output storage already belongs to the caller.
Link to line 109110 Engine::Effect(_) => AudioBuffer::in_place(&mut views, frames),
Borrow the active mutable channel slices as both effect input and output. Constructing the view does not allocate audio storage.
Link to line 110111 }
Close the surrounding scope, value or argument list in “Adapt the stereo scratch into a portable block”.
Link to line 111112 .expect("prepared stereo scratch");
Require the invariant “prepared stereo scratch”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 112113 let mut block = ProcessBlock::new(audio, events, Transport::default());
Combine borrowed audio, the active input-event slice and explicit transport into one processing view.
Link to line 113114 match &mut self.engine {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Adapt the stereo scratch into a portable block”.
Link to line 114115 Engine::Synth(s) => s.process(&mut block),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 115116 Engine::Effect(g) => g.process(&mut block),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 116117 }
Close the surrounding scope, value or argument list in “Adapt the stereo scratch into a portable block”.
Link to line 117118 }
Close the surrounding scope, value or argument list in “Adapt the stereo scratch into a portable block”.
Link to line 118Apply MIDI without advancing samples
Submit a zero-frame block with one offset-zero MIDI event. This updates voice state at the block boundary but advances no envelope or oscillator. reset_engine dispatches reset to the active engine.
119 fn flush_midi(&mut self, message: MidiMessage) {
Define flush_midi. Submit a zero-frame block with one offset-zero MIDI event. This updates voice state at the block boundary but advances no envelope or oscillator. reset_engine dispatches reset to the active engine.
Link to line 119120 self.process_inner(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Apply MIDI without advancing samples” explanation above.
Link to line 120121 0,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 121122 &[Event {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Apply MIDI without advancing samples” explanation above.
Link to line 122123 frame_offset: 0,
The event’s timing coordinate, interpreted relative to its current clip/block context.
Link to line 123124 data: EventData::Midi(message),
Typed event payload; timing is kept separately in frame_offset.
Link to line 124125 }],
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 125126 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 126127 }
Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.
Link to line 127128 fn reset_engine(&mut self) {
Define reset_engine. Submit a zero-frame block with one offset-zero MIDI event. This updates voice state at the block boundary but advances no envelope or oscillator. reset_engine dispatches reset to the active engine.
Link to line 128129 match &mut self.engine {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Apply MIDI without advancing samples”.
Link to line 129130 Engine::Synth(s) => s.reset(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 130131 Engine::Effect(g) => g.reset(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 131132 }
Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.
Link to line 132133 }
Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.
Link to line 133134}
Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.
Link to line 134Prepare routing and scratch storage
Reject blocks beyond 512 frames, auxiliary buses and emitted events. Validate nonempty masks against available channels, avoiding a shift by 64, and at most 16 MIDI inputs. Prepare the inner stereo engine with event capacity two and allocate stereo scratch before activation.
135impl Processor for Audio {
Declare the state/type or implementation used by this chapter. Reject blocks beyond 512 frames, auxiliary buses and emitted events. Validate nonempty masks against available channels, avoiding a shift by 64, and at most 16 MIDI inputs. Prepare the inner stereo engine with event capacity two and allocate stereo scratch before activation.
Link to line 135136 fn prepare(&mut self, config: ProcessConfig) -> Result<(), PrepareError> {
Define prepare. Reject blocks beyond 512 frames, auxiliary buses and emitted events. Validate nonempty masks against available channels, avoiding a shift by 64, and at most 16 MIDI inputs. Prepare the inner stereo engine with event capacity two and allocate stereo scratch before activation.
Link to line 136137 self.config = None;
Mark the processor inactive before preparation or after deactivation; a failed setup must not retain an apparently valid configuration.
Link to line 137138 if config.maximum_frames() > MAX_FRAMES
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Prepare routing and scratch storage”.
Link to line 138139 || !config.auxiliary_buses().is_empty()
Accept this alternative condition in the surrounding check; evaluation stops once the combined condition is true.
Link to line 139140 || config.maximum_output_events() != 0
Accept this alternative condition in the surrounding check; evaluation stops once the combined condition is true.
Link to line 140141 {
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 141142 return Err(PrepareError::InvalidMaximumFrames);
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 142143 }
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 143144 let channels = config.layout().output_channels();
Bind channels to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 144145 let valid = if channels == 64 {
Bind valid to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 145146 u64::MAX
Allow all 64 channel bits without shifting a u64 by 64, which would be invalid.
Link to line 146147 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Prepare routing and scratch storage” explanation above.
Link to line 147148 (1u64 << channels) - 1
Construct a low-channel mask for a channel count below 64.
Link to line 148149 };
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 149150 if self.routing.output == 0 || self.routing.output & !valid != 0 || self.midi.len() > 16 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Prepare routing and scratch storage”.
Link to line 150151 return Err(PrepareError::UnsupportedLayout);
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 151152 }
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 152153 if config.layout().input_channels() > 0 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Prepare routing and scratch storage”.
Link to line 153154 let channels = config.layout().input_channels();
Bind channels to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 154155 let valid = if channels == 64 {
Bind valid to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 155156 u64::MAX
Allow all 64 channel bits without shifting a u64 by 64, which would be invalid.
Link to line 156157 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Prepare routing and scratch storage” explanation above.
Link to line 157158 (1u64 << channels) - 1
Construct a low-channel mask for a channel count below 64.
Link to line 158159 };
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 159160 if self.routing.input == 0 || self.routing.input & !valid != 0 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Prepare routing and scratch storage”.
Link to line 160161 return Err(PrepareError::UnsupportedLayout);
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 161162 }
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 162163 }
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 163164 let layout = match self.engine {
Bind layout to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 164165 Engine::Synth(_) => AudioLayout::STEREO_INSTRUMENT,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 165166 Engine::Effect(_) => AudioLayout::STEREO,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 166167 };
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 167168 let inner = ProcessConfig::new(config.sample_rate(), config.maximum_frames(), 2, layout)?;
Bind inner to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 168169 match &mut self.engine {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Prepare routing and scratch storage”.
Link to line 169170 Engine::Synth(s) => s.prepare(inner)?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 170171 Engine::Effect(g) => g.prepare(inner)?,
The ? operator returns an error immediately on failure and unwraps the success value for the next step.
Link to line 171172 };
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 172173 self.scratch = [
Assign the computed value to self.scratch. The right-hand expression supplies the new value for this step.
Link to line 173174 vec![0.; config.maximum_frames()],
Allocate one zeroed scratch channel at the prepared maximum frame count; this occurs outside processing.
Link to line 174175 vec![0.; config.maximum_frames()],
Allocate one zeroed scratch channel at the prepared maximum frame count; this occurs outside processing.
Link to line 175176 ];
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 176177 self.config = Some(config);
Mark preparation successful only after the required state and storage have been established.
Link to line 177178 Ok(())
Report successful completion without returning a payload.
Link to line 178179 }
Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.
Link to line 179Validate and honor panic requests
Validate the complete outer block before touching state. Atomically consume a panic request, reset the engine and drain bounded command/native queues. This prevents queued notes from immediately retriggering after All notes off.
180 fn process(&mut self, block: &mut ProcessBlock<'_, '_, '_>) -> ProcessStatus {
Define process. Validate the complete outer block before touching state. Atomically consume a panic request, reset the engine and drain bounded command/native queues. This prevents queued notes from immediately retriggering after All notes off.
Link to line 180181 let config = match self
Bind config to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 181182 .config
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Validate and honor panic requests” explanation above.
Link to line 182183 .ok_or(ProcessError::NotPrepared)
Convert missing preparation into a typed fault instead of processing with unknown limits.
Link to line 183184 .and_then(|c| c.validate_block(block).map(|()| c))
Validate the borrowed block, then retain its prepared configuration only on success.
Link to line 184185 {
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 185186 Ok(c) => c,
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 186187 Err(e) => {
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 187188 block.clear_outputs();
Silence active output samples and discard emitted events. This is the documented failure path, and also clears unselected device channels before routing.
Link to line 188189 return ProcessStatus::Fault(e);
Exit this path with an explicit error/fault; the caller must not treat this branch as successfully applied state.
Link to line 189190 }
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 190191 };
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 191192 if self.shared.panic.swap(false, Ordering::AcqRel) {
Atomically consume a pending All notes off/reset request using acquire/release ordering.
Link to line 192193 self.reset_engine();
Reset whichever prepared inner engine is currently selected.
Link to line 193194 for _ in 0..QUEUE {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate and honor panic requests”.
Link to line 194195 if self.commands.pop().is_err() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate and honor panic requests”.
Link to line 195196 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 196197 }
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 197198 }
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 198199 for source in &mut self.midi {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate and honor panic requests”.
Link to line 199200 let midi = &mut source.receiver;
Bind midi to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 200201 for _ in 0..256 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate and honor panic requests”.
Link to line 201202 if midi.pop().is_none() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Validate and honor panic requests”.
Link to line 202203 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 203204 }
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 204205 }
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 205206 }
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 206207 }
Close the surrounding scope, value or argument list in “Validate and honor panic requests”.
Link to line 207Consume bounded control commands
Handle at most 16 commands. Prepared synth patches and delay controls update the appropriate engine; Demo changes the synthetic source; Midi flushes a zero-frame event. A mismatched engine ignores the irrelevant command variant.
208 for _ in 0..QUEUE {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Consume bounded control commands”.
Link to line 208209 let Ok(command) = self.commands.pop() else {
Bind Ok to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 209210 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 210211 };
Close the surrounding scope, value or argument list in “Consume bounded control commands”.
Link to line 211212 match command {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Consume bounded control commands”.
Link to line 212213 Command::Patch(p) => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 213214 if let Engine::Synth(s) = &mut self.engine {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Consume bounded control commands”.
Link to line 214215 s.set_patch(&p).expect("matching prepared rate");
Require the invariant “matching prepared rate”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 215216 }
Close the surrounding scope, value or argument list in “Consume bounded control commands”.
Link to line 216217 }
Close the surrounding scope, value or argument list in “Consume bounded control commands”.
Link to line 217218 Command::Delay(values) => {
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 218219 if let Engine::Effect(delay) = &mut self.engine {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Consume bounded control commands”.
Link to line 219220 delay
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Consume bounded control commands” explanation above.
Link to line 220221 .set_controls(values)
Call the displayed operation with these arguments as the next step in “Consume bounded control commands”. The chapter describes its role and validation.
Link to line 221222 .expect("validated delay controls");
Require the invariant “validated delay controls”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 222223 }
Close the surrounding scope, value or argument list in “Consume bounded control commands”.
Link to line 223224 }
Close the surrounding scope, value or argument list in “Consume bounded control commands”.
Link to line 224225 Command::Demo(enabled) => self.demo = enabled,
Commit the demo-source switch from the bounded control command.
Link to line 225226 Command::Midi(m) => self.flush_midi(m),
Apply the validated command message at this block boundary through an event-only inner block.
Link to line 226227 }
Close the surrounding scope, value or argument list in “Consume bounded control commands”.
Link to line 227228 }
Close the surrounding scope, value or argument list in “Consume bounded control commands”.
Link to line 228Detect dropped native MIDI packets
Compare each source’s dropped_full statistic with its previous reading. Accumulate the delta with wrapping counters, drain that source’s bounded queue and reset the engine if any loss occurred. A dropped note-off is handled as a state-loss event rather than leaving a held voice.
229 let mut lost = false;
Track whether any native input reports packet loss during this callback.
Link to line 229230 for source in &mut self.midi {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Detect dropped native MIDI packets”.
Link to line 230231 let drops = source.receiver.statistics().dropped_full;
Read the source’s cumulative count of packets dropped because its bounded queue was full.
Link to line 231232 if drops != source.dropped {
Detect newly reported loss relative to the previous callback’s counter.
Link to line 232233 self.dropped = self
Assign the computed value to self.dropped. The right-hand expression supplies the new value for this step.
Link to line 233234 .dropped
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Detect dropped native MIDI packets” explanation above.
Link to line 234235 .wrapping_add(drops.wrapping_sub(source.dropped));
Call the displayed operation with these arguments as the next step in “Detect dropped native MIDI packets”. The chapter describes its role and validation.
Link to line 235236 source.dropped = drops;
Save the latest per-source drop counter for the next comparison.
Link to line 236237 lost = true;
Mark MIDI state as unreliable so the inner engine will be reset after the bounded drain.
Link to line 237238 for _ in 0..256 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Detect dropped native MIDI packets”.
Link to line 238239 if source.receiver.pop().is_none() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Detect dropped native MIDI packets”.
Link to line 239240 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 240241 }
Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.
Link to line 241242 }
Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.
Link to line 242243 }
Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.
Link to line 243244 }
Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.
Link to line 244245 if lost {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Detect dropped native MIDI packets”.
Link to line 245246 self.reset_engine();
Reset whichever prepared inner engine is currently selected.
Link to line 246247 }
Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.
Link to line 247Poll MIDI fairly with a fixed budget
Round-robin the available inputs, retaining midi_cursor across callbacks. Decode accepted short packets and flush them at block start. Stop after 64 attempts or after a whole empty round. Native timestamps are not converted into sample offsets here.
248 let mut empty = 0;
Bind mutable empty to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 248249 for _ in 0..MIDI_BUDGET {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Poll MIDI fairly with a fixed budget”.
Link to line 249250 if self.midi.is_empty() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Poll MIDI fairly with a fixed budget”.
Link to line 250251 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 251252 }
Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.
Link to line 252253 let index = self.midi_cursor % self.midi.len();
Choose the next native MIDI input in the retained round-robin sequence.
Link to line 253254 self.midi_cursor = (index + 1) % self.midi.len();
Advance fairly to the next input, wrapping at the current input count.
Link to line 254255 let packet = self.midi[index].receiver.pop();
Attempt one nonblocking packet read from the selected native input.
Link to line 255256 if let Some(packet) = packet {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Poll MIDI fairly with a fixed budget”.
Link to line 256257 empty = 0;
A received packet breaks the consecutive-empty-input count.
Link to line 257258 if let Ok(message) = MidiMessage::from_bytes(packet.as_bytes()) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Poll MIDI fairly with a fixed budget”.
Link to line 258259 self.flush_midi(message);
Apply the validated short message at the beginning of this processing block.
Link to line 259260 }
Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.
Link to line 260261 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Poll MIDI fairly with a fixed budget” explanation above.
Link to line 261262 empty += 1;
Add the computed value to empty. The right-hand expression supplies the new value for this step.
Link to line 262263 if empty >= self.midi.len() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Poll MIDI fairly with a fixed budget”.
Link to line 263264 break;
End the nearest loop when its bounded work or input condition is complete.
Link to line 264265 }
Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.
Link to line 265266 }
Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.
Link to line 266267 }
Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.
Link to line 267Fill effect input and input meters
Only the effect needs input scratch. Demo mode generates staggered tapered 220/330 Hz tone bursts every 0.9 seconds. Live mode averages selected input pairs into stereo and supplies silence when no selected input contributes. Input meters inspect the resulting dry scratch.
268 let frames = block.audio.frames();
Bind frames to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 268269 let mut meters = [PeakRmsMeter::default(); 4];
Bind mutable meters to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 269270 if matches!(self.engine, Engine::Effect(_)) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Fill effect input and input meters”.
Link to line 270271 for frame in 0..frames {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Fill effect input and input meters”.
Link to line 271272 for channel in 0..2 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Fill effect input and input meters”.
Link to line 272273 let sample = if self.demo {
Bind sample to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 273274 // Staggered, tapered bursts leave space for audible echoes.
Source note: Staggered, tapered bursts leave space for audible echoes.
Link to line 274275 let beat = ((self.frames + frame as u64) as f64 / config.sample_rate()
Bind beat to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 275276 - if channel == 0 { 0. } else { 0.3 })
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Fill effect input and input meters” explanation above.
Link to line 276277 .rem_euclid(0.9);
Call the displayed operation with these arguments as the next step in “Fill effect input and input meters”. The chapter describes its role and validation.
Link to line 277278 let envelope = if beat < 0.18 {
Bind envelope to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 278279 (std::f64::consts::PI * beat / 0.18).sin().powi(2)
Call the displayed operation with these arguments as the next step in “Fill effect input and input meters”. The chapter describes its role and validation.
Link to line 279280 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Fill effect input and input meters” explanation above.
Link to line 280281 0.
Supply this literal numeric entry to the array or argument list being constructed. Its units/addressing follow the containing fixture or configuration.
Link to line 281282 };
Close the surrounding scope, value or argument list in “Fill effect input and input meters”.
Link to line 282283 let sample =
Bind sample to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 283284 (0.2 * envelope * (self.phase[channel] * std::f64::consts::TAU).sin())
Call the displayed operation with these arguments as the next step in “Fill effect input and input meters”. The chapter describes its role and validation.
Link to line 284285 as f32;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Fill effect input and input meters” explanation above.
Link to line 285286 self.phase[channel] = (self.phase[channel]
Assign the computed value to self.phase[channel]. The right-hand expression supplies the new value for this step.
Link to line 286287 + [220., 330.][channel] / config.sample_rate())
Call the displayed operation with these arguments as the next step in “Fill effect input and input meters”. The chapter describes its role and validation.
Link to line 287288 .fract();
Call the displayed operation with these arguments as the next step in “Fill effect input and input meters”. The chapter describes its role and validation.
Link to line 288289 sample
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Fill effect input and input meters” explanation above.
Link to line 289290 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Fill effect input and input meters” explanation above.
Link to line 290291 let mut sum = 0.;
Bind mutable sum to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 291292 let mut count = 0;
Bind mutable count to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 292293 for first in (0..block.audio.input_channels()).step_by(2) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Fill effect input and input meters”.
Link to line 293294 if self.routing.input & (1u64 << first) == 0 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Fill effect input and input meters”.
Link to line 294295 continue;
Skip the rest of this iteration and move to the next item or frame.
Link to line 295296 }
Close the surrounding scope, value or argument list in “Fill effect input and input meters”.
Link to line 296297 let index = (first + channel).min(block.audio.input_channels() - 1);
Bind index to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 297298 sum += block.audio.input(index).expect("selected input")[frame];
Require the invariant “selected input”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 298299 count += 1;
Add the computed value to count. The right-hand expression supplies the new value for this step.
Link to line 299300 }
Close the surrounding scope, value or argument list in “Fill effect input and input meters”.
Link to line 300301 if count == 0 { 0. } else { sum / count as f32 }
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Fill effect input and input meters”.
Link to line 301302 };
Close the surrounding scope, value or argument list in “Fill effect input and input meters”.
Link to line 302303 self.scratch[channel][frame] = sample;
Assign the computed value to self.scratch[channel][frame]. The right-hand expression supplies the new value for this step.
Link to line 303304 meters[channel].push(sample);
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 304305 }
Close the surrounding scope, value or argument list in “Fill effect input and input meters”.
Link to line 305306 }
Close the surrounding scope, value or argument list in “Fill effect input and input meters”.
Link to line 306307 }
Close the surrounding scope, value or argument list in “Fill effect input and input meters”.
Link to line 307Render and distribute selected output pairs
Run the inner engine once. On failure clear outer outputs and return its status. Otherwise clear every output, meter stereo scratch, copy it to selected pairs and average left/right into an odd final mono channel. Unselected channels remain silent.
308 let status = self.process_inner(frames, &[]);
Bind status to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 308309 if status != ProcessStatus::Continue {
Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.
Link to line 309310 block.clear_outputs();
Silence active output samples and discard emitted events. This is the documented failure path, and also clears unselected device channels before routing.
Link to line 310311 return status;
Return this result to the caller; the remaining statements in the function are skipped.
Link to line 311312 }
Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.
Link to line 312313 block.clear_outputs();
Silence active output samples and discard emitted events. This is the documented failure path, and also clears unselected device channels before routing.
Link to line 313314 for frame in 0..frames {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Render and distribute selected output pairs”.
Link to line 314315 for channel in 0..2 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Render and distribute selected output pairs”.
Link to line 315316 meters[2 + channel].push(self.scratch[channel][frame]);
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 316317 }
Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.
Link to line 317318 for first in (0..block.audio.output_channels()).step_by(2) {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Render and distribute selected output pairs”.
Link to line 318319 if self.routing.output & (1u64 << first) == 0 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Render and distribute selected output pairs”.
Link to line 319320 continue;
Skip the rest of this iteration and move to the next item or frame.
Link to line 320321 }
Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.
Link to line 321322 if first + 1 == block.audio.output_channels() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Render and distribute selected output pairs”.
Link to line 322323 block.audio.output_mut(first).expect("selected mono")[frame] =
Require the invariant “selected mono”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 323324 (self.scratch[0][frame] + self.scratch[1][frame]) * 0.5;
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Render and distribute selected output pairs” explanation above.
Link to line 324325 } else {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Render and distribute selected output pairs” explanation above.
Link to line 325326 for channel in 0..2 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Render and distribute selected output pairs”.
Link to line 326327 block
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Render and distribute selected output pairs” explanation above.
Link to line 327328 .audio
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Render and distribute selected output pairs” explanation above.
Link to line 328329 .output_mut(first + channel)
Call the displayed operation with these arguments as the next step in “Render and distribute selected output pairs”. The chapter describes its role and validation.
Link to line 329330 .expect("selected stereo")[frame] = self.scratch[channel][frame];
Require the invariant “selected stereo”. expect panics if it is broken; external inputs must be validated before relying on it.
Link to line 330331 }
Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.
Link to line 331332 }
Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.
Link to line 332333 }
Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.
Link to line 333334 }
Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.
Link to line 334335 self.frames = self.frames.wrapping_add(frames as u64);
Accumulate rendered frame count with explicit wrapping behavior.
Link to line 335336 let mut words = [0; 80];
Bind mutable words to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 336Publish coherent meters and voice telemetry
Split the u64 frame count into two u32 words, store four peak/RMS pairs and a MIDI-drop counter, then pack eight voice records beginning at word 12 with eight-word stride. Pack channel/key/phase into one word and float values as bit patterns. try_publish may fail without blocking.
337 words[0] = self.frames as u32;
Assign the computed value to words[0]. The right-hand expression supplies the new value for this step.
Link to line 337338 words[1] = (self.frames >> 32) as u32;
Store the high half of the 64-bit rendered-frame counter alongside its low u32 word.
Link to line 338339 for (i, meter) in meters.iter().enumerate() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Publish coherent meters and voice telemetry”.
Link to line 339340 let r = meter.reading();
Bind r to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 340341 words[2 + i * 2] = r.peak.to_bits();
Transfer an f32’s exact representation as a u32 word; the UI reconstructs the value with from_bits.
Link to line 341342 words[3 + i * 2] = r.rms.to_bits();
Transfer an f32’s exact representation as a u32 word; the UI reconstructs the value with from_bits.
Link to line 342343 }
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 343344 words[10] = self.dropped as u32;
Assign the computed value to words[10]. The right-hand expression supplies the new value for this step.
Link to line 344345 if let Engine::Synth(s) = &self.engine {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Publish coherent meters and voice telemetry”.
Link to line 345346 let envelopes = s.envelope_levels();
Bind envelopes to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 346347 for (i, envelope) in envelopes.into_iter().enumerate() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Publish coherent meters and voice telemetry”.
Link to line 347348 let voice = s.voices()[i];
Bind voice to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 348349 let Some(note) = voice.note else {
Bind Some to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 349350 continue;
Skip the rest of this iteration and move to the next item or frame.
Link to line 350351 };
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 351352 let start = 12 + i * 8;
Bind start to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 352353 let phase = match voice.phase {
Bind phase to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 353354 ravet_instrument::VoicePhase::Idle => 0,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 354355 ravet_instrument::VoicePhase::Held => 1,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 355356 ravet_instrument::VoicePhase::Sustained => 2,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 356357 ravet_instrument::VoicePhase::Released => 3,
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 357358 };
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 358359 words[start] = u32::from(note.channel) | u32::from(note.key) << 8 | phase << 16;
Assign the computed value to words[start]. The right-hand expression supplies the new value for this step.
Link to line 359360 for (offset, value) in [
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Publish coherent meters and voice telemetry”.
Link to line 360361 voice.velocity,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Publish coherent meters and voice telemetry” explanation above.
Link to line 361362 voice.expression.member_bend,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Publish coherent meters and voice telemetry” explanation above.
Link to line 362363 voice.expression.master_bend,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Publish coherent meters and voice telemetry” explanation above.
Link to line 363364 voice.expression.pressure,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Publish coherent meters and voice telemetry” explanation above.
Link to line 364365 voice.expression.timbre,
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Publish coherent meters and voice telemetry” explanation above.
Link to line 365366 envelope as f32,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 366367 ]
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 367368 .into_iter()
Consume the collection into an owning iterator; its elements are moved into the following transformation.
Link to line 368369 .enumerate()
Call the displayed operation with these arguments as the next step in “Publish coherent meters and voice telemetry”. The chapter describes its role and validation.
Link to line 369370 {
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 370371 words[start + 1 + offset] = value.to_bits();
Transfer an f32’s exact representation as a u32 word; the UI reconstructs the value with from_bits.
Link to line 371372 }
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 372373 }
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 373374 }
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 374375 let _ = self.shared.telemetry.try_publish(words);
Attempt a coherent telemetry update without blocking. Failure may leave the last readable snapshot in place.
Link to line 375376 ProcessStatus::Continue
Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.
Link to line 376377 }
Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.
Link to line 377Reset or deactivate the inner engine
Reset preserves prepared ownership and clears demo phase. Deactivation delegates to the engine and clears the outer configuration. Neither serializes JSON or touches native UI.
378 fn reset(&mut self) {
Define reset. Reset preserves prepared ownership and clears demo phase. Deactivation delegates to the engine and clears the outer configuration. Neither serializes JSON or touches native UI.
Link to line 378379 self.reset_engine();
Reset whichever prepared inner engine is currently selected.
Link to line 379380 self.phase = [0.; 2];
Assign the computed value to self.phase. The right-hand expression supplies the new value for this step.
Link to line 380381 }
Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.
Link to line 381382 fn deactivate(&mut self) {
Define deactivate. Reset preserves prepared ownership and clears demo phase. Deactivation delegates to the engine and clears the outer configuration. Neither serializes JSON or touches native UI.
Link to line 382383 match &mut self.engine {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Reset or deactivate the inner engine”.
Link to line 383384 Engine::Synth(s) => s.deactivate(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 384385 Engine::Effect(g) => g.deactivate(),
Handle the matching pattern on the left using the expression or scope on the right. Other variants are handled by the following arms.
Link to line 385386 };
Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.
Link to line 386387 self.config = None;
Mark the processor inactive before preparation or after deactivation; a failed setup must not retain an apparently valid configuration.
Link to line 387388 }
Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.
Link to line 388389}
Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.
Link to line 389390
Blank line separating the surrounding statements.
Link to line 390Test the adapter without native devices
The internal fixture tests use prepared inputs/output arrays, command rings and synthetic MIDI receivers. They cover repeated demo cycles, switching to live input, selected-pair mixing, silence on unselected channels, zero heap operations, dropped note-off handling and routing rejection.
391#[cfg(test)]
Apply this Rust attribute to the following item. cfg selects which target/feature/test build contains it; derive generates the named trait implementations.
Link to line 391392mod tests {
Bring these module/type names into scope for “Test the adapter without native devices”; the surrounding chapter explains their responsibilities.
Link to line 392393 use super::*;
Bring these module/type names into scope for “Test the adapter without native devices”; the surrounding chapter explains their responsibilities.
Link to line 393394 use ravet_midi_device::{CaptureStatus, PreparedMidiInput};
Bring these module/type names into scope for “Test the adapter without native devices”; the surrounding chapter explains their responsibilities.
Link to line 394395 #[test]
Apply this Rust attribute to the following item. cfg selects which target/feature/test build contains it; derive generates the named trait implementations.
Link to line 395396 fn demo_repeats_for_multiple_cycles_and_can_switch_to_live_input() {
Define demo_repeats_for_multiple_cycles_and_can_switch_to_live_input. The internal fixture tests use prepared inputs/output arrays, command rings and synthetic MIDI receivers. They cover repeated demo cycles, switching to live input, selected-pair mixing, silence on unselected channels, zero heap operations, dropped note-off handling and routing rejection.
Link to line 396397 let (mut commands, consumer) = rtrb::RingBuffer::new(QUEUE);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 397398 let mut audio = Audio::new(
Bind mutable audio to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 398399 false,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 399400 true,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 400401 consumer,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 401402 Vec::new(),
Define or initialize Vec with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 402403 Shared::new(),
Define or initialize Shared with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 403404 Routing::default(),
Define or initialize Routing with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 404405 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 405406 audio
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 406407 .prepare(ProcessConfig::new(48000., 64, 0, AudioLayout::new(4, 6).unwrap()).unwrap())
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 407408 .unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 408409 commands
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 409410 .push(Command::Delay([375., 0.45, 0.35, 1., 0.]))
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 410411 .ok()
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 411412 .unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 412413 let input = [[0.; 64]; 4];
Bind input to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 413414 let mut output = [[0.; 64]; 6];
Bind mutable output to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 414415 let mut energy = [[0f64; 2]; 3];
Bind mutable energy to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 415416 for block in 0..2025 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Test the adapter without native devices”.
Link to line 416417 assert_eq!(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 417418 render(&mut audio, &input, &mut output),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 418419 ProcessStatus::Continue
Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.
Link to line 419420 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 420421 let cycle = block / 675; // exactly 0.9 seconds per cycle at 48 kHz
Bind cycle to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 421422 for (channel, samples) in output[..2].iter().enumerate() {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Test the adapter without native devices”.
Link to line 422423 energy[cycle][channel] +=
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 423424 samples.iter().map(|s| f64::from(*s).powi(2)).sum::<f64>();
Borrow collection entries for iteration without moving or copying the whole collection.
Link to line 424425 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 425426 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 426427 for cycle in energy {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Test the adapter without native devices”.
Link to line 427428 for channel in cycle {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Test the adapter without native devices”.
Link to line 428429 assert!(channel > 10.);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 429430 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 430431 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 431432 commands.push(Command::Demo(false)).ok().unwrap();
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 432433 render(&mut audio, &input, &mut output);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 433434 assert!(output.iter().flatten().all(|s| *s == 0.));
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 434435 let input = [[0.1; 64], [-0.2; 64], [0.; 64], [0.; 64]];
Bind input to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 435436 render(&mut audio, &input, &mut output);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 436437 assert_eq!(output[0], input[0]);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 437438 assert_eq!(output[1], input[1]);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 438439 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 439440 fn render(
Define render. The internal fixture tests use prepared inputs/output arrays, command rings and synthetic MIDI receivers. They cover repeated demo cycles, switching to live input, selected-pair mixing, silence on unselected channels, zero heap operations, dropped note-off handling and routing rejection.
Link to line 440441 audio: &mut Audio,
Define or initialize audio with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 441442 input: &[[f32; 64]; 4],
Define or initialize input with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 442443 output: &mut [[f32; 64]; 6],
Define or initialize output with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 443444 ) -> ProcessStatus {
Complete the function’s parameter list and specify the return type. A Result preserves the explicit success/error distinction.
Link to line 444445 let inputs = input.each_ref().map(|c| &c[..]);
Bind inputs to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 445446 let mut outputs = output.each_mut().map(|c| &mut c[..]);
Bind mutable outputs to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 446447 let buffer = AudioBuffer::separate(&inputs, &mut outputs, 64).unwrap();
Borrow distinct input/output slices. An instrument supplies an empty input slice; output storage already belongs to the caller.
Link to line 447448 audio.process(&mut ProcessBlock::new(buffer, &[], Transport::default()))
Combine borrowed audio, the active input-event slice and explicit transport into one processing view.
Link to line 448449 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 449450 #[test]
Apply this Rust attribute to the following item. cfg selects which target/feature/test build contains it; derive generates the named trait implementations.
Link to line 450451 fn selected_input_pairs_mix_and_unselected_outputs_remain_silent_without_heap_actions() {
Define selected_input_pairs_mix_and_unselected_outputs_remain_silent_without_heap_actions. The internal fixture tests use prepared inputs/output arrays, command rings and synthetic MIDI receivers. They cover repeated demo cycles, switching to live input, selected-pair mixing, silence on unselected channels, zero heap operations, dropped note-off handling and routing rejection.
Link to line 451452 let (mut commands, consumer) = rtrb::RingBuffer::new(QUEUE);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 452453 let shared = Shared::new();
Bind shared to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 453454 let mut audio = Audio::new(
Bind mutable audio to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 454455 false,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 455456 false,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 456457 consumer,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 457458 Vec::new(),
Define or initialize Vec with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 458459 shared,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 459460 Routing {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 460461 input: 15,
Define or initialize input with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 461462 output: 60,
Define or initialize output with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 462463 },
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 463464 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 464465 audio
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 465466 .prepare(ProcessConfig::new(48000., 64, 0, AudioLayout::new(4, 6).unwrap()).unwrap())
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 466467 .unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 467468 let input = [[1.; 64], [2.; 64], [3.; 64], [4.; 64]];
Bind input to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 468469 let mut output = [[99.; 64]; 6];
Bind mutable output to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 469470 commands
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 470471 .push(Command::Delay([375., 0.45, 0.35, 1., 0.]))
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 471472 .ok()
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 472473 .unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 473474 let measured = allocation_counter::measure(|| {
Measure heap activity only in the enclosed processing/changes/reset region; preparation and assertions are outside it.
Link to line 474475 for _ in 0..1000 {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Test the adapter without native devices”.
Link to line 475476 assert_eq!(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 476477 render(&mut audio, &input, &mut output),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 477478 ProcessStatus::Continue
Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.
Link to line 478479 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 479480 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 480481 audio.reset();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 481482 });
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 482483 assert_eq!(measured.count_total, 0);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 483484 assert_eq!(measured.count_current, 0);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 484485 assert_eq!(output[0], [0.; 64]);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 485486 assert_eq!(output[1], [0.; 64]);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 486487 for channel in [2, 4] {
Evaluate this condition or visit this range in source order. The statements in the following scope implement “Test the adapter without native devices”.
Link to line 487488 assert_eq!(output[channel], [2.; 64]);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 488489 assert_eq!(output[channel + 1], [3.; 64]);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 489490 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 490491 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 491492 #[test]
Apply this Rust attribute to the following item. cfg selects which target/feature/test build contains it; derive generates the named trait implementations.
Link to line 492493 fn multiple_midi_sources_and_dropped_note_off_clear_voices() {
Define multiple_midi_sources_and_dropped_note_off_clear_voices. The internal fixture tests use prepared inputs/output arrays, command rings and synthetic MIDI receivers. They cover repeated demo cycles, switching to live input, selected-pair mixing, silence on unselected channels, zero heap operations, dropped note-off handling and routing rejection.
Link to line 493494 let (mut first, receiver_a) = PreparedMidiInput::new(2).unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 494495 let (mut second, receiver_b) = PreparedMidiInput::new(2).unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 495496 let (mut commands, consumer) = rtrb::RingBuffer::new(QUEUE);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 496497 let shared = Shared::new();
Bind shared to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 497498 let mut audio = Audio::new(
Bind mutable audio to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 498499 true,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 499500 false,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 500501 consumer,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 501502 vec![receiver_a, receiver_b],
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 502503 shared.clone(),
Clone this value. Fixed arrays copy their entries; owned strings/vectors may allocate and remain outside the callback.
Link to line 503504 Routing::default(),
Define or initialize Routing with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 504505 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 505506 audio
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 506507 .prepare(ProcessConfig::new(48000., 64, 0, AudioLayout::new(4, 6).unwrap()).unwrap())
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 507508 .unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 508509 assert_eq!(first.capture(0, &[0x90, 60, 100]), CaptureStatus::Accepted);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 509510 assert_eq!(second.capture(0, &[0x91, 64, 100]), CaptureStatus::Accepted);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 510511 let mut output = [[0.; 64]; 6];
Bind mutable output to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 511512 let input = [[0.; 64]; 4];
Bind input to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 512513 assert_eq!(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 513514 render(&mut audio, &input, &mut output),
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 514515 ProcessStatus::Continue
Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.
Link to line 515516 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 516517 let Engine::Synth(synth) = &audio.engine else {
Bind Engine to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 517518 panic!("synth")
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 518519 };
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 519520 assert_eq!(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 520521 synth.voices().iter().filter(|v| v.note.is_some()).count(),
Borrow collection entries for iteration without moving or copying the whole collection.
Link to line 521522 2
Supply this literal numeric entry to the array or argument list being constructed. Its units/addressing follow the containing fixture or configuration.
Link to line 522523 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 523524 first.capture(1, &[0xb0, 1, 0]);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 524525 first.capture(2, &[0xb0, 1, 0]);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 525526 assert_eq!(first.capture(3, &[0x80, 60, 0]), CaptureStatus::Full);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 526527 render(&mut audio, &input, &mut output);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 527528 assert_eq!(audio.dropped, 1);
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 528529 assert!(output.iter().flatten().all(|s| *s == 0.));
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 529530 commands
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 530531 .push(Command::Midi(
Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.
Link to line 531532 MidiMessage::from_bytes(&[0x90, 60, 100]).unwrap(),
Define or initialize MidiMessage with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 532533 ))
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 533534 .ok()
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 534535 .unwrap();
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 535536 shared.panic.store(true, Ordering::Release);
Publish the new atomic flag/value using the specified memory ordering.
Link to line 536537 render(&mut audio, &input, &mut output);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 537538 assert!(output.iter().flatten().all(|s| *s == 0.));
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 538539 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 539540 #[test]
Apply this Rust attribute to the following item. cfg selects which target/feature/test build contains it; derive generates the named trait implementations.
Link to line 540541 fn routing_is_checked_before_processing() {
Define routing_is_checked_before_processing. The internal fixture tests use prepared inputs/output arrays, command rings and synthetic MIDI receivers. They cover repeated demo cycles, switching to live input, selected-pair mixing, silence on unselected channels, zero heap operations, dropped note-off handling and routing rejection.
Link to line 541542 let (_, consumer) = rtrb::RingBuffer::new(QUEUE);
Call the displayed operation with these arguments as the next step in “Test the adapter without native devices”. The chapter describes its role and validation.
Link to line 542543 let mut audio = Audio::new(
Bind mutable audio to the expression on this and any following continuation lines. The chapter above explains how this intermediate value is used.
Link to line 543544 true,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 544545 false,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 545546 consumer,
Supply these names as the remaining imports, arguments or fields of the surrounding declaration.
Link to line 546547 Vec::new(),
Define or initialize Vec with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 547548 Shared::new(),
Define or initialize Shared with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 548549 Routing {
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 549550 input: 3,
Select input channels zero and one: bitmask 3 is binary 11.
Link to line 550551 output: 1 << 9,
Define or initialize output with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 551552 },
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 552553 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 553554 assert_eq!(
Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.
Link to line 554555 audio.prepare(
Continue the surrounding value or expression with this exact operand. Read it together with the preceding statement and the “Test the adapter without native devices” explanation above.
Link to line 555556 ProcessConfig::new(48000., 64, 0, AudioLayout::STEREO_INSTRUMENT).unwrap()
Define or initialize ProcessConfig with the displayed type/value. Its ownership and use are described in “Test the adapter without native devices”.
Link to line 556557 ),
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 557558 Err(PrepareError::UnsupportedLayout)
Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.
Link to line 558559 );
Close the current expression or scope; no additional processing operation occurs on this line.
Link to line 559560 }
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 560561}
Close the surrounding scope, value or argument list in “Test the adapter without native devices”.
Link to line 561