sim_lib_stream_bridge/model.rs
1use sim_citizen_derive::Citizen;
2use sim_kernel::{Diagnostic, Symbol};
3use sim_lib_midi_core::DEFAULT_US_PER_QUARTER;
4use sim_lib_stream_core::StreamValue;
5
6/// Result of a bridge conversion: the produced stream plus any diagnostics.
7pub struct BridgeOutput {
8 /// Converted stream carrying the resulting MIDI or PCM packets.
9 pub stream: StreamValue,
10 /// Diagnostics emitted while converting (for example, unrepresentable pitches).
11 pub diagnostics: Vec<Diagnostic>,
12}
13
14/// Options controlling MIDI-to-PCM rendering through the sound libraries.
15///
16/// # Examples
17///
18/// ```
19/// use sim_lib_stream_bridge::StreamBridgeRenderOptions;
20///
21/// let opts = StreamBridgeRenderOptions::default();
22/// assert_eq!(opts.channels, 2);
23/// assert_eq!(opts.sample_rate, 48_000);
24/// ```
25#[derive(Clone, Debug, PartialEq, Citizen)]
26#[citizen(symbol = "stream-bridge/RenderOptions", version = 1)]
27pub struct StreamBridgeRenderOptions {
28 /// Output sample rate in hertz.
29 pub sample_rate: u32,
30 /// Number of interleaved output channels.
31 pub channels: u8,
32 /// Number of frames carried by each produced PCM packet.
33 pub chunk_frames: usize,
34}
35
36impl Default for StreamBridgeRenderOptions {
37 fn default() -> Self {
38 Self {
39 sample_rate: 48_000,
40 channels: 2,
41 chunk_frames: 512,
42 }
43 }
44}
45
46/// Options controlling PCM-to-MIDI lifting through the audio-lift libraries.
47#[derive(Clone, Debug, PartialEq, Citizen)]
48#[citizen(symbol = "stream-bridge/LiftMidiOptions", version = 1)]
49pub struct StreamBridgeLiftMidiOptions {
50 /// Input sample rate in hertz used to convert sample offsets to time.
51 pub sample_rate: u32,
52 /// Ticks per quarter note for the lifted MIDI timeline.
53 pub tpq: u16,
54 /// Microseconds per quarter note used to map seconds onto ticks.
55 pub us_per_quarter: u32,
56 /// Minimum confidence a lifted note candidate must reach to be emitted.
57 pub min_confidence: f64,
58 /// Analysis window size, in samples, for the lifter.
59 pub window_size: usize,
60 /// Hop size, in samples, between successive analysis windows.
61 pub hop_size: usize,
62 /// Maximum number of MIDI events packed into a single stream packet.
63 pub max_events_per_packet: usize,
64}
65
66impl Default for StreamBridgeLiftMidiOptions {
67 fn default() -> Self {
68 Self {
69 sample_rate: 48_000,
70 tpq: 480,
71 us_per_quarter: DEFAULT_US_PER_QUARTER,
72 min_confidence: 0.75,
73 window_size: 2048,
74 hop_size: 512,
75 max_events_per_packet: 64,
76 }
77 }
78}
79
80/// Returns the `stream/bridge` symbol naming the bridge function export.
81///
82/// # Examples
83///
84/// ```
85/// let symbol = sim_lib_stream_bridge::stream_bridge_symbol();
86/// assert_eq!(&*symbol.name, "bridge");
87/// ```
88pub fn stream_bridge_symbol() -> Symbol {
89 Symbol::qualified("stream", "bridge")
90}
91
92/// Returns the class symbol for [`StreamBridgeRenderOptions`].
93pub fn stream_bridge_render_options_class_symbol() -> Symbol {
94 Symbol::qualified("stream-bridge", "RenderOptions")
95}
96
97/// Returns the class symbol for [`StreamBridgeLiftMidiOptions`].
98pub fn stream_bridge_lift_midi_options_class_symbol() -> Symbol {
99 Symbol::qualified("stream-bridge", "LiftMidiOptions")
100}