midi_event/
parse.rs

1use crate::types::*;
2
3use core::{mem, slice};
4
5/// Go from raw input into a midi event.
6pub trait Parse<Input>: Sized {
7    fn parse(input: Input) -> Option<Self>;
8}
9
10impl<'src> Parse<&'src [u8]> for Event<'src> {
11    #[inline]
12    fn parse(input: &[u8]) -> Option<Event> {
13        let first = input.get(0)?;
14        match first & 0xF0 {
15            0x80 => {
16                let velocity = *input.get(2)?;
17                let note = *input.get(1)?;
18                Some(Event::Midi(MidiEvent {
19                    channel: first & 0x0F,
20                    event: MidiEventType::NoteOff(note.into(), velocity & 0x7F),
21                }))
22            }
23            0x90 => {
24                let velocity = *input.get(2)?;
25                let note = *input.get(1)?;
26                Some(Event::Midi(MidiEvent {
27                    channel: first & 0x0F,
28                    event: MidiEventType::NoteOn(note.into(), velocity & 0x7F),
29                }))
30            }
31            0xA0 => {
32                let pressure = *input.get(2)?;
33                let note = *input.get(1)?;
34                Some(Event::Midi(MidiEvent {
35                    channel: first & 0x0F,
36                    event: MidiEventType::PolyphonicPressure(note.into(), pressure & 0x7F),
37                }))
38            }
39            0xB0 => {
40                let value = *input.get(2)?;
41                let controller = *input.get(1)?;
42                Some(Event::Midi(MidiEvent {
43                    channel: first & 0x0F,
44                    event: MidiEventType::Controller(controller & 0x7F, value & 0x7F),
45                }))
46            }
47            0xC0 => {
48                let program = *input.get(1)?;
49                Some(Event::Midi(MidiEvent {
50                    channel: first & 0x0F,
51                    event: MidiEventType::ProgramChange(program & 0x7F),
52                }))
53            }
54            0xD0 => {
55                let pressure = *input.get(1)?;
56                Some(Event::Midi(MidiEvent {
57                    channel: first & 0x0F,
58                    event: MidiEventType::ChannelPressure(pressure & 0x7F),
59                }))
60            }
61            0xE0 => {
62                let msb = *input.get(2)?;
63                let lsb = *input.get(1)?;
64                Some(Event::Midi(MidiEvent {
65                    channel: first & 0x0F,
66                    event: MidiEventType::PitchBend(lsb & 0x7F, msb & 0x7F),
67                }))
68            }
69            0xF0 => match first & 0x0F {
70                0x00 => {
71                    let mut end_idx = 0;
72                    loop {
73                        match input.get(end_idx) {
74                            Some(0xF7) | None => break,
75                            _ => (),
76                        }
77                        end_idx += 1;
78                    }
79                    unsafe {
80                        let pointer = input.as_ptr().offset(1);
81                        Some(Event::SysEx(slice::from_raw_parts(pointer, end_idx - 1)))
82                    }
83                }
84                _ => None,
85            },
86            _ => None,
87        }
88    }
89}
90
91impl Parse<&'_ [u8]> for MidiEvent {
92    #[inline]
93    fn parse(input: &[u8]) -> Option<MidiEvent> {
94        match Event::parse(input) {
95            Some(Event::Midi(evt)) => Some(evt),
96            _ => None,
97        }
98    }
99}
100
101impl Parse<u8> for Note {
102    #[inline]
103    fn parse(input: u8) -> Option<Self> {
104        if input & 0x80 == 0x80 {
105            None
106        } else {
107            Some(unsafe { mem::transmute(input) })
108        }
109    }
110}