public void AddVenueTrack(MidiEventCollection midi) { var existingTrack = midi.FindTrackNumberByName(TrackName.Venue.ToString()); if (existingTrack != -1) { return; } midi.AddNamedTrack(TrackName.Venue.ToString()); }
public static MidiEventCollection ReorderTracks(MidiEventCollection midi) { var newMidi = new MidiEventCollection(midi.MidiFileType, midi.DeltaTicksPerQuarterNote); var tempoMapIndex = midi.FindTrackNumberByName(TrackName.TempoMap.ToString()); newMidi.AddTrack(midi[tempoMapIndex]); for (var t = 0; t < midi.Tracks; t++) { if (t != tempoMapIndex) { newMidi.AddTrack(midi[t]); } } return(newMidi); }
public void ProcessTimeSignatures(MidiEventCollection midi) { // This is way easier if these have already been consolidated ConsolidateTimeTracks(midi); var timeSigTrackNo = midi.FindTrackNumberByName(TrackName.InputTimeSig.ToString()); if (timeSigTrackNo == -1) { AddInfo($"No '{TrackName.InputTimeSig}' track"); return; } var timeEvents = midi[midi.FindTrackNumberByName(TrackName.TempoMap.ToString())]; var inputTimeSignatureEvents = midi[timeSigTrackNo].OfType <NoteOnEvent>(); var groups = inputTimeSignatureEvents.GroupBy(e => e.AbsoluteTime); var error = false; foreach (var pair in groups) { var time = pair.Key; // The higher velocity value is the numerator (top) // And the lower velocity value is the denominator (bottom) var sorted = pair.OrderByDescending(e => e.Velocity).ToArray(); if (sorted.Length != 2) { error = true; var detail = string.Join(", ", sorted.Select(e => $"<{e.NoteName} ({e.NoteNumber}), Velocity: {e.Velocity}>")); AddError($"Incorrect number of time signature notes at {GetBarInfo(midi, time)}: {detail}"); continue; } if (sorted[0].Velocity == sorted[1].Velocity) { error = true; var detail = string.Join(", ", sorted.Select(e => $"<{e.NoteName} ({e.NoteNumber}), Velocity: {e.Velocity}>")); AddError($"Multiple notes with the same velocity at {GetBarInfo(midi, time)}: {detail}"); continue; } var numerator = sorted[0].NoteNumber; int denominator; if (!TryConvertToDenominator(sorted[1].NoteNumber, out denominator)) { error = true; AddError($"Invalid denominator note '{sorted[1].NoteNumber}' at {time}"); continue; } var timeSigEvent = new TimeSignatureEvent(time, numerator, denominator, TicksInClick, NumberOfThirtySecondNotesInQuarterNote); var existingTimeSigEvent = timeEvents.OfType <TimeSignatureEvent>().SingleOrDefault(e => e.AbsoluteTime == time); if (existingTimeSigEvent != null) { timeEvents.Remove(existingTimeSigEvent); } timeEvents.Add(timeSigEvent); } if (error) { throw new InvalidOperationException("Invalid time signature input"); } // Clean up input track midi.RemoveTrack(timeSigTrackNo); UpdateTrackEnd(timeEvents, timeEvents.OrderBy(e => e.AbsoluteTime).Last().AbsoluteTime); // TODO: If there is no TimeSignatureEvent or TempoEvent at 0, wig out }