1pub const MAX_EVENTS: usize = 256;
3pub const MAX_SYSEX_BYTES: usize = 256;
4pub(crate) const EVENT_WORDS: usize = 72;
5pub(crate) const CONTEXT_WORDS: usize = 32;
6pub(crate) const PACKET_WORDS: usize = 2 + MAX_EVENTS * EVENT_WORDS;
7pub(crate) const METADATA_WORDS: usize = CONTEXT_WORDS + 2 * PACKET_WORDS;
8
9#[derive(Clone, Copy, Debug, PartialEq)]
10pub struct Transport {
11 pub sample_position: i64,
12 pub continuous_position: i64,
13 pub ppq_position: f64,
14 pub tempo: f64,
15 pub bar_start: f64,
16 pub cycle_start: f64,
17 pub cycle_end: f64,
18 pub numerator: u16,
19 pub denominator: u16,
20 pub playing: bool,
21 pub recording: bool,
22 pub cycling: bool,
23}
24impl Default for Transport {
25 fn default() -> Self {
26 Self {
27 sample_position: 0,
28 continuous_position: 0,
29 ppq_position: 0.0,
30 tempo: 120.0,
31 bar_start: 0.0,
32 cycle_start: 0.0,
33 cycle_end: 4.0,
34 numerator: 4,
35 denominator: 4,
36 playing: true,
37 recording: false,
38 cycling: false,
39 }
40 }
41}
42impl Transport {
43 pub fn valid(self) -> bool {
44 [
45 self.ppq_position,
46 self.tempo,
47 self.bar_start,
48 self.cycle_start,
49 self.cycle_end,
50 ]
51 .iter()
52 .all(|v| v.is_finite())
53 && self.tempo > 0.0
54 && self.tempo <= 1_000_000.0
55 && (1..=1024).contains(&self.numerator)
56 && self.denominator.is_power_of_two()
57 && self.denominator <= 1024
58 && (!self.cycling || self.cycle_end > self.cycle_start)
59 }
60 pub fn advanced(mut self, frames: usize, rate: u32) -> Self {
61 let frames_i64 = i64::try_from(frames).unwrap_or(i64::MAX);
62 self.continuous_position = self.continuous_position.saturating_add(frames_i64);
63 if self.playing {
64 self.sample_position = self.sample_position.saturating_add(frames_i64);
65 self.ppq_position += frames as f64 * self.tempo / (60.0 * f64::from(rate.max(1)));
66 }
67 self
68 }
69 pub(crate) fn words(self) -> [u32; CONTEXT_WORDS] {
70 let mut words = [0; CONTEXT_WORDS];
71 words[0] = u32::from(self.playing)
72 | (u32::from(self.recording) << 1)
73 | (u32::from(self.cycling) << 2);
74 words[1] = u32::from(self.numerator) | (u32::from(self.denominator) << 16);
75 for (i, value) in [
76 self.sample_position as u64,
77 self.continuous_position as u64,
78 self.ppq_position.to_bits(),
79 self.tempo.to_bits(),
80 self.bar_start.to_bits(),
81 self.cycle_start.to_bits(),
82 self.cycle_end.to_bits(),
83 ]
84 .into_iter()
85 .enumerate()
86 {
87 words[2 + i * 2] = value as u32;
88 words[3 + i * 2] = (value >> 32) as u32;
89 }
90 words
91 }
92 pub(crate) fn from_words(words: &[u32]) -> Option<Self> {
93 if words.len() < CONTEXT_WORDS || words[0] & !7 != 0 {
94 return None;
95 }
96 let wide = |i: usize| u64::from(words[2 + i * 2]) | (u64::from(words[3 + i * 2]) << 32);
97 let value = Self {
98 sample_position: wide(0) as i64,
99 continuous_position: wide(1) as i64,
100 ppq_position: f64::from_bits(wide(2)),
101 tempo: f64::from_bits(wide(3)),
102 bar_start: f64::from_bits(wide(4)),
103 cycle_start: f64::from_bits(wide(5)),
104 cycle_end: f64::from_bits(wide(6)),
105 numerator: words[1] as u16,
106 denominator: (words[1] >> 16) as u16,
107 playing: words[0] & 1 != 0,
108 recording: words[0] & 2 != 0,
109 cycling: words[0] & 4 != 0,
110 };
111 value.valid().then_some(value)
112 }
113}
114
115#[derive(Clone, Copy, Debug, PartialEq)]
116pub enum EventData {
117 Midi([u8; 3]),
119 SysEx {
120 len: u16,
121 bytes: [u8; MAX_SYSEX_BYTES],
122 },
123 Parameter {
124 id: u32,
125 value: f64,
126 },
127 Transport(Transport),
129}
130#[derive(Clone, Copy, Debug, PartialEq)]
131pub struct Event {
132 pub sample_offset: u32,
133 pub bus: u16,
134 pub data: EventData,
135}
136impl Default for Event {
137 fn default() -> Self {
138 Self {
139 sample_offset: 0,
140 bus: 0,
141 data: EventData::Midi([0x80, 0, 0]),
142 }
143 }
144}
145impl Event {
146 pub fn midi(sample_offset: u32, bus: u16, data: [u8; 3]) -> Self {
147 Self {
148 sample_offset,
149 bus,
150 data: EventData::Midi(data),
151 }
152 }
153 pub fn valid(self, frames: u32) -> bool {
154 self.sample_offset < frames
155 && self.bus < 32
156 && match self.data {
157 EventData::Midi([status, a, b]) => {
158 (0x80..=0xef).contains(&status)
159 && a < 128
160 && b < 128
161 && (!matches!(status & 0xf0, 0xc0 | 0xd0) || b == 0)
162 }
163 EventData::SysEx { len, .. } => usize::from(len) <= MAX_SYSEX_BYTES && len > 0,
164 EventData::Parameter { value, .. } => {
165 self.bus == 0 && value.is_finite() && (0.0..=1.0).contains(&value)
166 }
167 EventData::Transport(context) => self.bus == 0 && context.valid(),
168 }
169 }
170 pub(crate) fn words(self) -> [u32; EVENT_WORDS] {
171 let mut words = [0; EVENT_WORDS];
172 words[1] = self.sample_offset;
173 words[2] = u32::from(self.bus);
174 match self.data {
175 EventData::Midi([a, b, c]) => {
176 words[0] = 1;
177 words[3] = u32::from_le_bytes([a, b, c, 0]);
178 }
179 EventData::Parameter { id, value } => {
180 words[0] = 2;
181 words[3] = id;
182 words[4] = value.to_bits() as u32;
183 words[5] = (value.to_bits() >> 32) as u32;
184 }
185 EventData::Transport(context) => {
186 words[0] = 3;
187 words[4..4 + CONTEXT_WORDS].copy_from_slice(&context.words());
188 }
189 EventData::SysEx { len, bytes } => {
190 words[0] = 4;
191 words[3] = u32::from(len);
192 for (to, from) in words[4..68].iter_mut().zip(bytes.as_chunks::<4>().0.iter()) {
193 *to = u32::from_le_bytes(*from);
194 }
195 }
196 }
197 words
198 }
199 pub(crate) fn from_words(words: &[u32], frames: u32) -> Option<Self> {
200 if words.len() != EVENT_WORDS || words[2] >= 32 {
201 return None;
202 }
203 let data = match words[0] {
204 1 => {
205 let [a, b, c, d] = words[3].to_le_bytes();
206 if d != 0 {
207 return None;
208 }
209 EventData::Midi([a, b, c])
210 }
211 2 => EventData::Parameter {
212 id: words[3],
213 value: f64::from_bits(u64::from(words[4]) | (u64::from(words[5]) << 32)),
214 },
215 3 => EventData::Transport(Transport::from_words(&words[4..4 + CONTEXT_WORDS])?),
216 4 => {
217 if words[3] == 0 || words[3] > MAX_SYSEX_BYTES as u32 {
218 return None;
219 }
220 let mut bytes = [0; MAX_SYSEX_BYTES];
221 for (to, from) in bytes
222 .as_chunks_mut::<4>()
223 .0
224 .iter_mut()
225 .zip(words[4..68].iter())
226 {
227 to.copy_from_slice(&from.to_le_bytes());
228 }
229 EventData::SysEx {
230 len: words[3] as u16,
231 bytes,
232 }
233 }
234 _ => return None,
235 };
236 let event = Self {
237 sample_offset: words[1],
238 bus: words[2] as u16,
239 data,
240 };
241 event.valid(frames).then_some(event)
242 }
243}
244
245#[derive(Clone, Debug)]
246pub struct EventBuffer {
247 events: [Event; MAX_EVENTS],
248 len: usize,
249 pub dropped: u32,
250}
251impl Default for EventBuffer {
252 fn default() -> Self {
253 Self {
254 events: [Event::default(); MAX_EVENTS],
255 len: 0,
256 dropped: 0,
257 }
258 }
259}
260impl EventBuffer {
261 pub fn clear(&mut self) {
262 self.len = 0;
263 self.dropped = 0;
264 }
265 pub fn sort_by_offset(&mut self) {
266 for i in 1..self.len {
267 let mut j = i;
268 while j > 0 && self.events[j - 1].sample_offset > self.events[j].sample_offset {
269 self.events.swap(j - 1, j);
270 j -= 1;
271 }
272 }
273 }
274 pub fn as_slice(&self) -> &[Event] {
275 &self.events[..self.len]
276 }
277 pub fn push(&mut self, event: Event) -> bool {
278 if self.len == MAX_EVENTS {
279 self.dropped = self.dropped.saturating_add(1);
280 return false;
281 }
282 self.events[self.len] = event;
283 self.len += 1;
284 true
285 }
286}