public static bool IsInSameMeasure(MIDIEventHelper a, MIDIEventHelper b) { int measure_a = Mathf.FloorToInt(a.TimeMeasures); int measure_b = Mathf.FloorToInt(b.TimeMeasures); return(measure_a == measure_b); }
public bool GetEvent(int index, out MIDIEventHelper @event) { bool result = index >= 0 && index < _Events.Count; if (result) { @event = _Events[index]; } else { @event = null; } return(result); }
public MIDIEventList(MidiData midi_data, TrackChunk track, MIDIEventFilter filter) { // TODO: get beats per measure by reading all // Midi.Events.MetaEvents.TimeSignatureEvents // along with the notes in the track (i.e. // time signature changes, etc.) float beats_per_measure = 4f; // Calculate the time scale as the reciprocal // of the MIDI time_division // time_division is also known as PPQ // https://en.wikipedia.org/wiki/Pulses_per_quarter_note float time_beats_scale = 1f / midi_data.header.time_division; float time_beats_to_measures_scale = 1f / beats_per_measure; // Instatiate the event list pEvents = new List <MIDIEventHelper>(); // Starting from time zero float time_beats = 0f; float time_measures = 0f; // Keep track of the last note-on events and // match them with note-off events that follow, // then store the time between the events as // the duration in the event helper MIDIEventHelper[] notes_on_last = new MIDIEventHelper[256]; // Keep track of the valid event index int index = 0; // Add all of the events needed for this track to the backing list (pEvents) MIDIEventHelper previous_helper = null; var track_filtered = track.events.Where(MIDIEventListFilter); foreach (var midi_event in track_filtered) { if (filter.Accepts(midi_event)) { // Calculate the event time based on delta_time // delta_time is measured in ticks float delta_time = (float)midi_event.delta_time; time_beats += time_beats_scale * delta_time; // Quantize to 32nd notes time_beats = Quantize(time_beats, 32); time_measures += time_beats_to_measures_scale * time_beats; // Create an event helper (wrapper for event and details) MIDIEventHelper current_event_helper = new MIDIEventHelper() { MIDIEvent = midi_event, Index = index, TimeBeats = time_beats, TimeMeasures = time_measures, DurationBeats = 0f, }; // Add the event helper to the backing list pEvents.Add(current_event_helper); // If this event is a note off event if (midi_event is NoteOffEvent) { var note_off = midi_event as NoteOffEvent; int number = note_off.note_number; var on_event_helper = notes_on_last[number]; if (on_event_helper != null) { float duration = time_beats - on_event_helper.TimeBeats; on_event_helper.DurationBeats = duration; current_event_helper.DurationBeats = duration; } // The note off event is not accounted for when consolidating } // If this event is a note on event else if (midi_event is NoteOnEvent) { // Store it as the last note-on event for this note number var note_on = midi_event as NoteOnEvent; int number = note_on.note_number; notes_on_last[number] = current_event_helper; } index++; previous_helper = current_event_helper; } else if (MIDIEventFilter.TrackNameFilter.Accepts(midi_event)) { Name = track.chunk_ID ?? ""; // TODO: get this working //var name = (m_e.Element as Midi.Events.MetaEvents.SequenceOrTrackNameEvent).name; // Small workaround for bug in MIDI parsing library //Name = name.Trim(new[] {'\0'}); } } }