From 2c6dbbf952b822f2c48eb44a0ef9e6194ebe2218 Mon Sep 17 00:00:00 2001 From: Nicole Tietz-Sokolskaya <me@ntietz.com> Date: Sun, 10 Nov 2024 16:21:27 -0500 Subject: [PATCH] finish parsing voice messages --- src/bin/main.rs | 8 ++++---- src/midi.rs | 4 ++-- src/parser.rs | 30 +++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index a90e2b4..20b9933 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,6 +1,6 @@ use std::{ fs::File, - io::{stdin, Read, Write}, + io::{stdin, Write}, }; 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 len_buf = message.len().to_be_bytes(); - file.write(&ts_buf).unwrap(); - file.write(&len_buf).unwrap(); - file.write(message).unwrap(); + file.write_all(&ts_buf).unwrap(); + file.write_all(&len_buf).unwrap(); + file.write_all(message).unwrap(); } let hex_msg = hex::encode(message); diff --git a/src/midi.rs b/src/midi.rs index d7a0e9e..078d5ca 100644 --- a/src/midi.rs +++ b/src/midi.rs @@ -20,10 +20,10 @@ impl VoiceMessage { pub enum VoiceCategory { NoteOff { note: u8, velocity: u8 }, NoteOn { note: u8, velocity: u8 }, - AfterTouch, + AfterTouch { note: u8, pressure: u8 }, ControlChange { controller: u8, value: u8 }, ProgramChange { value: u8 }, - ChannelPressure, + ChannelPressure { pressure: u8 }, PitchWheel { value: u16 }, } diff --git a/src/parser.rs b/src/parser.rs index c7f040a..a04d9f8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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> { - return Err(nom::Err::Error(nom::error::Error { + Err(nom::Err::Error(nom::error::Error { input: bytes, code: nom::error::ErrorKind::Fail, - })); + })) } 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 { 0x80 => parse_voice_note(remainder, true)?, 0x90 => parse_voice_note(remainder, false)?, + 0xa0 => parse_aftertouch(remainder)?, 0xb0 => parse_control_change(remainder)?, 0xc0 => parse_program_change(remainder)?, + 0xd0 => parse_channel_pressure(remainder)?, 0xe0 => parse_pitch_wheel(remainder)?, _ => { 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> { - if bytes.len() < 1 { + if bytes.is_empty() { 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 })) } + +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)] mod tests { use crate::{log::load_raw_log, midi::VoiceMessage};