aboutsummaryrefslogtreecommitdiff
path: root/src/convert.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/convert.rs')
-rw-r--r--src/convert.rs45
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
{