public static MidiTrack CombineToSingleTrack(List<MidiTrack> tracks)
{
/* Add all notes into one track */
MidiTrack result = new MidiTrack(1);
if (tracks.Count == 0) {
return result;
}
else if (tracks.Count == 1) {
MidiTrack track = tracks[0];
foreach (MidiNote note in track.Notes) {
result.AddNote(note);
}
return result;
}
int[] noteindex = new int[64];
int[] notecount = new int[64];
for (int tracknum = 0; tracknum < tracks.Count; tracknum++) {
noteindex[tracknum] = 0;
notecount[tracknum] = tracks[tracknum].Notes.Count;
}
MidiNote prevnote = null;
while (true) {
MidiNote lowestnote = null;
int lowestTrack = -1;
for (int tracknum = 0; tracknum < tracks.Count; tracknum++) {
MidiTrack track = tracks[tracknum];
if (noteindex[tracknum] >= notecount[tracknum]) {
continue;
}
MidiNote note = track.Notes[ noteindex[tracknum] ];
if (lowestnote == null) {
lowestnote = note;
lowestTrack = tracknum;
}
else if (note.StartTime < lowestnote.StartTime) {
lowestnote = note;
lowestTrack = tracknum;
}
else if (note.StartTime == lowestnote.StartTime && note.Number < lowestnote.Number) {
lowestnote = note;
lowestTrack = tracknum;
}
}
if (lowestnote == null) {
/* We've finished the merge */
break;
}
noteindex[lowestTrack]++;
if ((prevnote != null) && (prevnote.StartTime == lowestnote.StartTime) &&
(prevnote.Number == lowestnote.Number) ) {
/* Don't add duplicate notes, with the same start time and number */
if (lowestnote.Duration > prevnote.Duration) {
prevnote.Duration = lowestnote.Duration;
}
}
else {
result.AddNote(lowestnote);
prevnote = lowestnote;
}
}
return result;
}