AUDIO
Source snapshot · 12 October 2026

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 --locked
Chapters
  1. Define routing and bounded shared state lines 1–44
  2. Commands and engine ownership lines 45–70
  3. Construct the audio owner before callbacks lines 71–104
  4. Adapt the stereo scratch into a portable block lines 105–118
  5. Apply MIDI without advancing samples lines 119–134
  6. Prepare routing and scratch storage lines 135–179
  7. Validate and honor panic requests lines 180–207
  8. Consume bounded control commands lines 208–228
  9. Detect dropped native MIDI packets lines 229–247
  10. Poll MIDI fairly with a fixed budget lines 248–267
  11. Fill effect input and input meters lines 268–307
  12. Render and distribute selected output pairs lines 308–336
  13. Publish coherent meters and voice telemetry lines 337–377
  14. Reset or deactivate the inner engine lines 378–390
  15. 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 1
2use 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 2
3use 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 3
4use 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 4
5 AudioBuffer, AudioLayout, Event, EventData, MidiMessage, PrepareError, ProcessBlock,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 5
6 ProcessConfig, ProcessError, ProcessStatus, Processor, SnapshotMailbox, Transport,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 6
7};

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 7
8use 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 8
9use 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 9
10 Arc,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 10
11 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 11
12};

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 12
13

Blank line separating the surrounding statements.

Link to line 13
14pub 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 14
15pub 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 15
16const 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 16
17pub 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 17
18 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 18
19 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 19
20}

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 20
21impl 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 21
22 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 22
23 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 23
24 input: 3,

Select input channels zero and one: bitmask 3 is binary 11.

Link to line 24
25 output: 3,

Select output channels zero and one using the same two-bit default mask.

Link to line 25
26 }

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 26
27 }

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 27
28}

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 28
29struct 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 29
30 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 30
31 dropped: u64,

Cumulative MIDI packet-loss count retained for the UI.

Link to line 31
32}

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 32
33pub 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 33
34 pub telemetry: SnapshotMailbox<80>,

An 80-word coherent snapshot mailbox; it carries latest state rather than an ordered event stream.

Link to line 34
35 pub panic: AtomicBool,

Atomic reset request set by UI cancellation or queue overflow.

Link to line 35
36}

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 36
37impl 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 37
38 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 38
39 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 39
40 telemetry: SnapshotMailbox::new([0; 80]),

Initialize the coherent fixed-size telemetry mailbox with an all-zero record.

Link to line 40
41 panic: AtomicBool::new(false),

Initialize the shared panic/reset request flag as clear.

Link to line 41
42 })

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 42
43 }

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 43
44}

Close the surrounding scope, value or argument list in “Define routing and bounded shared state”.

Link to line 44

Commands 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 45
46#[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 46
47pub 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 47
48 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 48
49 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 49
50 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 50
51 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 51
52}

Close the surrounding scope, value or argument list in “Commands and engine ownership”.

Link to line 52
53enum 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 53
54 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 54
55 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 55
56}

Close the surrounding scope, value or argument list in “Commands and engine ownership”.

Link to line 56
57pub 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 57
58 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 58
59 commands: rtrb::Consumer<Command>,

The audio-side consumer of the bounded UI command ring.

Link to line 59
60 midi: Vec<MidiSource>,

Prepared native input receivers and their last observed loss counts.

Link to line 60
61 routing: Routing,

Channel-selection bitmasks validated during preparation.

Link to line 61
62 midi_cursor: usize,

Retained round-robin cursor for fair native MIDI polling.

Link to line 62
63 shared: Arc<Shared>,

Reference-counted mailbox and reset flag shared with the main-thread owner.

Link to line 63
64 scratch: [Vec<f32>; 2],

Prepared planar stereo scratch; callbacks borrow only the active prefix.

Link to line 64
65 config: Option<ProcessConfig>,

Processing limits. An optional configuration in processor-owned state is None until preparation succeeds.

