finish parsing voice messages
This commit is contained in:
parent
36fafbf144
commit
2c6dbbf952
3 changed files with 33 additions and 9 deletions
|
@ -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);
|
||||||
|
|
|
@ -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 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
Loading…
Reference in a new issue