Skip to main content

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}