Link to line 65
66 demo: bool,

Whether the effect input uses the synthetic demonstration source.

Link to line 66
67 phase: [f64; 2],

Retained oscillator phases for the demo input.

Link to line 67
68 frames: u64,

Cumulative rendered frame count for telemetry.

Link to line 68
69 dropped: u64,

Cumulative MIDI packet-loss count retained for the UI.

Link to line 69
70}

Close the surrounding scope, value or argument list in “Commands and engine ownership”.

Link to line 70

Construct 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 71
72 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 72
73 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 73
74 demo: bool,

Whether the effect input uses the synthetic demonstration source.

Link to line 74
75 commands: rtrb::Consumer<Command>,

The audio-side consumer of the bounded UI command ring.

Link to line 75
76 midi: Vec<ravet_midi_device::MidiReceiver>,

Prepared native input receivers and their last observed loss counts.

Link to line 76
77 shared: Arc<Shared>,

Reference-counted mailbox and reset flag shared with the main-thread owner.

Link to line 77
78 routing: Routing,

Channel-selection bitmasks validated during preparation.

Link to line 78
79 ) -> Self {

Complete the function’s parameter list and specify the return type. A Result preserves the explicit success/error distinction.

Link to line 79
80 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 80
81 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 81
82 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 82
83 } 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 83
84 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 84
85 },

Close the surrounding scope, value or argument list in “Construct the audio owner before callbacks”.

Link to line 85
86 commands,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 86
87 midi: midi

Prepared native input receivers and their last observed loss counts.

Link to line 87
88 .into_iter()

Consume the collection into an owning iterator; its elements are moved into the following transformation.

Link to line 88
89 .map(|receiver| MidiSource {

Transform each iterator entry, or the successful value of an Option/Result, using the supplied closure.

Link to line 89
90 receiver,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 90
91 dropped: 0,

Cumulative MIDI packet-loss count retained for the UI.

Link to line 91
92 })

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 92
93 .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 93
94 routing,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 94
95 midi_cursor: 0,

Retained round-robin cursor for fair native MIDI polling.

Link to line 95
96 shared,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 96
97 scratch: [Vec::new(), Vec::new()],

Start with empty stereo scratch; prepare allocates the required capacities later.

Link to line 97
98 config: None,

Processing limits. An optional configuration in processor-owned state is None until preparation succeeds.

Link to line 98
99 demo,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 99
100 phase: [0.; 2],

Retained oscillator phases for the demo input.

Link to line 100
101 frames: 0,

Cumulative rendered frame count for telemetry.

Link to line 101
102 dropped: 0,

Cumulative MIDI packet-loss count retained for the UI.

Link to line 102
103 }

Close the surrounding scope, value or argument list in “Construct the audio owner before callbacks”.

Link to line 103
104 }

Close the surrounding scope, value or argument list in “Construct the audio owner before callbacks”.

Link to line 104

Adapt 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 105
106 let [left, right] = &mut self.scratch;

Borrow the two owned scratch vectors separately for channel views.

Link to line 106
107 let mut views = [&mut left[..frames], &mut right[..frames]];

Restrict both mutable channel views to this callback’s active frame prefix.

Link to line 107
108 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 108
109 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 109
110 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 110
111 }

Close the surrounding scope, value or argument list in “Adapt the stereo scratch into a portable block”.

Link to line 111
112 .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 112
113 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 113
114 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 114
115 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 115
116 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 116
117 }

Close the surrounding scope, value or argument list in “Adapt the stereo scratch into a portable block”.

Link to line 117
118 }

Close the surrounding scope, value or argument list in “Adapt the stereo scratch into a portable block”.

Link to line 118

Apply 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 119
120 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 120
121 0,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 121
122 &[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 122
123 frame_offset: 0,

The event’s timing coordinate, interpreted relative to its current clip/block context.

Link to line 123
124 data: EventData::Midi(message),

Typed event payload; timing is kept separately in frame_offset.

Link to line 124
125 }],

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 125
126 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 126
127 }

Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.

