将 0xC0<byte> 替换为 0xC000 以“重置”MIDI 乐器?
Posted
技术标签:
【中文标题】将 0xC0<byte> 替换为 0xC000 以“重置”MIDI 乐器?【英文标题】:Replace 0xC0<byte> with 0xC000 to "reset" MIDI instrument? 【发布时间】:2012-04-09 07:05:17 【问题描述】:我有一些由 Sibelius (v.4?..) 制作的 MIDI 文件,其中包含“不寻常”的乐器;我听不见旋律。我决定我需要将乐器“重置”为 0(我相信原声三角钢琴)。
所以,我使用python-midi 和mingus 编写了一个Python 程序;这些程序可以改变 MIDI 乐器,但它们都极大地改变了节奏。
Rosegarden这个工作做得很好,但是我不能批量使用。
接下来,在阅读了一些 MIDI 格式信息(例如,here 和 here)之后,我编写了一个简单的 Python 脚本(见下文),它只是将一些字符串替换为另一个字符串 --- 替换 0xC0[byte ] 与 0xC000 类似。
现在那些 MIDI 文件听起来不错,我可以听到所有的声音。
所以,我的问题是 --- 这样做是否“安全”(在任何意义上)?我怎样才能更好地更换乐器?如何更好地“检测” MIDI 文件中的 0xCx 命令?
谢谢!
#!/usr/bin/env python
#
import sys
import re
patt = re.compile('(\xC0|\xC1|\xC2|\xC3|\xC4|\xC5|\xC6|\xC7).')
try:
filein = sys.argv[1]
except IndexError:
print "Specify input file as an argument."
sys.exit(1)
try:
fileout = sys.argv[2]
except IndexError:
fileout = '%s-out2.mid' % filein.replace('.mid', '')
filein_data = open(filein, 'rb').read()
open(fileout, 'wb').write(patt.sub('\1\x00',filein_data))
【问题讨论】:
【参考方案1】:简单地替换所有的0xC是不安全的??? 0xC?00的字节,主要是因为0xC???可能指示事件的增量时间,但实际上并不是程序更改事件的一部分。意外修改 delta 时间会使所有后续事件都偏离时间,如果它是多轨组合的一部分,这听起来会很糟糕。
至于解决方案,我怀疑是否有一个正则表达式可以检测程序更改事件,而不会同时获取增量时间。我修改 MIDI 的唯一经验是使用我编写的 Java library,您可以使用以下代码完成任务:
MidiFile input = new MidiFile(INPUT_FILE);
for(MidiTrack T : input.getTracks())
Iterator<MidiEvent> it = T.getEvents().iterator();
while(it.hasNext())
MidiEvent E = it.next();
if(E instanceof ProgramChange)
E.setProgramNumber(0);
input.writeToFile(OUTPUT_FILE);
我是徒手写的,所以你可能不得不使用一些异常捕获,但它相当简单。
希望对您有所帮助。
【讨论】:
所以,\xC???
可以是时间增量的一部分(“介于”或最后一个,取决于最小符号位)或程序更改事件(对于任何轨道)。对?嗯.. 我想我应该用python-midi
写一些脚本。谢谢。【参考方案2】:
这对我有用。不知道什么是错的prevoiusly。 python-midi
不错。
#!/usr/bin/env python
#
# Sets all instruments' numbers to zero.
#
import sys
import midi
try:
infile = sys.argv[1]
except IndexError:
print "Specify input file as an argument, please."
sys.exit(1)
try:
outfile = sys.argv[2]
except IndexError:
outfile = '%s-out.mid' % infile.replace('.mid', '')
midi_data = midi.read_midifile(infile)
for track_idx in range(len(midi_data)):
for event in midi_data[track_idx]:
if isinstance(event, midi.ProgramChangeEvent):
event.data = map(lambda x: 0, event.data)
midi.write_midifile(outfile, midi_data)
【讨论】:
我觉得这不是对所提出问题的答案。这是收到答案后达成的解决方案,但如果其他人有这个问题,这不提供任何关于该主题的教育。也就是说,我很高兴你找到了解决方案! :-) @LeffelMania 是的,可能。我错了,一问三问。我也会取消选择我的回答者。以上是关于将 0xC0<byte> 替换为 0xC000 以“重置”MIDI 乐器?的主要内容,如果未能解决你的问题,请参考以下文章
c++中的 0x004114a4 处有未经处理的异常: 0xC0000005: 写入位置 0xcccccccc 时发生访