Trimming Silence from a MIDI file

I recently wrote about recording an Android piano keyboard app’s output to a MIDI file here. I shared a slight annoyance I encountered – the inevitable noticeable delay between hitting the record button and the actual start of the music. The result? A MIDI file with an unwelcome silence before any notes are played. Notes are often less boring to listen to, so it’d be nice to skip this silence.

Turns out the naive solution for single-track MIDI files is incredibly simple! With a solid 5 minutes of reading the MIDI file specifications, I discovered a straightforward fix for single-track MIDI files. I stumbled upon Midly, a Rust library that describes itself as a “feature-complete MIDI decoder and encoder designed for efficiency and ease of use.” With a change of a single byte in the file, we can remove all the silence preceding the first note.

The code

To remove all the silence preceding the first note in a MIDI file, find the first note and changes it’s delta from whatever non-0 value it is to 0. The guts of the (tiny amount of) code look like:

let mut smf = Smf::parse(&buffer)?;
let track = smf.tracks.first_mut().unwrap();
let first_note = track.iter().position(|event| {
if let TrackEventKind::Midi {
message: MidiMessage::NoteOn { .. },
..
} = &event.kind
{
return true;
}
false
});

let mut empty_track = Vec::new();

let trimmed_track = match first_note {
Some(index) => {
track[index].delta = 0.into();
track
}
None => {
&mut empty_track
}
};

let trimmed_smf = Smf {
header: smf.header,
tracks: vec![trimmed_track.to_vec()],
};

As a bit of a noob, I’m not 100% sold on “if let” statements in Rust, but otherwise this code is super straightforward. Find the first note, set its “delta” (time from the previous note) to 0, write the file back out.

I’ve uploaded the code here, so you can give it a whirl and eliminate the silence in your own recordings. Feel free to share your experiences or suggest improvements.

Open questions…

This also suggests some straightforward-ish answers to a few of the previous open questions I had. For example, how can I automatically split MIDI files into songs? Look for large delta values and slice the file there!

Leave a comment