aboutsummaryrefslogtreecommitdiff
path: root/src/midifile.rs
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2022-11-25 23:34:51 -0500
committerGravatar Chris Xiong <chirs241097@gmail.com> 2022-11-25 23:34:51 -0500
commitf8cf52fa4b2bbaff5627fa397a26589070084d3e (patch)
tree6ffc67fbba825eed811409732ce8e6cbda0dc38f /src/midifile.rs
parent736033237b41f91bcc093c06780e47c4ad5febaa (diff)
downloadit2midi-f8cf52fa4b2bbaff5627fa397a26589070084d3e.tar.xz
Actually produce some valid midi output.
Major restructure in the IT player: No more custom trait objects, let's just use closures instead... Basic note handling. Fixes to the midi file modules so the output is now valid. Other fixes to appease the Rust Gods. Current converter handles no IT effects (except timing effects like Axx, Bxx, Cxx, SBx and SEx, as those are handled as a part of the player). But this is a start.
Diffstat (limited to 'src/midifile.rs')
-rw-r--r--src/midifile.rs27
1 files changed, 16 insertions, 11 deletions
diff --git a/src/midifile.rs b/src/midifile.rs
index 71a861c..219a931 100644
--- a/src/midifile.rs
+++ b/src/midifile.rs
@@ -10,6 +10,7 @@ pub struct RawMidiEvent
data: Vec<u8>
}
+#[derive(Clone)]
pub enum MidiEvent
{
NoteOn{ch: u8, key: u8, vel: u8},
@@ -26,6 +27,7 @@ pub enum MidiEvent
MetaEndOfTrack
}
+#[derive(Clone)]
pub struct TimedMidiEvent
{
pub t: u32,
@@ -39,7 +41,7 @@ impl From<&MidiEvent> for RawMidiEvent
match e
{
MidiEvent::NoteOff{ch, key, vel}
- if *vel == 0x40 => RawMidiEvent{ty: 0x90 | ch, p1: *key, p2: 0, data:vec![]},
+ if *vel == 0x40 => RawMidiEvent{ty: 0x90 | ch, p1: *key, p2: 0, data: vec![]},
MidiEvent::NoteOff{ch, key, vel} => RawMidiEvent{ty: 0x80 | ch, p1: *key, p2: *vel, data: vec![]},
MidiEvent::NoteOn {ch, key, vel} => RawMidiEvent{ty: 0x90 | ch, p1: *key, p2: *vel, data: vec![]},
MidiEvent::KeyAfterTouch{ch, key, val} => RawMidiEvent{ty: 0xa0 | ch, p1: *key, p2: *val, data: vec![]},
@@ -64,12 +66,12 @@ impl From<&MidiEvent> for RawMidiEvent
RawMidiEvent{ty: 0xff, p1: 0x03, p2: s.len() as u8, data: Vec::from(sb)}
}
MidiEvent::MetaEndOfTrack =>
- RawMidiEvent{ty: 0xff, p1: 0x2f, p2: 0xff, data: vec![]}
+ RawMidiEvent{ty: 0xff, p1: 0x2f, p2: 0, data: vec![]}
}
}
}
-type MidiTrack = Vec<TimedMidiEvent>;
+pub type MidiTrack = Vec<TimedMidiEvent>;
pub struct MidiFile
{
@@ -77,19 +79,19 @@ pub struct MidiFile
pub tracks: Vec<MidiTrack>
}
-fn write_u16be(f: &mut File, v: u16) -> io::Result<()>
+fn write_u16be<W>(f: &mut W, v: u16) -> io::Result<()> where W: Write
{
let bytes = v.to_be_bytes();
f.write_all(&bytes)
}
-fn write_u32be(f: &mut File, v: u32) -> io::Result<()>
+fn write_u32be<W>(f: &mut W, v: u32) -> io::Result<()> where W: Write
{
let bytes = v.to_be_bytes();
f.write_all(&bytes)
}
-fn write_varlen(f: &mut File, v: u32) -> io::Result<()>
+fn write_varlen<W>(f: &mut W, v: u32) -> io::Result<()> where W: Write
{
if v > 0x0fffffff
{ return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid variable length value")); }
@@ -103,7 +105,7 @@ fn write_varlen(f: &mut File, v: u32) -> io::Result<()>
f.write_all(&buf[..])
}
-fn write_raw_event(f: &mut File, re: &RawMidiEvent) -> io::Result<()>
+fn write_raw_event<W>(f: &mut W, re: &RawMidiEvent) -> io::Result<()> where W: Write
{
let mut buf: Vec<u8> = Vec::new();
buf.push(re.ty);
@@ -113,23 +115,26 @@ fn write_raw_event(f: &mut File, re: &RawMidiEvent) -> io::Result<()>
f.write_all(&buf[..])
}
-fn write_track(f: &mut File, trk: &MidiTrack) -> io::Result<()>
+fn write_track<W>(f: &mut W, trk: &MidiTrack) -> io::Result<()> where W: Write
{
let header = "MTrk".as_bytes();
f.write_all(header)?;
+ let mut buf: Vec<u8> = Vec::new();
let mut curt = 0u32;
for te in trk
{
let TimedMidiEvent{t, e} = te;
- write_varlen(f, t - curt)?;
+ write_varlen(&mut buf, t - curt)?;
curt = *t;
let re = RawMidiEvent::from(e);
- write_raw_event(f, &re)?;
+ write_raw_event(&mut buf, &re)?;
}
+ write_u32be(f, buf.len() as u32)?;
+ f.write_all(&buf[..])?;
Ok(())
}
-fn write_file(filename: &str, mf: &MidiFile) -> io::Result<()>
+pub fn write_file(filename: &str, mf: &MidiFile) -> io::Result<()>
{
let mut f = File::create(filename)?;
let header = "MThd".as_bytes();