Reading notes from MIDI file using NAudio

c#, midi, naudio

Solution

In MIDI files, a note has separate note-on and note-off events. NAudio already searches for the corresponding note-off event and calculates the length for you, so you don't need to handle note-off events yourself. (However, the tempo might change between the note-on and note-off events, so you have to compute the two times separately.)

These are descriptions of the values, not the actual field names. `tempo` is the `MicrosecondsPerQuarterNote` value of the last tempo event. `lastTempoEvent.RealTime` is the time (in microseconds) that you computed for the last tempo event.

The last tempo event is the tempo event with the largest absolute time that is still before this event's absolute time. That tempo event is likely to be in another track, so it might be a good idea to merge all tracks (set `midi.Events.MidiFileType` to zero) before handling the events.

Problem

Task is to get all notes and their time from MIDI file using NAudio library. So far I get all notes from file but I can't get their time. ``` Note noteOn = new Note(); //custom class Note MidiFile midi = new MidiFile(open.FileName); List<TempoEvent> tempo = new List<TempoEvent>(); for (int i = 0; i < midi.Events.Count(); i++) { foreach (MidiEvent note in midi.Events[i]) { TempoEvent tempoE; try { tempoE = (TempoEvent)note; tempo.Add(tempoE); } catch { } if (note.CommandCode == MidiCommandCode.NoteOn) { var t_note = ( NoteOnEvent)note; var noteOffEvent = t_note.OffEvent; noteOn.NoteName.Add(t_note.NoteName); noteOn.NoteNumber.Add(t_note.NoteNumber); noteOn.NoteVelocity.Add(t_note.Velocity); noteOn.NoteLenght.Add(t_note.NoteLength); double d = (t_note.AbsoluteTime / midi.DeltaTicksPerQuarterNote) * tempo[tempo.Count() - 1].Tempo; noteOn.StartTime.Add(TimeSpan.FromSeconds(d)); } } } ``` Questions: 1) To get just list of notes I just look in `NoteOnEvents` or not? If I understand this correctly, each note has 'start' and 'end', start is defined by `NoteOnEvent` and 'end' is defined by `NoteOffEvent`. If I look in both events (`NoteOn` and `NoteOff`) I would get duplicate notes. Am I right? 2) How to get note's time? According to this post , I get some values but it seems that the first note's time is correct, but others don't. Also in this post, there is a comment which says the formula for calculating time must be: ``` ((note.AbsTime - lastTempoEvent.AbsTime) / midi.ticksPerQuarterNote) * tempo + lastTempoEvent.RealTime. ``` I don't know parameters `lastTempoEvent.RealTime` and `tempo`. It's it tempo of last tempo event or? 3) Reading MIDI file it's very slow, for a smaller files it's ok, but for a big files don't. This small files have ~150 `NoteOnEvents` and this bigger files have ~1250 `NoteOnEvents`, which isn't so 'heavy'. Why is so slow?

Original source

Related problems