finish parsing voice messages

This commit is contained in:
Nicole Tietz-Sokolskaya 2024-11-10 16:21:27 -05:00
parent 36fafbf144
commit 2c6dbbf952
3 changed files with 33 additions and 9 deletions

View file

@ -1,6 +1,6 @@
use std::{ use std::{
fs::File, fs::File,
io::{stdin, Read, Write}, io::{stdin, Write},
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -65,9 +65,9 @@ fn handle_midi_event(timestamp: u64, message: &[u8], file: &mut Option<File>) {
let ts_buf = timestamp.to_be_bytes(); let ts_buf = timestamp.to_be_bytes();
let len_buf = message.len().to_be_bytes(); let len_buf = message.len().to_be_bytes();
file.write(&ts_buf).unwrap(); file.write_all(&ts_buf).unwrap();
file.write(&len_buf).unwrap(); file.write_all(&len_buf).unwrap();
file.write(message).unwrap(); file.write_all(message).unwrap();
} }
let hex_msg = hex::encode(message); let hex_msg = hex::encode(message);

View file

@ -20,10 +20,10 @@ impl VoiceMessage {
pub enum VoiceCategory { pub enum VoiceCategory {
NoteOff { note: u8, velocity: u8 }, NoteOff { note: u8, velocity: u8 },
NoteOn { note: u8, velocity: u8 }, NoteOn { note: u8, velocity: u8 },
AfterTouch, AfterTouch { note: u8, pressure: u8 },
ControlChange { controller: u8, value: u8 }, ControlChange { controller: u8, value: u8 },
ProgramChange { value: u8 }, ProgramChange { value: u8 },
ChannelPressure, ChannelPressure { pressure: u8 },
PitchWheel { value: u16 }, PitchWheel { value: u16 },
} }

View file

@ -16,10 +16,10 @@ pub fn parse_message(bytes: &[u8]) -> IResult<&[u8], Message> {
} }
fn parse_status_message(_status_byte: u8, bytes: &[u8]) -> IResult<&[u8], SystemMessage> { fn parse_status_message(_status_byte: u8, bytes: &[u8]) -> IResult<&[u8], SystemMessage> {
return Err(nom::Err::Error(nom::error::Error { Err(nom::Err::Error(nom::error::Error {
input: bytes, input: bytes,
code: nom::error::ErrorKind::Fail, code: nom::error::ErrorKind::Fail,
})); }))
} }
pub fn parse_voice_message(status_byte: u8, remainder: &[u8]) -> IResult<&[u8], VoiceMessage> { pub fn parse_voice_message(status_byte: u8, remainder: &[u8]) -> IResult<&[u8], VoiceMessage> {
@ -30,8 +30,10 @@ pub fn parse_voice_message(status_byte: u8, remainder: &[u8]) -> IResult<&[u8],
let (remainder, category) = match category_nibble { let (remainder, category) = match category_nibble {
0x80 => parse_voice_note(remainder, true)?, 0x80 => parse_voice_note(remainder, true)?,
0x90 => parse_voice_note(remainder, false)?, 0x90 => parse_voice_note(remainder, false)?,
0xa0 => parse_aftertouch(remainder)?,
0xb0 => parse_control_change(remainder)?, 0xb0 => parse_control_change(remainder)?,
0xc0 => parse_program_change(remainder)?, 0xc0 => parse_program_change(remainder)?,
0xd0 => parse_channel_pressure(remainder)?,
0xe0 => parse_pitch_wheel(remainder)?, 0xe0 => parse_pitch_wheel(remainder)?,
_ => { _ => {
return Err(nom::Err::Error(nom::error::Error { return Err(nom::Err::Error(nom::error::Error {
@ -92,7 +94,7 @@ pub fn parse_control_change(bytes: &[u8]) -> IResult<&[u8], VoiceCategory> {
} }
pub fn parse_program_change(bytes: &[u8]) -> IResult<&[u8], VoiceCategory> { pub fn parse_program_change(bytes: &[u8]) -> IResult<&[u8], VoiceCategory> {
if bytes.len() < 1 { if bytes.is_empty() {
return Err(generic_error(bytes)); return Err(generic_error(bytes));
} }
@ -100,6 +102,28 @@ pub fn parse_program_change(bytes: &[u8]) -> IResult<&[u8], VoiceCategory> {
Ok((&bytes[1..], VoiceCategory::ProgramChange { value })) Ok((&bytes[1..], VoiceCategory::ProgramChange { value }))
} }
pub fn parse_aftertouch(bytes: &[u8]) -> IResult<&[u8], VoiceCategory> {
if bytes.len() < 2 {
return Err(generic_error(bytes));
}
let note = bytes[0];
let pressure = bytes[1];
Ok((&bytes[2..], VoiceCategory::AfterTouch { note, pressure }))
}
pub fn parse_channel_pressure(bytes: &[u8]) -> IResult<&[u8], VoiceCategory> {
if bytes.is_empty() {
return Err(generic_error(bytes));
}
let pressure = bytes[0];
Ok((&bytes[1..], VoiceCategory::ChannelPressure { pressure }))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{log::load_raw_log, midi::VoiceMessage}; use crate::{log::load_raw_log, midi::VoiceMessage};