use sim_citizen_derive::Citizen;
use sim_kernel::{Diagnostic, Error, Result, Symbol};
use sim_lib_midi_core::DEFAULT_US_PER_QUARTER;
use sim_lib_stream_core::StreamValue;
pub struct BridgeOutput {
pub stream: StreamValue,
pub diagnostics: Vec<Diagnostic>,
}
#[derive(Clone, Debug, PartialEq, Citizen)]
#[citizen(symbol = "stream-bridge/RenderOptions", version = 1)]
pub struct StreamBridgeRenderOptions {
pub sample_rate: u32,
pub channels: u8,
pub chunk_frames: usize,
}
impl StreamBridgeRenderOptions {
pub fn new(sample_rate: u32, channels: u8, chunk_frames: usize) -> Result<Self> {
let options = Self {
sample_rate,
channels,
chunk_frames,
};
options.validate()?;
Ok(options)
}
pub fn validate(&self) -> Result<()> {
if self.sample_rate == 0 {
return Err(Error::Eval(
"stream/bridge render sample_rate must be greater than zero".to_owned(),
));
}
if !(1..=2).contains(&self.channels) {
return Err(Error::Eval(
"stream/bridge render channels must be 1 or 2".to_owned(),
));
}
if self.chunk_frames == 0 {
return Err(Error::Eval(
"stream/bridge render chunk_frames must be greater than zero".to_owned(),
));
}
Ok(())
}
}
impl Default for StreamBridgeRenderOptions {
fn default() -> Self {
Self {
sample_rate: 48_000,
channels: 2,
chunk_frames: 512,
}
}
}
#[derive(Clone, Debug, PartialEq, Citizen)]
#[citizen(symbol = "stream-bridge/LiftMidiOptions", version = 1)]
pub struct StreamBridgeLiftMidiOptions {
pub sample_rate: u32,
pub tpq: u16,
pub us_per_quarter: u32,
pub min_confidence: f64,
pub window_size: usize,
pub hop_size: usize,
pub max_events_per_packet: usize,
}
impl StreamBridgeLiftMidiOptions {
pub fn validate(&self) -> Result<()> {
if self.sample_rate == 0 {
return Err(Error::Eval(
"stream/bridge lift-midi sample_rate must be greater than zero".to_owned(),
));
}
if self.tpq == 0 {
return Err(Error::Eval(
"stream/bridge lift-midi tpq must be greater than zero".to_owned(),
));
}
if self.us_per_quarter == 0 {
return Err(Error::Eval(
"stream/bridge lift-midi us_per_quarter must be greater than zero".to_owned(),
));
}
if !self.min_confidence.is_finite() || !(0.0..=1.0).contains(&self.min_confidence) {
return Err(Error::Eval(
"stream/bridge lift-midi min_confidence must be between 0 and 1".to_owned(),
));
}
if self.window_size == 0 {
return Err(Error::Eval(
"stream/bridge lift-midi window_size must be greater than zero".to_owned(),
));
}
if self.hop_size == 0 {
return Err(Error::Eval(
"stream/bridge lift-midi hop_size must be greater than zero".to_owned(),
));
}
if self.max_events_per_packet == 0 {
return Err(Error::Eval(
"stream/bridge lift-midi max_events_per_packet must be greater than zero"
.to_owned(),
));
}
Ok(())
}
}
impl Default for StreamBridgeLiftMidiOptions {
fn default() -> Self {
Self {
sample_rate: 48_000,
tpq: 480,
us_per_quarter: DEFAULT_US_PER_QUARTER,
min_confidence: 0.75,
window_size: 2048,
hop_size: 512,
max_events_per_packet: 64,
}
}
}
pub fn stream_bridge_symbol() -> Symbol {
Symbol::qualified("stream", "bridge")
}
pub fn stream_bridge_render_options_class_symbol() -> Symbol {
Symbol::qualified("stream-bridge", "RenderOptions")
}
pub fn stream_bridge_lift_midi_options_class_symbol() -> Symbol {
Symbol::qualified("stream-bridge", "LiftMidiOptions")
}