Задача состоит в том, чтобы получить все ноты и их время из файла MIDI, используя библиотеку NAudio. Пока я получаю все заметки из файла, но не могу получить их время.
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));
}
}
}
Вопросы:
1) Чтобы получить только список заметок, я просто смотрю в NoteOnEvents
или нет? Если я правильно понимаю, у каждой ноты есть «начало» и «конец», начало определяется NoteOnEvent
, а «конец» определяется NoteOffEvent
. Если я загляну в оба события (NoteOn
и NoteOff
), я получу повторяющиеся заметки. Я прав?
2) Как узнать время заметки? Согласно этому сообщению, я получаю некоторые значения, но кажется, что время первой заметки правильное, а другие нет. Также в этом посте есть комментарий, в котором говорится, что формула для расчета времени должна быть:
((note.AbsTime - lastTempoEvent.AbsTime) / midi.ticksPerQuarterNote) * tempo + lastTempoEvent.RealTime.
Параметры lastTempoEvent.RealTime
и tempo
мне неизвестны. Это темп последнего темпового события или?
3) Чтение MIDI-файла очень медленное, для небольших файлов нормально, а для больших нет. В этих маленьких файлах ~150 NoteOnEvents
, а в больших файлах ~1250 NoteOnEvents
, что не так уж «тяжело». Почему так медленно?