该MIDI软件包将做到这一点给你,但确切的方法取决于MIDI文件的原始内容.
midi文件由一个或多个轨道组成,每个轨道是16个通道中任意一个的事件序列,例如Note Off,Note On,Program Change等.其中最后一个将改变分配给通道的仪器,并且这就是你需要改变或添加的东西.
如果没有任何节目变更事件,频道将使用程序号(语音号码)零,这是一个声学三角钢琴.如果您想更改此类频道的乐器,那么您需要做的就是在曲目的开头为此频道添加新的节目变更事件.
但是,如果某个频道已经有一个程序更改事件,那么在开头添加一个新事件将不起作用,因为它会立即被预先存在的一个覆盖.在这种情况下,您必须更改现有事件的参数才能使用所需的仪器.
如果最初有一些频道的节目变更事件,事情可能会更加复杂,这意味着乐器会在整个音轨中发生变化.这很不寻常,但如果您遇到这样的文件,您将不得不决定如何更改它.
假设您有一个非常简单的midi文件,其中包含一个轨道,一个通道,并且没有现有的Program Change事件.该程序MIDI::Opus从文件创建一个新对象,访问轨道列表(只有一个成员),并引用第一个轨道事件的列表.然后patch_change,通道0 的新程序更改事件(此模块将其调用)未被移位到事件列表的开头.新活动的节目编号为40 - 小提琴 - 所以这个频道现在将用小提琴而不是钢琴演奏.
通过多个轨道,多个通道和现有的程序变更事件,任务变得更加复杂,但原则是相同的 - 决定需要做什么并根据需要更改事件列表.
use strict;
use warnings;
use MIDI;
my $opus = MIDI::Opus->new( { from_file => 'song.mid' } );
my $tracks = $opus->tracks_r;
my $track0_events = $tracks->[0]->events_r;
unshift @$track0_events, ['patch_change', 0, 0, 40];
$opus->write_to_file('newsong.mid');
Run Code Online (Sandbox Code Playgroud)
使用music21库(插入我自己的系统,希望没问题)。如果部件中定义了补丁,请执行以下操作:
from music21 import converter,instrument # or import *
s = converter.parse('/Users/cuthbert/Desktop/oldfilename.mid')
for el in s.recurse():
if 'Instrument' in el.classes: # or 'Piano'
el.activeSite.replace(el, instrument.Violin())
s.write('midi', '/Users/cuthbert/Desktop/newfilename.mid')
Run Code Online (Sandbox Code Playgroud)
或者如果当前没有定义补丁更改:
from music21 import converter,instrument # or import *
s = converter.parse('/Users/cuthbert/Desktop/oldfilename.mid')
for p in s.parts:
p.insert(0, instrument.Violin())
s.write('midi', '/Users/cuthbert/Desktop/newfilename.mid')
Run Code Online (Sandbox Code Playgroud)