use midix::prelude::*;
mod parsed;
#[test]
fn midi_file_ref() {
let bytes = include_bytes!("./simple.mid");
let mut reader = Reader::from_byte_slice(bytes);
let Ok(FileEvent::Header(header)) = reader.read_event() else {
panic!()
};
assert_eq!(header.format_type(), FormatType::SingleMultiChannel);
assert_eq!(header.timing().ticks_per_quarter_note(), Some(96));
let Ok(FileEvent::Track(track)) = reader.read_event() else {
panic!()
};
assert_eq!(track.len(), 59);
let Ok(FileEvent::TrackEvent(track_event)) = reader.read_event() else {
panic!()
};
assert_eq!(track_event.delta_ticks(), 0);
let TrackMessage::Meta(MetaMessage::TimeSignature(time_sig)) = track_event.event() else {
panic!();
};
assert_eq!(time_sig.num(), 4);
assert_eq!(time_sig.den(), 2); assert_eq!(time_sig.clocks_per_click(), 24);
assert_eq!(time_sig.notated_32nds_per_24_clocks(), 8);
let Ok(FileEvent::TrackEvent(track_event)) = reader.read_event() else {
panic!()
};
assert_eq!(track_event.delta_ticks(), 0);
let TrackMessage::Meta(MetaMessage::Tempo(tempo)) = track_event.event() else {
panic!();
};
assert_eq!(tempo.micros_per_quarter_note(), 500000);
let Ok(FileEvent::TrackEvent(track_event)) = reader.read_event() else {
panic!()
};
assert_eq!(track_event.delta_ticks(), 0);
let TrackMessage::ChannelVoice(cv) = track_event.event() else {
panic!();
};
assert_eq!(cv.channel(), Channel::One);
let VoiceEvent::ProgramChange { program } = cv.event() else {
panic!();
};
assert_eq!(program.byte(), 5);
let Ok(FileEvent::TrackEvent(track_event)) = reader.read_event() else {
panic!()
};
assert_eq!(track_event.delta_ticks(), 0);
let TrackMessage::ChannelVoice(cv) = track_event.event() else {
panic!();
};
assert_eq!(cv.channel(), Channel::Two);
let VoiceEvent::ProgramChange { program } = cv.event() else {
panic!();
};
assert_eq!(program.byte(), 46);
let Ok(FileEvent::TrackEvent(track_event)) = reader.read_event() else {
panic!()
};
assert_eq!(track_event.delta_ticks(), 0);
let TrackMessage::ChannelVoice(cv) = track_event.event() else {
panic!();
};
assert_eq!(cv.channel(), Channel::Three);
let VoiceEvent::ProgramChange { program } = cv.event() else {
panic!();
};
assert_eq!(program.byte(), 70);
use Channel::*;
note_on(&mut reader, 0, Three, Note::C, 3, Dynamic::ff());
note_on(&mut reader, 0, Three, Note::C, 4, Dynamic::ff());
note_on(&mut reader, 96, Two, Note::G, 4, Dynamic::mf());
note_on(&mut reader, 96, One, Note::E, 5, Dynamic::p());
note_off(&mut reader, 192, Three, Note::C, 3);
note_off(&mut reader, 0, Three, Note::C, 4);
note_off(&mut reader, 0, Two, Note::G, 4);
note_off(&mut reader, 0, One, Note::E, 5);
}
fn note_on(
reader: &mut Reader<&[u8]>,
delta_ticks: u32,
channel: Channel,
note: Note,
octave: i8,
dynamic: Dynamic,
) {
let Ok(FileEvent::TrackEvent(track_event)) = reader.read_event() else {
panic!()
};
assert_eq!(track_event.delta_ticks(), delta_ticks);
let TrackMessage::ChannelVoice(cv) = track_event.event() else {
panic!();
};
assert_eq!(cv.channel(), channel);
let VoiceEvent::NoteOn { key, velocity } = cv.event() else {
panic!();
};
assert_eq!(key.note(), note);
assert_eq!(key.octave(), Octave::new(octave));
assert_eq!(velocity.dynamic(), dynamic);
}
fn note_off(
reader: &mut Reader<&[u8]>,
delta_ticks: u32,
channel: Channel,
note: Note,
octave: i8,
) {
let Ok(FileEvent::TrackEvent(track_event)) = reader.read_event() else {
panic!()
};
assert_eq!(track_event.delta_ticks(), delta_ticks);
let TrackMessage::ChannelVoice(cv) = track_event.event() else {
panic!();
};
assert_eq!(cv.channel(), channel);
match cv.event() {
VoiceEvent::NoteOn { key, velocity } => {
assert_eq!(velocity.byte(), 0);
assert_eq!(key.note(), note);
assert_eq!(key.octave(), Octave::new(octave));
}
VoiceEvent::NoteOff { key, velocity: _ } => {
assert_eq!(key.note(), note);
assert_eq!(key.octave(), Octave::new(octave));
}
_ => panic!(),
}
}