sim_lib_plugin_vst3/
event.rs1use std::collections::BTreeMap;
2
3use sim_kernel::{Error, Result};
4use sim_lib_audio_graph_core::BlockEvent;
5
6#[derive(Clone, Debug, PartialEq)]
12pub enum Vst3Event {
13 NoteOn {
15 sample_offset: u32,
17 channel: u8,
19 pitch: u8,
21 velocity: f32,
23 },
24 NoteOff {
26 sample_offset: u32,
28 channel: u8,
30 pitch: u8,
32 velocity: f32,
34 },
35 Midi {
37 sample_offset: u32,
39 bytes: [u8; 3],
41 len: u8,
43 },
44 ParamValue {
46 sample_offset: u32,
48 vst3_param_id: u32,
50 normalized: f64,
52 },
53}
54
55impl Vst3Event {
56 pub fn to_block_event(&self, params: &Vst3ParamMap) -> BlockEvent<'_> {
59 match self {
60 Self::NoteOn {
61 sample_offset,
62 channel,
63 pitch,
64 velocity,
65 } => BlockEvent::NoteOn {
66 offset: *sample_offset,
67 channel: *channel,
68 key: *pitch,
69 velocity: *velocity,
70 },
71 Self::NoteOff {
72 sample_offset,
73 channel,
74 pitch,
75 velocity,
76 } => BlockEvent::NoteOff {
77 offset: *sample_offset,
78 channel: *channel,
79 key: *pitch,
80 velocity: *velocity,
81 },
82 Self::Midi {
83 sample_offset,
84 bytes,
85 len,
86 } => BlockEvent::Midi {
87 offset: *sample_offset,
88 bytes: *bytes,
89 len: *len,
90 },
91 Self::ParamValue {
92 sample_offset,
93 vst3_param_id,
94 normalized,
95 } => BlockEvent::ParamSet {
96 offset: *sample_offset,
97 param: params.sim_param_for(*vst3_param_id),
98 value: *normalized,
99 },
100 }
101 }
102
103 pub fn try_to_block_event(&self, params: &Vst3ParamMap, frames: u32) -> Result<BlockEvent<'_>> {
106 let event = self.to_block_event(params);
107 let offset = block_event_offset(&event);
108 if offset >= frames {
109 return Err(Error::Eval(format!(
110 "VST3 event offset {offset} is outside block frames 0..{frames}"
111 )));
112 }
113 Ok(event)
114 }
115}
116
117fn block_event_offset(event: &BlockEvent<'_>) -> u32 {
118 match *event {
119 BlockEvent::Midi { offset, .. }
120 | BlockEvent::MidiLong { offset, .. }
121 | BlockEvent::ParamSet { offset, .. }
122 | BlockEvent::NoteOn { offset, .. }
123 | BlockEvent::NoteOff { offset, .. } => offset,
124 }
125}
126
127#[derive(Clone, Debug, Default, PartialEq, Eq)]
131pub struct Vst3ParamMap {
132 vst3_to_sim: BTreeMap<u32, u32>,
133}
134
135impl Vst3ParamMap {
136 pub fn new() -> Self {
138 Self::default()
139 }
140
141 pub fn identity(ids: impl IntoIterator<Item = u32>) -> Self {
143 let mut map = Self::new();
144 for id in ids {
145 map.insert(id, id);
146 }
147 map
148 }
149
150 pub fn insert(&mut self, vst3_param_id: u32, sim_param_id: u32) {
152 self.vst3_to_sim.insert(vst3_param_id, sim_param_id);
153 }
154
155 pub fn sim_param_for(&self, vst3_param_id: u32) -> u32 {
158 self.vst3_to_sim
159 .get(&vst3_param_id)
160 .copied()
161 .unwrap_or(vst3_param_id)
162 }
163}
164
165#[derive(Clone, Debug, Default, PartialEq)]
167pub struct Vst3EventBuffer {
168 events: Vec<Vst3Event>,
169}
170
171impl Vst3EventBuffer {
172 pub fn new(events: Vec<Vst3Event>) -> Self {
174 Self { events }
175 }
176
177 pub fn events(&self) -> &[Vst3Event] {
179 &self.events
180 }
181
182 pub fn push(&mut self, event: Vst3Event) {
184 self.events.push(event);
185 }
186
187 pub fn to_block_events(&self, params: &Vst3ParamMap) -> Vec<BlockEvent<'_>> {
190 self.events
191 .iter()
192 .map(|event| event.to_block_event(params))
193 .collect()
194 }
195
196 pub fn try_to_block_events(
199 &self,
200 params: &Vst3ParamMap,
201 frames: u32,
202 ) -> Result<Vec<BlockEvent<'_>>> {
203 self.events
204 .iter()
205 .map(|event| event.try_to_block_event(params, frames))
206 .collect()
207 }
208}