<p><a href="https://metacpan.org/module/MIDI" rel="noreferrer">^{<cd1>}</a>包将为您执行此操作,但具体方法取决于midi文件的原始内容。</p>
<p>midi文件由一个或多个曲目组成,每个曲目是16个频道中任何一个频道上的<em>事件</em>序列,例如<em>注释关闭</em>,<em>注释打开</em>,<em>程序更改</em>等。最后一个曲目将更改分配给频道的乐器,这是您需要更改或添加的。</p>
<p>如果没有任何程序更改事件,频道将使用程序编号(语音编号)0,这是一架原声大钢琴。如果您想更改这样一个频道的乐器,那么您只需要在曲目的开头为这个频道添加一个新的节目更改事件。</p>
<p>但是,如果一个频道已经有一个程序更改事件,那么在开头添加一个新的将不会有任何效果,因为它会立即被先前存在的事件覆盖。在这种情况下,必须<em>更改</em>现有事件的参数才能使用所需的工具。</p>
<p>如果一个频道最初有几个程序更改事件,这意味着乐器在整个音轨中都会更改,那么事情可能会更复杂。这是不寻常的,但如果你遇到这样的文件,你将不得不决定如何改变它。</p>
<p>假设您有一个非常简单的midi文件,其中包含一个单轨、一个通道,并且没有现有的程序更改事件。这个程序从文件中创建一个新的<code>MIDI::Opus</code>对象,访问曲目列表(只有一个成员),并引用第一个曲目的事件列表。然后通道0的一个新的程序更改事件(这个模块称之为<code>patch_change</code>)被取消将<em>移到事件列表的开头。新的活动有40个节目-小提琴-所以这个频道现在将用小提琴而不是钢琴演奏。</p>
<p>有了多个轨迹、多个通道和现有的程序更改事件,任务变得更加复杂,但原理是一样的——决定需要做什么,并根据需要更改事件列表。</p>
<pre><code>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');
</code></pre>