Reading notes from MIDI file using NAudio

◇◆丶佛笑我妖孽 提交于 2019-11-27 06:24:43

问题


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?


回答1:


  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.




回答2:


You can take a look at other .NET libraries that provide MIDI file parsing. For example, with DryWetMIDI you can get all notes contained in a MIDI file with this code:

MidiFile file = MidiFile.Read("Great Song.mid");
IEnumerable<Note> notes = file.GetNotes();

Note has Time and Length properties. Units of values returned by these properties defined by the time division of a MIDI file. But you can get time and length of a note in more understandable format. For hours, minutes, seconds you can write:

TempoMap tempoMap = file.GetTempoMap();
MetricTimeSpan metricTime = note.TimeAs<MetricTimeSpan>(tempoMap);
MetricTimeSpan metricLength = note.LengthAs<MetricTimeSpan>(tempoMap);

Using TimeAs and LengthAs methods you don't need to do any calculations by yourself. Instance of MetricTimeSpan can be implicitly casted to TimeSpan.



来源:https://stackoverflow.com/questions/23888692/reading-notes-from-midi-file-using-naudio

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!