Skip to content

Commit

Permalink
convert more midi events
Browse files Browse the repository at this point in the history
  • Loading branch information
bates64 committed Apr 15, 2021
1 parent 510ffc7 commit 9cbabae
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 9 deletions.
7 changes: 5 additions & 2 deletions mamar/src/interface/state/track_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl TrackListInterface {
}

if self.is_edit_voice {
ui.modal(7, true, (600.0, 500.0), |ui| {
ui.modal(7, true, (600.0, 700.0), |ui| {
ui.text(0, format!("Voice of '{}'", track.name));
ui.pad(1, 20.0);

Expand Down Expand Up @@ -230,7 +230,10 @@ impl TrackListInterface {
}
});
range_select(ui, 6, 0..=255, 1, &mut voice.volume, |v| format!("Volume {}", v));
range_select(ui, 7, -128..127, 1, &mut voice.pan, |v| format!("Pan {}", v));
range_select(ui, 7, -128..=127, 1, &mut voice.pan, |v| {
let a = v.abs();
format!("Pan {} ({})", v, if a > 64 { "right" } else if a == 64 { "middle" } else { "left" })
});
range_select(ui, 8, 0..=255, 1, &mut voice.reverb, |v| format!("Reverb {}", v));
range_select(ui, 9, 0..=255, 1, &mut voice.coarse_tune, |v| format!("Coarse tune {}", v));
range_select(ui, 10, 0..=255, 1, &mut voice.fine_tune, |v| format!("Fine tune {}", v));
Expand Down
9 changes: 8 additions & 1 deletion pm64/src/bgm/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,11 @@ pub enum Command {
patch: u8,
},

SubTrackPan(u8), // TODO: better type for field
/// Left = (+/-)0.
/// Middle = (+/-)64.
/// Right = (+/-)127.
SubTrackPan(i8),

SubTrackReverb(u8),
SubTrackReverbType(u8), // TODO: enum for field

Expand All @@ -626,6 +630,9 @@ pub enum Command {
speed: u8,
unknown: u8,
},

// XXX: Angry_Bowser_67 doesn't have any TrackTremolo but does have TrackTremoloStop.
// It may reset SubTrackVolume also?
TrackTremoloStop,

// TODO: figure out whether Seg or Sub
Expand Down
2 changes: 1 addition & 1 deletion pm64/src/bgm/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ impl CommandSeq {
patch: f.read_u8()?,
},
0xE9 => Command::SubTrackVolume(f.read_u8()?),
0xEA => Command::SubTrackPan(f.read_u8()?),
0xEA => Command::SubTrackPan(f.read_i8()?),
0xEB => Command::SubTrackReverb(f.read_u8()?),
0xEC => Command::SegTrackVolume(f.read_u8()?),
0xED => Command::SubTrackCoarseTune(f.read_u8()?),
Expand Down
2 changes: 1 addition & 1 deletion pm64/src/bgm/en.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ impl CommandSeq {
}
Command::SubTrackPan(a) => {
f.write_u8(0xEA)?;
f.write_u8(*a)?;
f.write_i8(*a)?;
}
Command::SubTrackReverb(a) => {
f.write_u8(0xEB)?;
Expand Down
141 changes: 138 additions & 3 deletions pm64/src/bgm/midi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ fn midi_track_to_bgm_track(
format!("Track {}", track_number)
},

flags: track_flags::POLYPHONY_1 | track_flags::POLYPHONY_3,
flags: track_flags::POLYPHONY_1, // Sounds better with more polyphony, but can cause crashes

commands: CommandSeq::new(),
mute: false,
Expand Down Expand Up @@ -222,6 +222,12 @@ fn midi_track_to_bgm_track(
);
is_pitch_bent = true;
}
MidiMessage::Aftertouch { key: _, vel } | MidiMessage::ChannelAftertouch { vel } => {
track.commands.insert(
convert_time(time, time_divisor),
Command::SubTrackVolume(vel.as_int()),
);
}
MidiMessage::ProgramChange { program } => {
if !set_bank_patch {
voices[voice_idx].patch = program.as_int();
Expand All @@ -233,7 +239,126 @@ fn midi_track_to_bgm_track(
);
}
}
_ => {}
MidiMessage::Controller { controller, value } => {
let controller = controller.as_int();
let value = value.as_int(); // Note this is in the range 0..=127

// See page 12 of the specification:
// https://www.cs.cmu.edu/~music/cmsip/readings/Standard-MIDI-file-format-updated.pdf
// Or:
// https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2
match controller {
// Modulation wheel
1 | 33 => {
// Stack exchange says that the synthesizer (that's us!) gets to define
// what the modulation wheel does:
// https://music.stackexchange.com/questions/42847
//
// I declare it...tremolo!
track.commands.insert(
convert_time(time, time_divisor),
Command::TrackTremolo {
// XXX: These values are total guesses. Investigate!
amount: 8,
speed: value,
unknown: 8,
},
);
}
// Channel Volume
7 | 39 => track.commands.insert(
convert_time(time, time_divisor),
Command::SubTrackVolume(value),
),
// Pan
10 | 42 | 8 | 40 => track.commands.insert(
convert_time(time, time_divisor),
Command::SubTrackPan(value as i8),
),
// Effect control 1
12 | 44 => track.commands.insert(
convert_time(time, time_divisor),
Command::SubTrackReverb(value),
),
// Damper pedal on/off (sustain)
64 => {
let sustain = if value >= 64 {
// Sustain on
0
} else {
// Sustain off
3
};

track.commands.insert(
convert_time(time, time_divisor),
Command::TrackOverridePatch {
bank: voices[voice_idx].bank & 0xF0 | sustain,
patch: voices[voice_idx].bank,
},
);
}
// Sound Controller 3 (Release Time)
72 => {
// The lower nibble of the bank mod 3 is the 'staccatoness' (how short the
// notes are). The MIDI value for this event is the release time (sustain),
// change it to one of 4 levels:
let sustain = if value < (127 / 4) * 1 {
3 // Staccato
} else if value < (127 / 4) * 2 {
2 // Sustain even less
} else if value < (127 / 4) * 3 {
1 // Sustain less
} else {
0 // Default (sustain)
};

track.commands.insert(
convert_time(time, time_divisor),
Command::TrackOverridePatch {
bank: voices[voice_idx].bank & 0xF0 | sustain,
patch: voices[voice_idx].bank,
},
);
}
// All notes off / All sound off
123 | 120 => for (key, start) in started_notes.drain() {
let length = time - start.time;
track.commands.insert(
convert_time(start.time, time_divisor),
Command::Note {
pitch: key + 104,
velocity: start.vel,
length: convert_time(length as usize, time_divisor) as u16,
},
);
}
// Poly[phonic] mode on/off
126 => {
if value == 0 {
// Off
track.flags &= !(
track_flags::POLYPHONY_1 |
track_flags::POLYPHONY_2 |
track_flags::POLYPHONY_3);
} else {
// On
track.flags |=
track_flags::POLYPHONY_1 |
track_flags::POLYPHONY_2 |
track_flags::POLYPHONY_3;
}
}
// Poly[phonic] mode on
127 => {
track.flags |=
track_flags::POLYPHONY_1 |
track_flags::POLYPHONY_2 |
track_flags::POLYPHONY_3;
}
_ => {}
}
}
}
}
TrackEventKind::Meta(MetaMessage::Tempo(tempo)) => if track_number == 0 {
Expand All @@ -253,6 +378,15 @@ fn midi_track_to_bgm_track(
TrackEventKind::Meta(MetaMessage::TrackName(s)) => {
track_name = String::from_utf8(s.to_owned()).ok();
}
TrackEventKind::Meta(MetaMessage::CuePoint(s))
| TrackEventKind::Meta(MetaMessage::Marker(s)) => {
if let Ok(s) = String::from_utf8(s.to_owned()) {
track.commands.insert(
convert_time(time, time_divisor),
Command::Marker(s),
);
}
}
_ => {}
}
}
Expand Down Expand Up @@ -297,7 +431,8 @@ fn midi_track_to_bgm_track(

// There's not a very good way to detect MIDI drum tracks, so we'll just make a best guess by seeing if the
// designated track title contains 'drums' or not.
if track.name.to_lowercase().contains("drums") {
let name_lower = track.name.to_lowercase();
if name_lower.contains("drums") | name_lower.contains("percussion") {
// TODO: insert voice instead of drum
track.flags = track_flags::DRUM_TRACK;
}
Expand Down
13 changes: 12 additions & 1 deletion pm64/src/bgm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,12 @@ pub struct Drum {
pub coarse_tune: u8,
pub fine_tune: u8,
pub volume: u8,

/// Left = 0
/// Middle = 64
/// Right = 128
pub pan: i8,

pub reverb: u8,

#[serde(skip_serializing_if="is_default")]
Expand All @@ -184,11 +189,17 @@ pub struct Drum {
#[derive(Clone, Default, PartialEq, Eq, Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct Voice {
/// Upper nibble = bank. (0..=6 are valid?)
/// Lower nibble = staccatoness mod 3 (0 = sustain, 3 = staccato).
pub bank: u8,

pub patch: u8,
pub volume: u8,

/// Negative = left, positive = right. (?)
/// Values are just like in MIDI:
/// Left = 0.
/// Middle = (+/-)64.
/// Right = (+/-)127.
pub pan: i8,

pub reverb: u8,
Expand Down

0 comments on commit 9cbabae

Please sign in to comment.