Конвертировать MIDI-файл в список нот с продолжительностью и временем начала
Я работаю над игрой в Unity, которая будет генерировать уровни из музыки. Я планирую включить в игру простые текстовые файлы (которые не обязательно должны быть в стандартном формате) и проанализировать их для создания уровней. Проблема в том, что мне нужно иметь возможность конвертировать MIDI-файлы в текстовый формат (желательно не такой сложный, как MusicXML). Текстовые файлы, которые я включу в игру, в идеале должны состоять из списка заметок, каждая из которых имеет длину и время начала (в произвольных единицах времени). Я не могу просто включить музыкальный файл, так как моя игра с пулей-адом должна точно подсчитывать маркеры с примечаниями.
Мне все равно, на каком языке программирования это происходит, так как этот код не будет включен в игру. Кроме того, я никогда не работал с MIDI прежде в любой форме. Я счастлив использовать любую библиотеку и / или бесплатную программу для этого.
Заранее спасибо за вашу помощь!
1 ответ
Вы можете использовать любую библиотеку с открытым исходным кодом для анализа файла MIDI и преобразования его данных в текстовый файл в нужном формате. Например, с DryWetMIDI вы можете использовать этот код:
public static void ConvertMidiToText(string midiFilePath, string textFilePath)
{
var midiFile = MidiFile.Read(midiFilePath);
File.WriteAllLines(textFilePath,
midiFile.GetNotes()
.Select(n => $"{n.NoteNumber} {n.Time} {n.Length}"));
}
ConvertMidiToText
Метод выдаст текстовые файлы, подобные этому:
37 0 480
37 960 480
37 1920 480
37 2400 480
70 2640 192
где первый номер - номер ноты (60 = C4), второй - время начала в тиках MIDI, а третий - длина в тиках MIDI.
Вы даже можете написать время и длину в формате часы: минуты: секунды. Этот код
public static void ConvertMidiToText(string midiFilePath, string textFilePath)
{
var midiFile = MidiFile.Read(midiFilePath);
TempoMap tempoMap = midiFile.GetTempoMap();
File.WriteAllLines(textFilePath,
midiFile.GetNotes()
.Select(n => $"{n.NoteNumber} {n.TimeAs<MetricTimeSpan>(tempoMap)} {n.LengthAs<MetricTimeSpan>(tempoMap)}"));
}
будет выдавать текст так:
37 00:00:00 00:00:00.4800000
37 00:00:00.9600000 00:00:00.4800000
37 00:00:01.9200000 00:00:00.4800000
37 00:00:02.4000000 00:00:00.4800000
70 00:00:02.6400000 00:00:00.1920000