// util functions private static bool TrackIsOmitable(MidiTrack tr) { foreach (MidiEvent ev in tr.midiEvents) { if (ev is MetaMidiEvent) { MetaMidiEvent mev = ev as MetaMidiEvent; if (mev.getMetaType() == MetaType.TempoSetting) { return(false); } else if (mev.getMetaType() == MetaType.TimeSignature) { return(false); } else if (mev.getMetaType() == MetaType.MarkerText) { return(false); } } else if (ev is MessageMidiEvent) { MessageMidiEvent mev = ev as MessageMidiEvent; if (mev.type == NormalType.NoteON) { return(false); } if (mev.type == NormalType.NoteOFF) { return(false); } } } return(true); }
public static void QuantizeTempo(MidiFile midi) { /****************** * Rounds Tempo Events to the nearest BPM integer */ foreach (MidiTrack trk in midi.midiTracks) { for (int i = 0; i < trk.midiEvents.Count; i++) { MidiEvent ev = trk.midiEvents[i]; if (ev is MetaMidiEvent) { MetaMidiEvent mev = ev as MetaMidiEvent; if (mev.getMetaType() == MetaType.TempoSetting) { byte[] tempoBytes = mev.getEventData(); Debug.Assert(tempoBytes.Length == 6); int us = (tempoBytes[3] << 16) | (tempoBytes[4] << 8) | tempoBytes[5]; double bpm = CalcBPM(us); double ibpm = Math.Round(bpm, MidpointRounding.AwayFromZero); int ius = CalcUsPerBeat(ibpm); byte[] newTempoBytes = new byte[3]; newTempoBytes[0] = (byte)(ius >> 16); newTempoBytes[1] = (byte)((ius >> 8) & 0xFF); newTempoBytes[2] = (byte)(ius & 0xFF); MetaMidiEvent newTempoEvent = new MetaMidiEvent(mev.absoluteTicks, 0x51, newTempoBytes); trk.midiEvents[i] = newTempoEvent; } } } } }
public static void Trim(MidiFile midi) { /****************** * removes empty tracks and redundant controller/voice events */ midi.midiTracks.RemoveAll(TrackIsOmitable); foreach (MidiTrack tr in midi.midiTracks) { // int array for storing the last set values of the controller values int[] controllerValues = new int[128]; for (int i = 0; i < controllerValues.Length; i++) { controllerValues[i] = -1; } int lastVoice = -1; int lastPitchBendA = -1; int lastPitchBendB = -1; int lastTempo = -1; for (int i = 0; i < tr.midiEvents.Count;) { if (tr.midiEvents[i] is MessageMidiEvent) { MessageMidiEvent mev = tr.midiEvents[i] as MessageMidiEvent; if (mev.type == NormalType.Program) { if (mev.parameter1 == lastVoice) { tr.midiEvents.RemoveAt(i); continue; } lastVoice = mev.parameter1; } else if (mev.type == NormalType.PitchBend) { if (mev.parameter1 == lastPitchBendA && mev.parameter2 == lastPitchBendB) { tr.midiEvents.RemoveAt(i); continue; } lastPitchBendA = mev.parameter1; lastPitchBendB = mev.parameter2; } else if (mev.type == NormalType.Controller) { if (controllerValues[mev.parameter1] == mev.parameter2) { tr.midiEvents.RemoveAt(i); continue; } controllerValues[mev.parameter1] = mev.parameter2; } } else if (tr.midiEvents[i] is MetaMidiEvent) { MetaMidiEvent mev = tr.midiEvents[i] as MetaMidiEvent; if (mev.getMetaType() == MetaType.TempoSetting) { byte[] tempoBytes = mev.getEventData(); Debug.Assert(tempoBytes.Length == 6); int us = (tempoBytes[3] << 16) | (tempoBytes[4] << 8) | tempoBytes[5]; if (lastTempo == us) { tr.midiEvents.RemoveAt(i); continue; } lastTempo = us; } } // only count up if the current event didn't get deleted i++; } } }