diff options
Diffstat (limited to 'src/convert.rs')
-rw-r--r-- | src/convert.rs | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/src/convert.rs b/src/convert.rs index a683772..56ab4f7 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -3,7 +3,7 @@ use std::cell::RefCell; use std::rc::Rc; use crate::itfile::{ITFile, Cell}; use crate::utils::Rational; -use crate::midifile::{MidiEvent, TimedMidiEvent, MidiTrack, MidiFile}; +use crate::midifile::{MidiEvent, TimedMidiEvent, MidiTrack, MidiFile, lint_track}; use crate::portmod::Effect; #[derive(Debug)] @@ -25,7 +25,7 @@ struct PlayerState } type CellHandlerFn<'a> = dyn 'a + FnMut(u8, Cell, PlayerState) -> PlayerState; -type EfxHandlerFn<'a> = dyn 'a + FnMut(u8, Cell, Rc<RefCell<ChannelMemory>>, PlayerState, Rational) -> Vec<(TimedMidiEvent, bool)>; +type EfxHandlerFn<'a> = dyn 'a + FnMut(u8, Cell, Rc<RefCell<ChannelMemory>>, PlayerState, Rational) -> Vec<(TimedMidiEvent, (u8, u8))>; struct Player<'a, 'b> { @@ -33,17 +33,33 @@ struct Player<'a, 'b> it: &'a ITFile } -#[derive(Default)] struct ChannelMemory { note: u8, postnote: u8, inst: u8, + postinst: u8, vol: u8, efxmem: [u8; 32], pitch: Rational } +impl Default for ChannelMemory +{ + fn default() -> ChannelMemory + { + ChannelMemory { + note: 0xff, + postnote: 0xff, + inst: 0xff, + postinst: 0xff, + vol: 0, + efxmem: Default::default(), + pitch: 0u32.into() + } + } +} + pub struct Converter<'a> { miditick: Rational, @@ -206,15 +222,19 @@ impl<'a> Converter<'a> let nonfx = |ch: u8, cell, chmem: Rc<RefCell<ChannelMemory>>, ps: PlayerState, t: Rational| { if !ch == 0 { return Vec::new(); } let mut ret = Vec::new(); - let Cell { mask, note, .. } = cell; + let Cell { mask, note, mut inst, .. } = cell; if mask & 0x11 != 0 && ps.current_tick == 0 { + if mask & 0x22 == 0 + { + inst = chmem.borrow().postinst; + } match note { 0x78..=0xff => if chmem.borrow().postnote != 0xff { - ret.push((TimedMidiEvent{t: t.as_int_trunc() as u32, e: MidiEvent::NoteOff{ch: 0, key: chmem.borrow().postnote, vel: 0x40}}, false)); + ret.push((TimedMidiEvent{t: t.as_int_trunc() as u32, e: MidiEvent::NoteOff{ch: 0, key: chmem.borrow().postnote, vel: 0x40}}, (ch, inst))); chmem.borrow_mut().postnote = 0xff; }, 0 => (), @@ -222,10 +242,11 @@ impl<'a> Converter<'a> { if chmem.borrow().postnote != 0xff { - ret.push((TimedMidiEvent{t: t.as_int_trunc() as u32, e: MidiEvent::NoteOff{ch: 0, key: chmem.borrow().postnote, vel: 0x40}}, false)); + ret.push((TimedMidiEvent{t: t.as_int_trunc() as u32, e: MidiEvent::NoteOff{ch: 0, key: chmem.borrow().postnote, vel: 0x40}}, (ch, chmem.borrow().postinst))); } - ret.push((TimedMidiEvent{t: t.as_int_trunc() as u32, e: MidiEvent::NoteOn{ch: 0, key: note, vel: 0x40}}, false)); + ret.push((TimedMidiEvent{t: t.as_int_trunc() as u32, e: MidiEvent::NoteOn{ch: 0, key: note, vel: 0x40}}, (ch, inst))); chmem.borrow_mut().postnote = note; + chmem.borrow_mut().postinst = inst; } } } @@ -269,7 +290,7 @@ impl<'a> Converter<'a> self.trks[0].push(TimedMidiEvent{ t: 0, e: MidiEvent::MetaTempo(inittpo * 24. / rpb / initspd)}); for ((ch, inst), trkn) in instch.iter() { - let tn = format!("instr #{} @ ch{}", *inst, *ch); + let tn = format!("{} (instr #{}) @ ch{}", it.insts[(inst - 1) as usize].inst_name() , *inst, *ch); self.trks[*trkn].push(TimedMidiEvent{ t:0, e: MidiEvent::MetaTrackName(tn) }); } @@ -287,9 +308,9 @@ impl<'a> Converter<'a> |h| { let ev = (h.borrow_mut())(ch, cell, self.chmem[ch as usize].clone(), ps.clone(), self.miditick); ev.iter().for_each( - |(e, is_common)| { - let target_track = instch.get(&(ch, self.chmem[ch as usize].borrow().inst)).unwrap(); - (if *is_common { &mut self.trks[0] } else { &mut self.trks[*target_track] }).push(e.clone()); + |(e, (ch, inst))| { + let target_track = instch.get(&(*ch, *inst)).unwrap_or(&0); + self.trks[*target_track].push(e.clone()); } ); }); @@ -302,6 +323,8 @@ impl<'a> Converter<'a> self.trks.iter_mut().for_each(|t| t.push(TimedMidiEvent{ t: t.last().unwrap_or(&TimedMidiEvent{t: 0, e: MidiEvent::MetaEndOfTrack}).t, e: MidiEvent::MetaEndOfTrack})); + + self.trks.iter().for_each(|t| { lint_track(t); }); } pub fn result(self) -> MidiFile { |