Wie kann ich eine Midi-Datei programmatisch aufteilen?

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?

Muss es in Python sein ...? Sie könnten einfach zu midi.mathewvp.com/midiTrim.htm gehen , die gesamte Midi-Datei hochladen, 0 bis 10 Sekunden eingeben und die gekürzte Version erneut herunterladen. Dies ist möglicherweise der schnellste Weg, aber Sie können dies auch in jeder DAW tun, wenn Sie möchten.

Antworten (2)

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");