用0xC000替换0xC0 <byte>以“重置”MIDI乐器?</byte>

时间:2012-04-09 07:05:17

标签: midi midi-instrument

我有一些Sibelius(第4节?)制作的MIDI文件,其中包含“异常”乐器;我听不到旋律。我决定我需要将乐器“重置”为0(我相信Acoustic Grand Piano)。

所以,我用python-midimingus写了一个Python程序;这些程序可能会改变MIDI乐器,但它们都会大大改变节奏。

Rosegarden做得很好,但我不能批量使用它。

接下来,在阅读了一些MIDI格式信息(例如herehere)之后,我写了一个简单的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))

2 个答案:

答案 0 :(得分:2)

简单地替换所有0xC是不安全的???字节有0xC?00,主要是因为0xC ???可以指示事件的增量时间,而不是实际上是程序更改事件的一部分。意外修改增量时间会将所有后续事件转移到关闭时间,如果它是多音轨合成的一部分,这听起来会非常糟糕。

至于解决方案,我怀疑有一个正则表达式可以检测程序变更事件而不会同时获取增量时间。我修改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);

我写了那个空闲的手,所以你可能不得不使用一些异常捕获,但它是相当简单的。

希望有所帮助。

答案 1 :(得分:0)

这对我有用。以前不知道什么是错的。 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)