sim_lib_plugin_vst3/event.rs
1use std::collections::BTreeMap;
2
3use sim_lib_audio_graph_core::BlockEvent;
4
5/// A VST3 input event for one processing block.
6///
7/// Mirrors the VST3 event surface; [`to_block_event`](Vst3Event::to_block_event)
8/// translates each variant into a graph `BlockEvent`, remapping parameter ids
9/// through a [`Vst3ParamMap`].
10#[derive(Clone, Debug, PartialEq)]
11pub enum Vst3Event {
12 /// A note-on event.
13 NoteOn {
14 /// The sample offset of the event within the block.
15 sample_offset: u32,
16 /// The MIDI channel.
17 channel: u8,
18 /// The note pitch (MIDI key number).
19 pitch: u8,
20 /// The note-on velocity.
21 velocity: f32,
22 },
23 /// A note-off event.
24 NoteOff {
25 /// The sample offset of the event within the block.
26 sample_offset: u32,
27 /// The MIDI channel.
28 channel: u8,
29 /// The note pitch (MIDI key number).
30 pitch: u8,
31 /// The note-off (release) velocity.
32 velocity: f32,
33 },
34 /// A raw MIDI event of up to three bytes.
35 Midi {
36 /// The sample offset of the event within the block.
37 sample_offset: u32,
38 /// The MIDI message bytes.
39 bytes: [u8; 3],
40 /// The number of valid bytes in `bytes`.
41 len: u8,
42 },
43 /// A normalized parameter value change.
44 ParamValue {
45 /// The sample offset of the event within the block.
46 sample_offset: u32,
47 /// The VST3 parameter id, remapped to a SIM id on conversion.
48 vst3_param_id: u32,
49 /// The normalized parameter value.
50 normalized: f64,
51 },
52}
53
54impl Vst3Event {
55 /// Translates this event into a graph `BlockEvent`, remapping any parameter
56 /// id through `params`.
57 pub fn to_block_event(&self, params: &Vst3ParamMap) -> BlockEvent<'_> {
58 match self {
59 Self::NoteOn {
60 sample_offset,
61 channel,
62 pitch,
63 velocity,
64 } => BlockEvent::NoteOn {
65 offset: *sample_offset,
66 channel: *channel,
67 key: *pitch,
68 velocity: *velocity,
69 },
70 Self::NoteOff {
71 sample_offset,
72 channel,
73 pitch,
74 velocity,
75 } => BlockEvent::NoteOff {
76 offset: *sample_offset,
77 channel: *channel,
78 key: *pitch,
79 velocity: *velocity,
80 },
81 Self::Midi {
82 sample_offset,
83 bytes,
84 len,
85 } => BlockEvent::Midi {
86 offset: *sample_offset,
87 bytes: *bytes,
88 len: *len,
89 },
90 Self::ParamValue {
91 sample_offset,
92 vst3_param_id,
93 normalized,
94 } => BlockEvent::ParamSet {
95 offset: *sample_offset,
96 param: params.sim_param_for(*vst3_param_id),
97 value: *normalized,
98 },
99 }
100 }
101}
102
103/// A mapping from host-facing VST3 parameter ids to SIM parameter ids.
104///
105/// Unmapped ids pass through unchanged, so an empty map behaves as the identity.
106#[derive(Clone, Debug, Default, PartialEq, Eq)]
107pub struct Vst3ParamMap {
108 vst3_to_sim: BTreeMap<u32, u32>,
109}
110
111impl Vst3ParamMap {
112 /// Creates an empty map (every id passes through unchanged).
113 pub fn new() -> Self {
114 Self::default()
115 }
116
117 /// Creates a map where each id in `ids` maps to itself.
118 pub fn identity(ids: impl IntoIterator<Item = u32>) -> Self {
119 let mut map = Self::new();
120 for id in ids {
121 map.insert(id, id);
122 }
123 map
124 }
125
126 /// Records that `vst3_param_id` maps to `sim_param_id`.
127 pub fn insert(&mut self, vst3_param_id: u32, sim_param_id: u32) {
128 self.vst3_to_sim.insert(vst3_param_id, sim_param_id);
129 }
130
131 /// Returns the SIM parameter id for `vst3_param_id`, or the input id itself
132 /// when it is unmapped.
133 pub fn sim_param_for(&self, vst3_param_id: u32) -> u32 {
134 self.vst3_to_sim
135 .get(&vst3_param_id)
136 .copied()
137 .unwrap_or(vst3_param_id)
138 }
139}
140
141/// An ordered buffer of VST3 events for one processing block.
142#[derive(Clone, Debug, Default, PartialEq)]
143pub struct Vst3EventBuffer {
144 events: Vec<Vst3Event>,
145}
146
147impl Vst3EventBuffer {
148 /// Creates a buffer from an existing `events` vector.
149 pub fn new(events: Vec<Vst3Event>) -> Self {
150 Self { events }
151 }
152
153 /// Returns the buffered events in order.
154 pub fn events(&self) -> &[Vst3Event] {
155 &self.events
156 }
157
158 /// Appends `event` to the buffer.
159 pub fn push(&mut self, event: Vst3Event) {
160 self.events.push(event);
161 }
162
163 /// Translates every buffered event into a graph `BlockEvent`, remapping
164 /// parameter ids through `params`.
165 pub fn to_block_events(&self, params: &Vst3ParamMap) -> Vec<BlockEvent<'_>> {
166 self.events
167 .iter()
168 .map(|event| event.to_block_event(params))
169 .collect()
170 }
171}