use std::collections::BTreeMap;
use sim_lib_audio_graph_core::BlockEvent;
#[derive(Clone, Debug, PartialEq)]
pub enum Vst3Event {
NoteOn {
sample_offset: u32,
channel: u8,
pitch: u8,
velocity: f32,
},
NoteOff {
sample_offset: u32,
channel: u8,
pitch: u8,
velocity: f32,
},
Midi {
sample_offset: u32,
bytes: [u8; 3],
len: u8,
},
ParamValue {
sample_offset: u32,
vst3_param_id: u32,
normalized: f64,
},
}
impl Vst3Event {
pub fn to_block_event(&self, params: &Vst3ParamMap) -> BlockEvent<'_> {
match self {
Self::NoteOn {
sample_offset,
channel,
pitch,
velocity,
} => BlockEvent::NoteOn {
offset: *sample_offset,
channel: *channel,
key: *pitch,
velocity: *velocity,
},
Self::NoteOff {
sample_offset,
channel,
pitch,
velocity,
} => BlockEvent::NoteOff {
offset: *sample_offset,
channel: *channel,
key: *pitch,
velocity: *velocity,
},
Self::Midi {
sample_offset,
bytes,
len,
} => BlockEvent::Midi {
offset: *sample_offset,
bytes: *bytes,
len: *len,
},
Self::ParamValue {
sample_offset,
vst3_param_id,
normalized,
} => BlockEvent::ParamSet {
offset: *sample_offset,
param: params.sim_param_for(*vst3_param_id),
value: *normalized,
},
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Vst3ParamMap {
vst3_to_sim: BTreeMap<u32, u32>,
}
impl Vst3ParamMap {
pub fn new() -> Self {
Self::default()
}
pub fn identity(ids: impl IntoIterator<Item = u32>) -> Self {
let mut map = Self::new();
for id in ids {
map.insert(id, id);
}
map
}
pub fn insert(&mut self, vst3_param_id: u32, sim_param_id: u32) {
self.vst3_to_sim.insert(vst3_param_id, sim_param_id);
}
pub fn sim_param_for(&self, vst3_param_id: u32) -> u32 {
self.vst3_to_sim
.get(&vst3_param_id)
.copied()
.unwrap_or(vst3_param_id)
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Vst3EventBuffer {
events: Vec<Vst3Event>,
}
impl Vst3EventBuffer {
pub fn new(events: Vec<Vst3Event>) -> Self {
Self { events }
}
pub fn events(&self) -> &[Vst3Event] {
&self.events
}
pub fn push(&mut self, event: Vst3Event) {
self.events.push(event);
}
pub fn to_block_events(&self, params: &Vst3ParamMap) -> Vec<BlockEvent<'_>> {
self.events
.iter()
.map(|event| event.to_block_event(params))
.collect()
}
}