Link to line 127
128 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 128
129 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 129
130 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 130
131 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 131
132 }

Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.

Link to line 132
133 }

Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.

Link to line 133
134}

Close the surrounding scope, value or argument list in “Apply MIDI without advancing samples”.

Link to line 134

Prepare 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 135
136 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 136
137 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 137
138 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 138
139 || !config.auxiliary_buses().is_empty()

Accept this alternative condition in the surrounding check; evaluation stops once the combined condition is true.

Link to line 139
140 || config.maximum_output_events() != 0

Accept this alternative condition in the surrounding check; evaluation stops once the combined condition is true.

Link to line 140
141 {

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 141
142 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 142
143 }

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 143
144 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 144
145 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 145
146 u64::MAX

Allow all 64 channel bits without shifting a u64 by 64, which would be invalid.

Link to line 146
147 } 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 147
148 (1u64 << channels) - 1

Construct a low-channel mask for a channel count below 64.

Link to line 148
149 };

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 149
150 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 150
151 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 151
152 }

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 152
153 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 153
154 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 154
155 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 155
156 u64::MAX

Allow all 64 channel bits without shifting a u64 by 64, which would be invalid.

Link to line 156
157 } 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 157
158 (1u64 << channels) - 1

Construct a low-channel mask for a channel count below 64.

Link to line 158
159 };

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 159
160 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 160
161 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 161
162 }

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 162
163 }

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 163
164 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 164
165 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 165
166 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 166
167 };

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 167
168 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 168
169 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 169
170 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 170
171 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 171
172 };

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 172
173 self.scratch = [

Assign the computed value to self.scratch. The right-hand expression supplies the new value for this step.

Link to line 173
174 vec![0.; config.maximum_frames()],

Allocate one zeroed scratch channel at the prepared maximum frame count; this occurs outside processing.

Link to line 174
175 vec![0.; config.maximum_frames()],

Allocate one zeroed scratch channel at the prepared maximum frame count; this occurs outside processing.

Link to line 175
176 ];

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 176
177 self.config = Some(config);

Mark preparation successful only after the required state and storage have been established.

Link to line 177
178 Ok(())

Report successful completion without returning a payload.

Link to line 178
179 }

Close the surrounding scope, value or argument list in “Prepare routing and scratch storage”.

Link to line 179

Validate 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 180
181 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 181
182 .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 182
183 .ok_or(ProcessError::NotPrepared)

Convert missing preparation into a typed fault instead of processing with unknown limits.

Link to line 183
184 .and_then(|c| c.validate_block(block).map(|()| c))

Validate the borrowed block, then retain its prepared configuration only on success.

Link to line 184
185 {

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 185
186 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 186
187 Err(e) => {

Construct the success/error variant selected by the surrounding match or function return. The enclosed value becomes its payload.

Link to line 187
188 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 188
189 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 189
190 }

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 190
191 };

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 191
192 if self.shared.panic.swap(false, Ordering::AcqRel) {

Atomically consume a pending All notes off/reset request using acquire/release ordering.

Link to line 192
193 self.reset_engine();

Reset whichever prepared inner engine is currently selected.

Link to line 193
194 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 194
195 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 195
196 break;

End the nearest loop when its bounded work or input condition is complete.

Link to line 196
197 }

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 197
198 }

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 198
199 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 199
200 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 200
201 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 201
202 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 202
203 break;

End the nearest loop when its bounded work or input condition is complete.

Link to line 203
204 }

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 204
205 }

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 205
206 }

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 206
207 }

Close the surrounding scope, value or argument list in “Validate and honor panic requests”.

Link to line 207

Consume 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 208
209 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 209
210 break;

End the nearest loop when its bounded work or input condition is complete.

Link to line 210
211 };

Close the surrounding scope, value or argument list in “Consume bounded control commands”.

