将 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 乐器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中解码和编码 UTF-8 字符

C++ BYTE数组转字符串

c++中的 0x004114a4 处有未经处理的异常: 0xC0000005: 写入位置 0xcccccccc 时发生访

ADC0832

Modbus CRC16 校验计算函数

动态分析技术