1use crate::{events::*, sequence::event::Delta};
2
3use super::{errors::MIDIParseError, readers::TrackReader};
4
5pub struct TrackParser<T: TrackReader> {
6 reader: T,
7 pushback: i16,
8 prev_command: u8,
9 errored: bool,
10}
11
12pub struct ParserCheckpoint {
13 pushback: i16,
14 prev_command: u8,
15 reader_pos: u64,
16 ended: bool,
17}
18
19impl ParserCheckpoint {
20 pub fn reader_pos(&self) -> u64 {
21 self.reader_pos
22 }
23}
24
25impl<T: TrackReader> TrackParser<T> {
26 pub fn from_checkpoint(reader: T, checkpoint: ParserCheckpoint) -> Self {
27 assert_eq!(
28 checkpoint.reader_pos,
29 reader.pos(),
30 "Checkpoint reader pos does not match reader pos"
31 );
32
33 Self {
34 reader,
35 pushback: checkpoint.pushback,
36 prev_command: checkpoint.prev_command,
37 errored: checkpoint.ended,
38 }
39 }
40
41 pub fn new(reader: T) -> Self {
42 Self {
43 reader,
44 pushback: -1,
45 prev_command: 0,
46 errored: false,
47 }
48 }
49
50 fn read(&mut self) -> Result<u8, MIDIParseError> {
51 if self.pushback != -1 {
52 let p: u8 = self.pushback as u8;
53 self.pushback = -1;
54 return Ok(p);
55 }
56 self.reader.read()
57 }
58
59 fn read_fast(&mut self) -> Result<u8, MIDIParseError> {
60 self.reader.read()
61 }
62
63 fn read_var_length(&mut self) -> Result<u64, MIDIParseError> {
64 let mut n: u64 = 0;
65 loop {
66 let byte = self.read()?;
67 n = (n << 7) | (byte & 0x7F) as u64;
68 if (byte & 0x80) == 0 {
69 break;
70 }
71 }
72 Ok(n)
73 }
74
75 fn try_parse_next_event(&mut self) -> Result<Option<Delta<u64, Event>>, MIDIParseError> {
76 macro_rules! ret {
77 ($val:expr) => {
78 Ok(Some($val))
79 };
80 }
81
82 macro_rules! assert_len {
83 ($size:expr) => {
84 if self.read_fast()? != $size {
85 return Err(MIDIParseError::CorruptEvent {
86 track_number: self.reader.track_number(),
87 position: self.reader.pos(),
88 });
89 }
90 };
91 }
92
93 let delta = self.read_var_length()?;
94 let mut command = self.read()?;
95 if command < 0x80 {
96 self.pushback = command as i16;
97 command = self.prev_command;
98 }
99 self.prev_command = command;
100 let comm = command & 0xF0;
101 match comm {
102 0x80 => {
103 let channel = command & 0x0F;
104 let key = self.read()?;
105 let _vel = self.read_fast()?;
106 ret!(Event::new_delta_note_off_event(delta, channel, key))
107 }
108 0x90 => {
109 let channel = command & 0x0F;
110 let key = self.read()?;
111 let vel = self.read_fast()?;
112 if vel == 0 {
113 ret!(Event::new_delta_note_off_event(delta, channel, key))
114 } else {
115 ret!(Event::new_delta_note_on_event(delta, channel, key, vel))
116 }
117 }
118 0xA0 => {
119 let channel = command & 0x0F;
120 let key = self.read()?;
121 let vel = self.read_fast()?;
122 ret!(Event::new_delta_polyphonic_key_pressure_event(
123 delta, channel, key, vel
124 ))
125 }
126 0xB0 => {
127 let channel = command & 0x0F;
128 let controller = self.read()?;
129 let value = self.read_fast()?;
130 ret!(Event::new_delta_control_change_event(
131 delta, channel, controller, value
132 ))
133 }
134 0xC0 => {
135 let channel = command & 0x0F;
136 let program = self.read()?;
137 ret!(Event::new_delta_program_change_event(
138 delta, channel, program
139 ))
140 }
141 0xD0 => {
142 let channel = command & 0x0F;
143 let pressure = self.read()?;
144 ret!(Event::new_delta_channel_pressure_event(
145 delta, channel, pressure
146 ))
147 }
148 0xE0 => {
149 let channel = command & 0x0F;
150 let var1 = self.read()?;
151 let var2 = self.read_fast()?;
152 ret!(Event::new_delta_pitch_wheel_change_event(
153 delta,
154 channel,
155 (((var2 as i16) << 7) | var1 as i16) - 8192
156 ))
157 }
158 _ => match command {
159 0xF0 => {
160 let size = self.read_var_length()?;
161 let mut data = Vec::new();
162 for _ in 0..size {
163 data.push(self.read_fast()?);
164 }
165 data.shrink_to_fit();
166 ret!(Event::new_delta_system_exclusive_message_event(delta, data))
167 }
168 0xF2 => {
169 let var1 = self.read()?;
170 let var2 = self.read_fast()?;
171 ret!(Event::new_delta_song_position_pointer_event(
172 delta,
173 ((var2 as u16) << 7) | var1 as u16
174 ))
175 }
176 0xF3 => {
177 let pos = self.read()?;
178 ret!(Event::new_delta_song_select_event(delta, pos))
179 }
180 0xF6 => {
181 ret!(Event::new_delta_tune_request_event(delta))
182 }
183 0xF7 => {
184 ret!(Event::new_delta_end_of_exclusive_event(delta))
185 }
186 0xF8 => {
187 ret!(Event::new_delta_end_of_exclusive_event(delta))
188 }
189 0xFF => {
190 let command = self.read()?;
191 match command {
192 0x00 => {
193 assert_len!(2);
194 self.read_fast()?;
195 self.read_fast()?;
196 ret!(Event::new_delta_track_start_event(delta))
197 }
198 0x01..=0x0A | 0xF7 => {
199 let size = self.read_var_length()?;
200 let mut data = Vec::new();
201 for _ in 0..size {
202 data.push(self.read_fast()?);
203 }
204 data.shrink_to_fit();
205
206 ret!(Event::new_delta_text_event(
207 delta,
208 TextEventKind::from_val(command),
209 data
210 ))
211 }
212 0x20 => {
213 assert_len!(1);
214 let prefix = self.read_fast()?;
215 ret!(Event::new_delta_channel_prefix_event(delta, prefix))
216 }
217 0x21 => {
218 assert_len!(1);
219 let port = self.read_fast()?;
220 ret!(Event::new_delta_midi_port_event(delta, port))
221 }
222 0x2F => {
223 assert_len!(0);
224 Ok(None)
226 }
227 0x51 => {
228 assert_len!(3);
229 let mut tempo: u32 = 0;
230 for _ in 0..3 {
231 tempo = (tempo << 8) | self.read_fast()? as u32;
232 }
233 ret!(Event::new_delta_tempo_event(delta, tempo))
234 }
235 0x54 => {
236 assert_len!(5);
237 let hr = self.read_fast()?;
238 let mn = self.read_fast()?;
239 let se = self.read_fast()?;
240 let fr = self.read_fast()?;
241 let ff = self.read_fast()?;
242 ret!(Event::new_delta_smpte_offset_event(
243 delta, hr, mn, se, fr, ff
244 ))
245 }
246 0x58 => {
247 assert_len!(4);
248 let nn = self.read_fast()?;
249 let dd = self.read_fast()?;
250 let cc = self.read_fast()?;
251 let bb = self.read_fast()?;
252 ret!(Event::new_delta_time_signature_event(delta, nn, dd, cc, bb))
253 }
254 0x59 => {
255 assert_len!(2);
256 let sf = self.read_fast()?;
257 let mi = self.read_fast()?;
258 ret!(Event::new_delta_key_signature_event(delta, sf, mi))
259 }
260 _ => {
261 let size = self.read_var_length()?;
262 let mut data = Vec::new();
263 for _ in 0..size {
264 data.push(self.read_fast()?);
265 }
266 data.shrink_to_fit();
267
268 ret!(Event::new_delta_unknown_meta_event(delta, command, data))
269 }
270 }
271 }
272 _ => ret!(Event::new_delta_undefined_event(delta, command)),
273 },
274 }
275 }
276}
277
278impl<T: TrackReader> Iterator for TrackParser<T> {
279 type Item = Result<Delta<u64, Event>, MIDIParseError>;
280
281 fn next(&mut self) -> Option<Self::Item> {
282 loop {
283 if self.errored || self.reader.is_at_end() {
284 return None;
285 }
286
287 let next_event = self.try_parse_next_event();
288 match next_event {
289 Ok(Some(event)) => return Some(Ok(event)),
290 Ok(None) => {
291 continue;
294 }
295 Err(e) => {
296 self.errored = true;
297 return Some(Err(e));
298 }
299 }
300 }
301 }
302}
303
304#[cfg(test)]
305mod tests {
306 use super::TrackParser;
307 use crate::{
308 events::{Event, NoteOnEvent},
309 io::FullRamTrackReader,
310 };
311
312 #[test]
313 fn track_start_consumes_its_payload_bytes() {
314 let reader = FullRamTrackReader::new_from_vec(
315 None,
316 vec![0x00, 0xFF, 0x00, 0x02, 0x12, 0x34, 0x00, 0x90, 0x3C, 0x40],
317 );
318 let mut parser = TrackParser::new(reader);
319
320 let track_start = parser.next().unwrap().unwrap();
321 assert!(matches!(track_start.event, Event::TrackStart(_)));
322
323 let note_on = parser.next().unwrap().unwrap();
324 assert!(matches!(
325 note_on.event,
326 Event::NoteOn(NoteOnEvent {
327 channel: 0,
328 key: 0x3C,
329 velocity: 0x40,
330 })
331 ));
332
333 assert!(parser.next().is_none());
334 }
335}