/** Create a MidiTrack based on the Midi events. Extract the NoteOn/NoteOff * events to gather the list of MidiNotes. */ public MidiTrack(List <MidiEvent> events, int tracknum) { int lyriccount; this.tracknum = tracknum; notes = new List <MidiNote>(events.Count); instrument = 0; foreach (MidiEvent mevent in events) { if (mevent.EventFlag == MUtil.EventNoteOn && mevent.Volume > 0) { MidiNote note = new MidiNote(mevent.StartTime, mevent.Channel, mevent.Notenumber, mevent.Volume, 0); AddNote(note); } else if (mevent.EventFlag == MUtil.EventNoteOn && mevent.Volume == 0) { NoteOff(mevent.Channel, mevent.Notenumber, mevent.StartTime); mevent.EventFlag = (byte)(128 + mevent.Channel); //mevent.Text = MidiFile.EventName(mevent.EventFlag); } else if (mevent.EventFlag == (MUtil.EventNoteOff)) { NoteOff(mevent.Channel, mevent.Notenumber, mevent.StartTime); //mevent.EventFlag = (byte)(127 + mevent.Channel); //mevent.Text = MidiFile.EventName(mevent.EventFlag); } else if (mevent.EventFlag == MUtil.EventProgramChange) { instrument = mevent.Instrument; } else if (mevent.MetaEvent == MUtil.MetaEventLyric) { if (lyrics == null) { lyrics = new List <MidiEvent>(); } lyrics.Add(mevent); } } if (notes.Count > 0 && notes[0].Channel == 9) { instrument = 128; /* Percussion */ } lyriccount = 0; if (lyrics != null) { lyriccount = lyrics.Count; } }
/** We want note durations to span up to the next note in general. * The sheet music looks nicer that way. In contrast, sheet music * with lots of 16th/32nd notes separated by small rests doesn't * look as nice. Having nice looking sheet music is more important * than faithfully representing the Midi File data. * * Therefore, this function rounds the duration of MidiNotes up to * the next note where possible. */ public static void RoundDurations(MidiFile midiFile) { List <MidiTrack> tracks; int quarterNote; tracks = midiFile.Tracks; quarterNote = midiFile.QuarterNote; foreach (MidiTrack track in tracks) { MidiNote prevNote = null; for (int i = 0; i < track.Notes.Count - 1; i++) { MidiNote note1 = track.Notes[i]; if (prevNote == null) { prevNote = note1; } /* Get the next note that has a different start time */ MidiNote note2 = note1; for (int j = i + 1; j < track.Notes.Count; j++) { note2 = track.Notes[j]; if (note1.StartTime < note2.StartTime) { break; } } int maxduration = note2.StartTime - note1.StartTime; int dur = 0; if (quarterNote <= maxduration) { dur = quarterNote; } else if (quarterNote / 2 <= maxduration) { dur = quarterNote / 2; } else if (quarterNote / 3 <= maxduration) { dur = quarterNote / 3; } else if (quarterNote / 4 <= maxduration) { dur = quarterNote / 4; } if (dur < note1.Length) { dur = note1.Length; } /* Special case: If the previous note's duration * matches this note's duration, we can make a notepair. * So don't expand the duration in that case. */ if ((prevNote.StartTime + prevNote.Length == note1.StartTime) && (prevNote.Length == note1.Length)) { dur = note1.Length; } note1.Length = dur; if (track.Notes[i + 1].StartTime != note1.StartTime) { prevNote = note1; } } } }
/** Add a MidiNote to this track. This is called for each NoteOn event */ public void AddNote(MidiNote m) { notes.Add(m); }