Я использую библиотеку mido на python для работы с файлом midi.
Учитывая любой миди-файл, я хотел бы вывести миди-файл, состоящий только из первых 10 секунд ввода. Я не вижу никаких функций для этого в библиотеке, поэтому я пытаюсь сделать это, просматривая каждый из треков.
Я нахожу несколько вещей запутанными. Например, ниже показано, что вы получите, изучив один трек в своем миди-объекте.
<meta message track_name name='Slow Strings' time=0>
program_change channel=0 program=49 time=0
program_change channel=0 program=49 time=0
control_change channel=0 control=7 value=71 time=0
control_change channel=0 control=10 value=75 time=0
note_on channel=0 note=55 velocity=89 time=15360
note_on channel=0 note=59 velocity=95 time=0
note_on channel=0 note=62 velocity=92 time=0
note_off channel=0 note=55 velocity=64 time=1324
note_off channel=0 note=62 velocity=64 time=12
Итак, я просматриваю этот список сообщений в дорожке и подсчитываю атрибут времени до тех пор, пока текущая сумма не превысит 10000 (миллисекунд)? Я так не думаю, потому что, глядя на кусок на musescore, ничего существенного не происходит через 15,36 секунды после начала песни.
Я прочитал здесь , что время указано не в миллисекундах, а в дельта-времени, которое необходимо преобразовать в миллисекунды через PPQ (импульсы на четверть). Правильно ли это, и если да, то является ли использование текущей суммы времени правильным подходом к созданию выходного миди продолжительностью 10 секунд?
Время указано не в миллисекундах, а в миди-тиках, которые вы можете преобразовать в секунды с помощью функции tick2second(ticks, ticks_per_beat, tempo)
. Ваш код должен выглядеть примерно так:
from mido import MidiFile
from mido import tick2second
mid = MidiFile('input.mid')
for i, track in enumerate(mid.tracks):
total_time = 0
for msg in track:
if msg.type == 'set_tempo':
tempo = msg.tempo
total_time += tick2second(msg.time, mid.ticks_per_beat, tempo)
print(msg, total_time) # or copy to output file
if total_time > 10:
break
Примечание: это предполагает отсутствие изменений темпа в течение первых 10 секунд ваших входных файлов. Если есть, ваш код должен быть более сложным.
Если вы согласны с C# вместо Python, вы можете использовать библиотеку DryWetMIDI . Код для первых 10 секунд MIDI-файла очень прост:
var midiFile = MidiFile.Read("My MIDI file.mid");
var newMidiFile = midiFile.TakePart(new MetricTimeSpan(0, 0, 10));
newMidiFile.Write("10sec version.mid");
Твой дядя Боб
Энди