Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading notes from MIDI file using NAudio

Tags:

c#

midi

naudio

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?

like image 883
skomi Avatar asked Nov 02 '25 07:11

skomi


1 Answers

  1. 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.)

  2. 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.

like image 175
CL. Avatar answered Nov 03 '25 23:11

CL.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!