Link to line 211
212 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 212
213 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 213
214 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 214
215 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 215
216 }

Close the surrounding scope, value or argument list in “Consume bounded control commands”.

Link to line 216
217 }

Close the surrounding scope, value or argument list in “Consume bounded control commands”.

Link to line 217
218 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 218
219 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 219
220 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 220
221 .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 221
222 .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 222
223 }

Close the surrounding scope, value or argument list in “Consume bounded control commands”.

Link to line 223
224 }

Close the surrounding scope, value or argument list in “Consume bounded control commands”.

Link to line 224
225 Command::Demo(enabled) => self.demo = enabled,

Commit the demo-source switch from the bounded control command.

Link to line 225
226 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 226
227 }

Close the surrounding scope, value or argument list in “Consume bounded control commands”.

Link to line 227
228 }

Close the surrounding scope, value or argument list in “Consume bounded control commands”.

Link to line 228

Detect 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 229
230 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 230
231 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 231
232 if drops != source.dropped {

Detect newly reported loss relative to the previous callback’s counter.

Link to line 232
233 self.dropped = self

Assign the computed value to self.dropped. The right-hand expression supplies the new value for this step.

Link to line 233
234 .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 234
235 .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 235
236 source.dropped = drops;

Save the latest per-source drop counter for the next comparison.

Link to line 236
237 lost = true;

Mark MIDI state as unreliable so the inner engine will be reset after the bounded drain.

Link to line 237
238 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 238
239 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 239
240 break;

End the nearest loop when its bounded work or input condition is complete.

Link to line 240
241 }

Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.

Link to line 241
242 }

Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.

Link to line 242
243 }

Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.

Link to line 243
244 }

Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.

Link to line 244
245 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 245
246 self.reset_engine();

Reset whichever prepared inner engine is currently selected.

Link to line 246
247 }

Close the surrounding scope, value or argument list in “Detect dropped native MIDI packets”.

Link to line 247

Poll 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 248
249 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 249
250 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 250
251 break;

End the nearest loop when its bounded work or input condition is complete.

Link to line 251
252 }

Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.

Link to line 252
253 let index = self.midi_cursor % self.midi.len();

Choose the next native MIDI input in the retained round-robin sequence.

Link to line 253
254 self.midi_cursor = (index + 1) % self.midi.len();

Advance fairly to the next input, wrapping at the current input count.

Link to line 254
255 let packet = self.midi[index].receiver.pop();

Attempt one nonblocking packet read from the selected native input.

Link to line 255
256 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 256
257 empty = 0;

A received packet breaks the consecutive-empty-input count.

Link to line 257
258 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 258
259 self.flush_midi(message);

Apply the validated short message at the beginning of this processing block.

Link to line 259
260 }

Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.

Link to line 260
261 } 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 261
262 empty += 1;

Add the computed value to empty. The right-hand expression supplies the new value for this step.

Link to line 262
263 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 263
264 break;

End the nearest loop when its bounded work or input condition is complete.

Link to line 264
265 }

Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.

Link to line 265
266 }

Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.

Link to line 266
267 }

Close the surrounding scope, value or argument list in “Poll MIDI fairly with a fixed budget”.

Link to line 267

Fill 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 268
269 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 269
270 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 270
271 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 271
272 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 272
273 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 273
274 // Staggered, tapered bursts leave space for audible echoes.

Source note: Staggered, tapered bursts leave space for audible echoes.

Link to line 274
275 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 275
276 - 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 276
277 .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 277
278 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 278
279 (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 279
280 } 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 280
281 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 281
282 };

Close the surrounding scope, value or argument list in “Fill effect input and input meters”.

Link to line 282
283 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 283
284 (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 284
285 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 285
286 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 286
287 + [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 287
288 .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 288
289 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 289
290 } 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 290
291 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 291
292 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 292
293 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 293
294 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 294
295 continue;

Skip the rest of this iteration and move to the next item or frame.

Link to line 295
296 }

