use sim_kernel::Result;
use sim_lib_stream_core::{ClockDomain, LatencyClass};
use crate::{PortDecl, PortDir, PortMedia, ProcessBlock};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PrepareConfig {
pub sample_rate_hz: u32,
pub max_block_frames: u32,
pub in_channels: u16,
pub out_channels: u16,
}
impl PrepareConfig {
pub fn new(
sample_rate_hz: u32,
max_block_frames: u32,
in_channels: u16,
out_channels: u16,
) -> Self {
Self {
sample_rate_hz,
max_block_frames,
in_channels,
out_channels,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Transport {
pub playing: bool,
pub sample_pos: u64,
pub tempo_bpm: f64,
pub ppq_pos: f64,
}
impl Default for Transport {
fn default() -> Self {
Self {
playing: false,
sample_pos: 0,
tempo_bpm: 120.0,
ppq_pos: 0.0,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BlockEvent<'a> {
Midi {
offset: u32,
bytes: [u8; 3],
len: u8,
},
MidiLong {
offset: u32,
bytes: &'a [u8],
},
ParamSet {
offset: u32,
param: u32,
value: f64,
},
NoteOn {
offset: u32,
channel: u8,
key: u8,
velocity: f32,
},
NoteOff {
offset: u32,
channel: u8,
key: u8,
velocity: f32,
},
}
pub trait EventSink {
fn push(&mut self, event: BlockEvent<'_>) -> Result<()>;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct NullEventSink;
impl EventSink for NullEventSink {
fn push(&mut self, _event: BlockEvent<'_>) -> Result<()> {
Ok(())
}
}
pub trait Processor: Send {
fn prepare(&mut self, cfg: PrepareConfig);
fn reset(&mut self);
fn process(&mut self, block: &mut ProcessBlock<'_>);
fn clock_domain(&self) -> ClockDomain {
ClockDomain::Sample
}
fn latency_class(&self) -> LatencyClass {
LatencyClass::BlockLocal
}
fn realtime_pin(&self) -> bool {
true
}
fn ports(&self, in_channels: u16, out_channels: u16) -> Vec<PortDecl> {
default_processor_ports(in_channels, out_channels)
}
fn descriptor(&self, in_channels: u16, out_channels: u16) -> ProcessorDescriptor {
ProcessorDescriptor::new(
self.clock_domain(),
self.latency_class(),
self.realtime_pin(),
self.ports(in_channels, out_channels),
)
}
fn tail_frames(&self) -> u64 {
0
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProcessorDescriptor {
clock_domain: ClockDomain,
latency_class: LatencyClass,
realtime_pin: bool,
ports: Vec<PortDecl>,
}
impl ProcessorDescriptor {
pub fn new(
clock_domain: ClockDomain,
latency_class: LatencyClass,
realtime_pin: bool,
ports: Vec<PortDecl>,
) -> Self {
Self {
clock_domain,
latency_class,
realtime_pin,
ports,
}
}
pub fn clock_domain(&self) -> ClockDomain {
self.clock_domain
}
pub fn latency_class(&self) -> LatencyClass {
self.latency_class
}
pub fn realtime_pin(&self) -> bool {
self.realtime_pin
}
pub fn ports(&self) -> &[PortDecl] {
&self.ports
}
}
fn default_processor_ports(in_channels: u16, out_channels: u16) -> Vec<PortDecl> {
let mut ports = Vec::new();
if in_channels > 0 {
ports.push(PortDecl::new(
"in",
PortMedia::Audio,
PortDir::In,
in_channels,
));
}
if out_channels > 0 {
ports.push(PortDecl::new(
"out",
PortMedia::Audio,
PortDir::Out,
out_channels,
));
}
ports
}