midi_toolkit/io/
track_parser.rs

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                            ret!(Event::new_delta_track_start_event(delta))
195                        }
196                        0x01..=0x0A | 0xF7 => {
197                            let size = self.read_var_length()?;
198                            let mut data = Vec::new();
199                            for _ in 0..size {
200                                data.push(self.read_fast()?);
201                            }
202                            data.shrink_to_fit();
203
204                            ret!(Event::new_delta_text_event(
205                                delta,
206                                TextEventKind::from_val(command),
207                                data
208                            ))
209                        }
210                        0x20 => {
211                            assert_len!(1);
212                            let prefix = self.read_fast()?;
213                            ret!(Event::new_delta_channel_prefix_event(delta, prefix))
214                        }
215                        0x21 => {
216                            assert_len!(1);
217                            let port = self.read_fast()?;
218                            ret!(Event::new_delta_midi_port_event(delta, port))
219                        }
220                        0x2F => {
221                            assert_len!(0);
222                            // Skip this event
223                            Ok(None)
224                        }
225                        0x51 => {
226                            assert_len!(3);
227                            let mut tempo: u32 = 0;
228                            for _ in 0..3 {
229                                tempo = (tempo << 8) | self.read_fast()? as u32;
230                            }
231                            ret!(Event::new_delta_tempo_event(delta, tempo))
232                        }
233                        0x54 => {
234                            assert_len!(5);
235                            let hr = self.read_fast()?;
236                            let mn = self.read_fast()?;
237                            let se = self.read_fast()?;
238                            let fr = self.read_fast()?;
239                            let ff = self.read_fast()?;
240                            ret!(Event::new_delta_smpte_offset_event(
241                                delta, hr, mn, se, fr, ff
242                            ))
243                        }
244                        0x58 => {
245                            assert_len!(4);
246                            let nn = self.read_fast()?;
247                            let dd = self.read_fast()?;
248                            let cc = self.read_fast()?;
249                            let bb = self.read_fast()?;
250                            ret!(Event::new_delta_time_signature_event(delta, nn, dd, cc, bb))
251                        }
252                        0x59 => {
253                            assert_len!(2);
254                            let sf = self.read_fast()?;
255                            let mi = self.read_fast()?;
256                            ret!(Event::new_delta_key_signature_event(delta, sf, mi))
257                        }
258                        _ => {
259                            let size = self.read_var_length()?;
260                            let mut data = Vec::new();
261                            for _ in 0..size {
262                                data.push(self.read_fast()?);
263                            }
264                            data.shrink_to_fit();
265
266                            ret!(Event::new_delta_unknown_meta_event(delta, command, data))
267                        }
268                    }
269                }
270                _ => ret!(Event::new_delta_undefined_event(delta, command)),
271            },
272        }
273    }
274}
275
276impl<T: TrackReader> Iterator for TrackParser<T> {
277    type Item = Result<Delta<u64, Event>, MIDIParseError>;
278
279    fn next(&mut self) -> Option<Self::Item> {
280        loop {
281            if self.errored || self.reader.is_at_end() {
282                return None;
283            }
284
285            let next_event = self.try_parse_next_event();
286            match next_event {
287                Ok(Some(event)) => return Some(Ok(event)),
288                Ok(None) => {
289                    // We skip some events such as track end events,
290                    // so we just loop again to get the next one
291                    continue;
292                }
293                Err(e) => {
294                    self.errored = true;
295                    return Some(Err(e));
296                }
297            }
298        }
299    }
300}