6

既存の .mid ファイルを解析し、楽器を「アコースティック グランド ピアノ」から「バイオリン」などに変更して、元に戻すか、別の .mid ファイルとして保存したいと考えています。

ドキュメントで見たところ、楽器はprogram_changeorpatch_changeディレクティブで変更されますが、既存の MIDI ファイルでこれを行うライブラリは見つかりません。それらはすべて、ゼロから作成された MIDI ファイルのみをサポートしているようです。

4

2 に答える 2

5

パッケージがこれMIDIを行いますが、正確な方法は midi ファイルの元の内容によって異なります。

MIDI ファイルは 1 つまたは複数のトラックで構成され、各トラックは、ノート オフノート オンプログラム チェンジなど、16 チャンネルのいずれかの一連のイベントです。これらの最後のものは、チャンネルに割り当てられた楽器を変更します。それはあなたが変更または追加する必要があるものです。

プログラム チェンジ イベントがまったくない場合、チャネルはアコースティック グランド ピアノであるプログラム番号 (ボイス番号) 0 を使用します。このようなチャンネルのインストゥルメントを変更したい場合は、このチャンネルの新しいプログラム チェンジ イベントをトラックの先頭に追加するだけです。

ただし、チャンネルにすでにプログラム チェンジ イベントがある場合、最初に新しいイベントを追加しても効果はありません。これは、既存のイベントによってすぐに上書きされるためです。この場合、必要なインストゥルメントを使用するには、既存のイベントのパラメーターを変更する必要があります。

1 つのチャンネルにもともと複数のプログラム チェンジ イベントがあり、楽器がトラック全体で変化する場合、事態はさらに複雑になる可能性があります。これは珍しいことですが、このようなファイルに遭遇した場合は、どのように変更するかを決定する必要があります。

トラックが 1 つ、チャンネルが 1 つしかなく、プログラム チェンジ イベントが存在しない非常に単純な midi ファイルがあるとします。このプログラムは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');
于 2013-01-28T09:29:24.980 に答える
4

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')

または、現在定義されているパッチの変更がない場合:

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')
于 2013-01-30T19:11:40.070 に答える