Close the surrounding scope, value or argument list in “Fill effect input and input meters”.

Link to line 296
297 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 297
298 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 298
299 count += 1;

Add the computed value to count. The right-hand expression supplies the new value for this step.

Link to line 299
300 }

Close the surrounding scope, value or argument list in “Fill effect input and input meters”.

Link to line 300
301 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 301
302 };

Close the surrounding scope, value or argument list in “Fill effect input and input meters”.

Link to line 302
303 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 303
304 meters[channel].push(sample);

Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.

Link to line 304
305 }

Close the surrounding scope, value or argument list in “Fill effect input and input meters”.

Link to line 305
306 }

Close the surrounding scope, value or argument list in “Fill effect input and input meters”.

Link to line 306
307 }

Close the surrounding scope, value or argument list in “Fill effect input and input meters”.

Link to line 307

Render 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 308
309 if status != ProcessStatus::Continue {

Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.

Link to line 309
310 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 310
311 return status;

Return this result to the caller; the remaining statements in the function are skipped.

Link to line 311
312 }

Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.

Link to line 312
313 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 313
314 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 314
315 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 315
316 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 316
317 }

Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.

Link to line 317
318 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 318
319 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 319
320 continue;

Skip the rest of this iteration and move to the next item or frame.

Link to line 320
321 }

Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.

Link to line 321
322 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 322
323 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 323
324 (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 324
325 } 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 325
326 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 326
327 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 327
328 .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 328
329 .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 329
330 .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 330
331 }

Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.

Link to line 331
332 }

Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.

Link to line 332
333 }

Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.

Link to line 333
334 }

Close the surrounding scope, value or argument list in “Render and distribute selected output pairs”.

Link to line 334
335 self.frames = self.frames.wrapping_add(frames as u64);

Accumulate rendered frame count with explicit wrapping behavior.

Link to line 335
336 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 336

Publish 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 337
338 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 338
339 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 339
340 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 340
341 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 341
342 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 342
343 }

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 343
344 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 344
345 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 345
346 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 346
347 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 347
348 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 348
349 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 349
350 continue;

Skip the rest of this iteration and move to the next item or frame.

Link to line 350
351 };

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 351
352 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 352
353 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 353
354 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 354
355 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 355
356 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 356
357 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 357
358 };

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 358
359 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 359
360 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 360
361 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 361
362 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 362
363 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 363
364 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 364
365 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 365
366 envelope as f32,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 366
367 ]

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 367
368 .into_iter()

Consume the collection into an owning iterator; its elements are moved into the following transformation.

Link to line 368
369 .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 369
370 {

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 370
371 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 371
372 }

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 372
373 }

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 373
374 }

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 374
375 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 375
376 ProcessStatus::Continue

Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.

Link to line 376
377 }

Close the surrounding scope, value or argument list in “Publish coherent meters and voice telemetry”.

Link to line 377

Reset 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 378
379 self.reset_engine();

Reset whichever prepared inner engine is currently selected.

Link to line 379
380 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 380
381 }

Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.

Link to line 381
382 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 382
383 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 383
384 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 384
385 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 385
386 };

Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.

Link to line 386
387 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 387
388 }

Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.

Link to line 388
389}

Close the surrounding scope, value or argument list in “Reset or deactivate the inner engine”.

Link to line 389
390

Blank line separating the surrounding statements.

Link to line 390

