通过 Python 在 Midi 的特定时间写笔记
Write Note at specific time in Midi via Python
我想将一系列音符(由时间、持续时间、音高定义)转换为音频文件。为此,我认为首先创建一个 midi 然后将其编译为 wav 是可行的方法。
我对音频处理和 MIDI 文件还很陌生,所以即使我阅读了几个教程,也可能是我没有理解要点。
编辑:我发现了问题,请参阅下面的解决方案。
有什么问题
通过 python 的 MIDIUtil
在特定时间以特定持续时间写笔记无法按预期工作。事实上,放置音符的时间(以秒为单位)在很大程度上取决于曲目的 bpm,尽管我认为在将音符时间转换为四分音符的 MIDI 时间度量时我考虑了 bpm。
我试过的
我正在创建具有给定 bpm 的 MIDI 曲目。
然后我通过转换笔记的事件时间
t_{quarter} = t_{seconds} * bpm/60
例子
我正在用下面的代码写两个音符,最后一个在 t=5 秒,持续时间为 1s;即我期待一个持续 6 秒的 midi 文件。但是在 bpm=600 时,文件长 14 秒。在 bpm=100 时,它几乎是预期的 6s。
这是我的代码
from midiutil import MIDIFile
def convert_seconds_to_quarter(time_in_sec, bpm):
quarter_per_second = (bpm/60)
time_in_quarter = time_in_sec * quarter_per_second
return time_in_quarter
def write_test_midi():
bpm = 600
MyMIDI = MIDIFile(1)
MyMIDI.addTrackName(track=0, time=0, trackName="Sample Track")
MyMIDI.addTempo(track=0, time=0, tempo=bpm)
MyMIDI.addNote(track=0, channel=0, pitch=60,
time=convert_seconds_to_quarter(1, bpm),
duration=convert_seconds_to_quarter(1, bpm), volume=100)
MyMIDI.addNote(track=0, channel=0, pitch=60,
time=convert_seconds_to_quarter(5, bpm),
duration=convert_seconds_to_quarter(1, bpm), volume=100)
with open("/tmp/output.mid", 'wb') as binfile:
MyMIDI.writeFile(binfile)
附加信息
带bpm=100
的文件的十六进制内容:
ADDRESS 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ASCII
00000010 4d 54 68 64 00 00 00 06 00 01 00 02 03 c0 4d 54 MThd..........MT
00000020 72 6b 00 00 00 0b 00 ff 51 03 09 27 c0 00 ff 2f rk......Q..'.../
00000030 00 4d 54 72 6b 00 00 00 28 00 ff 03 0c 53 61 6d .MTrk...(....Sam
00000040 70 6c 65 20 54 72 61 63 6b 8c 40 90 3c 64 8c 40 ple.Track.@.<d.@
00000050 80 3c 64 a5 40 90 3c 64 8c 40 80 3c 64 00 ff 2f .<d.@.<d.@.<d../
00000060 00 00 00 00 .
bpm=600
的文件内容:
ADDRESS 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ASCII
00000010 4d 54 68 64 00 00 00 06 00 01 00 02 03 c0 4d 54 MThd..........MT
00000020 72 6b 00 00 00 0b 00 ff 51 03 01 86 a0 00 ff 2f rk......Q....../
00000030 00 4d 54 72 6b 00 00 00 29 00 ff 03 0c 53 61 6d .MTrk...)....Sam
00000040 70 6c 65 20 54 72 61 63 6b cb 00 90 3c 64 cb 00 ple.Track...<d..
00000050 80 3c 64 81 e1 00 90 3c 64 cb 00 80 3c 64 00 ff .<d....<d...<d..
00000060 2f 00 00 00 /.
解决方案
我贴的代码、转换函数和文件都是正确的。问题出在我用来听 midi 的 VLC 播放器上。
第一个文件:
delta message absolute time
time ticks seconds
... 03 c0 ... 960 ticks per quarter note
... ff 51 03 09 27 c0 0 0 tempo: 600000 microseconds per quarter note
8c 40 90 3c 64 1600 1 note on
8c 40 80 3c 64 3200 2 note off
a5 40 90 3c 64 8000 5 note on
8c 40 80 3c 64 9600 6 note off
00 ff 2f 00 9600 6 end of track
第二个文件:
... 03 c0 ... 960 ticks per quarter note
... ff 51 03 01 86 a0 0 0 tempo: 100000 microseconds per quarter note
cb 00 90 3c 64 9600 1 note on
cb 00 80 3c 64 19200 2 note off
81 e1 00 90 3c 64 48000 5 note on
cb 00 80 3c 64 57600 6 note off
00 ff 2f 00 57600 6 end of track
两个文件的长度都正好是六秒。您的代码和文件都是正确的。
问题在于您使用什么工具来处理文件。
我想将一系列音符(由时间、持续时间、音高定义)转换为音频文件。为此,我认为首先创建一个 midi 然后将其编译为 wav 是可行的方法。
我对音频处理和 MIDI 文件还很陌生,所以即使我阅读了几个教程,也可能是我没有理解要点。
编辑:我发现了问题,请参阅下面的解决方案。
有什么问题
通过 python 的 MIDIUtil
在特定时间以特定持续时间写笔记无法按预期工作。事实上,放置音符的时间(以秒为单位)在很大程度上取决于曲目的 bpm,尽管我认为在将音符时间转换为四分音符的 MIDI 时间度量时我考虑了 bpm。
我试过的
我正在创建具有给定 bpm 的 MIDI 曲目。
然后我通过转换笔记的事件时间
t_{quarter} = t_{seconds} * bpm/60
例子
我正在用下面的代码写两个音符,最后一个在 t=5 秒,持续时间为 1s;即我期待一个持续 6 秒的 midi 文件。但是在 bpm=600 时,文件长 14 秒。在 bpm=100 时,它几乎是预期的 6s。
这是我的代码
from midiutil import MIDIFile
def convert_seconds_to_quarter(time_in_sec, bpm):
quarter_per_second = (bpm/60)
time_in_quarter = time_in_sec * quarter_per_second
return time_in_quarter
def write_test_midi():
bpm = 600
MyMIDI = MIDIFile(1)
MyMIDI.addTrackName(track=0, time=0, trackName="Sample Track")
MyMIDI.addTempo(track=0, time=0, tempo=bpm)
MyMIDI.addNote(track=0, channel=0, pitch=60,
time=convert_seconds_to_quarter(1, bpm),
duration=convert_seconds_to_quarter(1, bpm), volume=100)
MyMIDI.addNote(track=0, channel=0, pitch=60,
time=convert_seconds_to_quarter(5, bpm),
duration=convert_seconds_to_quarter(1, bpm), volume=100)
with open("/tmp/output.mid", 'wb') as binfile:
MyMIDI.writeFile(binfile)
附加信息
带bpm=100
的文件的十六进制内容:
ADDRESS 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ASCII
00000010 4d 54 68 64 00 00 00 06 00 01 00 02 03 c0 4d 54 MThd..........MT
00000020 72 6b 00 00 00 0b 00 ff 51 03 09 27 c0 00 ff 2f rk......Q..'.../
00000030 00 4d 54 72 6b 00 00 00 28 00 ff 03 0c 53 61 6d .MTrk...(....Sam
00000040 70 6c 65 20 54 72 61 63 6b 8c 40 90 3c 64 8c 40 ple.Track.@.<d.@
00000050 80 3c 64 a5 40 90 3c 64 8c 40 80 3c 64 00 ff 2f .<d.@.<d.@.<d../
00000060 00 00 00 00 .
bpm=600
的文件内容:
ADDRESS 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ASCII
00000010 4d 54 68 64 00 00 00 06 00 01 00 02 03 c0 4d 54 MThd..........MT
00000020 72 6b 00 00 00 0b 00 ff 51 03 01 86 a0 00 ff 2f rk......Q....../
00000030 00 4d 54 72 6b 00 00 00 29 00 ff 03 0c 53 61 6d .MTrk...)....Sam
00000040 70 6c 65 20 54 72 61 63 6b cb 00 90 3c 64 cb 00 ple.Track...<d..
00000050 80 3c 64 81 e1 00 90 3c 64 cb 00 80 3c 64 00 ff .<d....<d...<d..
00000060 2f 00 00 00 /.
解决方案
我贴的代码、转换函数和文件都是正确的。问题出在我用来听 midi 的 VLC 播放器上。
第一个文件:
delta message absolute time time ticks seconds ... 03 c0 ... 960 ticks per quarter note ... ff 51 03 09 27 c0 0 0 tempo: 600000 microseconds per quarter note 8c 40 90 3c 64 1600 1 note on 8c 40 80 3c 64 3200 2 note off a5 40 90 3c 64 8000 5 note on 8c 40 80 3c 64 9600 6 note off 00 ff 2f 00 9600 6 end of track
第二个文件:
... 03 c0 ... 960 ticks per quarter note ... ff 51 03 01 86 a0 0 0 tempo: 100000 microseconds per quarter note cb 00 90 3c 64 9600 1 note on cb 00 80 3c 64 19200 2 note off 81 e1 00 90 3c 64 48000 5 note on cb 00 80 3c 64 57600 6 note off 00 ff 2f 00 57600 6 end of track
两个文件的长度都正好是六秒。您的代码和文件都是正确的。
问题在于您使用什么工具来处理文件。