Ich verwende die Mido-Bibliothek auf Python, um mit der Midi-Datei zu arbeiten.
Bei einer beliebigen Midi-Datei möchte ich eine Midi-Datei ausgeben, die nur aus den ersten 10 Sekunden der Eingabe besteht. Ich sehe keine Funktionen, um dies in der Bibliothek zu tun, also versuche ich, dies zu tun, indem ich jeden der Tracks durchgehe.
Ich finde ein paar Dinge verwirrend. Unten sehen Sie beispielsweise, was Sie erhalten, wenn Sie eine einzelne Spur in Ihrem Midi-Objekt untersuchen.
<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
Gehe ich also diese Liste von Nachrichten in der Spur durch und zähle das Zeitattribut, bis die laufende Summe 10000 (Millisekunden) überschreitet? Ich glaube nicht, denn wenn man sich das Stück auf Musescore ansieht, passiert nach 15,36 Sekunden nichts Bedeutendes.
Ich habe hier gelesen , dass die Zeiten nicht in Millisekunden sind, sondern Delta-Zeiten, die durch PPQ (Pulses per Quarter Note) in Millisekunden umgerechnet werden müssen. Ist dies richtig, und wenn ja, ist die Verwendung einer laufenden Zeitsumme der richtige Ansatz, um ein Ausgabe-Midi mit einer Zeit von 10 Sekunden zu erstellen?
Die Zeiten sind nicht in Millisekunden, sondern in Midi-Ticks, die Sie mit der Funktion in Sekunden umwandeln können tick2second(ticks, ticks_per_beat, tempo)
. Ihr Code sollte in etwa so aussehen:
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
Hinweis: Dies setzt voraus, dass es in den ersten 10 Sekunden Ihrer Eingabedateien keine Tempoänderungen gibt. Wenn ja, muss Ihr Code komplexer sein.
Wenn Sie mit C# anstelle von Python einverstanden sind, können Sie die DryWetMIDI- Bibliothek verwenden. Der Code für die ersten 10 Sekunden einer MIDI-Datei ist super einfach:
var midiFile = MidiFile.Read("My MIDI file.mid");
var newMidiFile = midiFile.TakePart(new MetricTimeSpan(0, 0, 10));
newMidiFile.Write("10sec version.mid");
Dein Onkel Bob
Andy