Test 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 391
392mod tests {

Bring these module/type names into scope for “Test the adapter without native devices”; the surrounding chapter explains their responsibilities.

Link to line 392
393 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 393
394 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 394
395 #[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 395
396 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 396
397 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 397
398 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 398
399 false,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 399
400 true,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 400
401 consumer,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 401
402 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 402
403 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 403
404 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 404
405 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 405
406 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 406
407 .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 407
408 .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 408
409 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 409
410 .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 410
411 .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 411
412 .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 412
413 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 413
414 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 414
415 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 415
416 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 416
417 assert_eq!(

Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.

Link to line 417
418 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 418
419 ProcessStatus::Continue

Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.

Link to line 419
420 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 420
421 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 421
422 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 422
423 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 423
424 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 424
425 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 425
426 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 426
427 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 427
428 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 428
429 assert!(channel > 10.);

Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.

Link to line 429
430 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 430
431 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 431
432 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 432
433 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 433
434 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 434
435 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 435
436 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 436
437 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 437
438 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 438
439 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 439
440 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 440
441 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 441
442 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 442
443 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 443
444 ) -> ProcessStatus {

Complete the function’s parameter list and specify the return type. A Result preserves the explicit success/error distinction.

Link to line 444
445 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 445
446 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 446
447 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 447
448 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 448
449 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 449
450 #[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 450
451 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 451
452 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 452
453 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 453
454 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 454
455 false,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 455
456 false,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 456
457 consumer,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 457
458 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 458
459 shared,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 459
460 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 460
461 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 461
462 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 462
463 },

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 463
464 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 464
465 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 465
466 .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 466
467 .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 467
468 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 468
469 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 469
470 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 470
471 .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 471
472 .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 472
473 .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 473
474 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 474
475 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 475
476 assert_eq!(

Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.

Link to line 476
477 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 477
478 ProcessStatus::Continue

Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.

Link to line 478
479 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 479
480 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 480
481 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 481
482 });

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 482
483 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 483
484 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 484
485 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 485
486 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 486
487 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 487
488 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 488
489 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 489
490 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 490
491 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 491
492 #[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 492
493 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 493
494 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 494
495 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 495
496 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 496
497 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 497
498 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 498
499 true,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 499
500 false,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 500
501 consumer,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 501
502 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 502
503 shared.clone(),

Clone this value. Fixed arrays copy their entries; owned strings/vectors may allocate and remain outside the callback.

Link to line 503
504 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 504
505 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 505
506 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 506
507 .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 507
508 .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 508
509 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 509
510 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 510
511 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 511
512 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 512
513 assert_eq!(

Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.

Link to line 513
514 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 514
515 ProcessStatus::Continue

Represent a successfully processed block. The offline renderer treats any different status as a failed rendering session.

Link to line 515
516 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 516
517 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 517
518 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 518
519 };

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 519
520 assert_eq!(

Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.

Link to line 520
521 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 521
522 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 522
523 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 523
524 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 524
525 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 525
526 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 526
527 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 527
528 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 528
529 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 529
530 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 530
531 .push(Command::Midi(

Append the supplied item to this owned collection. UI/fixture collections grow outside the audio callback.

Link to line 531
532 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 532
533 ))

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 533
534 .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 534
535 .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 535
536 shared.panic.store(true, Ordering::Release);

Publish the new atomic flag/value using the specified memory ordering.

Link to line 536
537 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 537
538 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 538
539 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 539
540 #[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 540
541 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 541
542 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 542
543 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 543
544 true,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 544
545 false,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 545
546 consumer,

Supply these names as the remaining imports, arguments or fields of the surrounding declaration.

Link to line 546
547 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 547
548 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 548
549 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 549
550 input: 3,

Select input channels zero and one: bitmask 3 is binary 11.

Link to line 550
551 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 551
552 },

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 552
553 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 553
554 assert_eq!(

Verify the fixture’s expected result. A mismatch fails the test rather than becoming a successful support claim.

Link to line 554
555 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 555
556 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 556
557 ),

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 557
558 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 558
559 );

Close the current expression or scope; no additional processing operation occurs on this line.

Link to line 559
560 }

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 560
561}

Close the surrounding scope, value or argument list in “Test the adapter without native devices”.

Link to line 561

Source SHA-256: 49f881a2e16f6799ad7619f8097ea098121d24ab7d91b58a84054085af6db961

API: ravet_foundation · ravet_instrument · ravet_midi_device · ravet_signal

All tutorial walkthroughs