m2m: TiMidity++のmod→midiファイル変換




概要:

これは，TiMidity++に新しく-OM出力モードを追加して，modファイルを読み込
みmidiファイルを出力するものです。変換のために必要とされるパラメータは，
すべてmodと同じベース名の.m2mファイルに含まれています。このファイルが見
つからない場合は，自動で生成されます。コードの割り当てや値の置き換えを
手で行うのは，とても難しく退屈な作業でしょう。プログラムに，初期の.m2m
ファイルを生成してもらうことを*強く*推奨します。これにより，ほとんどの
ことを(すべてではないにしても)を行ってくれます。今のところ，ドラムの割
り当て，バンク/プログラムの修正，音量の調整を手動で行う必要があるでしょ
う。




使用例:

timidity -c c:\timidity\timidity.cfg -OM -V 2 -idt foo.mod

これは，変換のためのコンフィグファイルであるfoo.m2mの読み込みを試みて，
foo.midというファイルを出力します。-V 2は，X^2の音量カーブを使用する装
置(すべてのGM/GS/XGのハードウェア)に適したmidiを生成するように指定しま
す。-oフラグを使用して，他に出力したい名前を指定することができます。

もし，有効なtimidity.cfgなしでtimidityがインストールされている場合は，
単に0バイトのファイルを作成し，実体の代わりにそれを使います。modファイ
ルを演奏するのに，timidityは一切のmidiインスツルメントをロードする必要
がないので，パッチのセットやtimidity.cfgファイル実体を持つ必要がないの
です。:)




背景:

MODファイルはMIDIファイルと非常に似ています。両フォーマットは，基本的に
どのインスツルメントでどのようにノートを演奏するかの制御を並べたもので
す。MIDIがインスツルメントの外部音源に依存している一方，MODはイベントと
ともに，インスツルメントを一つのファイルにまとめています。mod→midiファ
イル変換を行う上で最も難しいのは，この基本的な違いです。modファイルは，
それがドラムあるいはコードである場合，各サンプルのチューニングされるピ
ッチが何かを知る必要がありません。MODプレーヤーは，それらが実際どうであ
れ，サンプルがすべて同じ固定周波数にチューニングされたものとして，要求
されたピッチでまとめられたサンプルを単に演奏します。したがって，もし直
接のmod→midiイベント変換を行ったとしたら，誤ったキーで演奏したり，スネ
アドラムを普通のメロディのインスツルメントとして扱ったり，コードである
べきところを単一のノートとしてまとめてしまうことでしょう。移調，ドラム
がらみのチャンネル移動，およびコード発行は，正確なmod→midi変換を行う場
合に克服すべき最も分かりやすい障害です。

Paolo Bonziniは，すでに仕事の半分を済ませていました。彼は，TiMidity++を
一流のmodプレーヤーに変えるのに十分なコードを寄付しました。これ単独では，
十分な助けにはならなかったでしょう。それは，彼がどのように実装したかと
いうことでした。良く知られている他のmodプレーヤーのようにイベントを扱う
のではなく，TiMidity++ではそれらを標準midiイベントに変換し，スペシャル
パッチとしてmodインスツルメントをロードし，それらを任意の普通のmidiファ
イルのようにレンダリングします。modイベントの構文解析，インスツルメント
の解析，直接のイベント転換は，すでに終わりました！ 私がしなければならな
かったのは，midiファイルに内部のTiMidity++のイベントを書く前に，私が言
及していない多くのより小さな事柄に加えて，私が先に述べた問題を扱うこと
でした。変換処理中に取り組む必要のある他の問題のうち，いくつかに興味を
お持ちであれば，m2m.cの一番上のコメントを参照してください。これらの他の
問題のうちのいくつかは扱うのに不明瞭で，4オクターブのピッチベンドがいま
だ少し奇妙に鳴りますが，それらは平均的なユーザが知る必要のないもの，あ
るいはmodファイルを上手く変換しようとする場合に，心に留めておけば良いも
のです。知る必要のあるただ一つのことは，先に議論された変換問題に取り組
むために，modの中の各サンプルに関するいくつかの情報を，個々のmodファイ
ルに関連したコンフィグファイル(.m2m)の中で，指定しなければならないとい
うことです。このファイルのフォーマットを下記に示します。




M2Mコンフィグファイルフォーマット:

コメント行は#で開始します。空行(改行の隣に空白その他の文字が存在しない)
は許容します。他のすべての行は，下記に示すフィールドを*5つ全部*指定して
ください。各フィールドは空白で分離されます。



フィールド1: サンプル番号

これは情報を定義しているサンプルの数です。modファイル中の第1のサンプル
は1(0ではない)です。



フィールド2: バンク/プログラム，ドラムフラグ，コード，静寂フラグ

このフィールドは，サンプルのいくつかの異なる特性を指定します。オプショ
ンパラメータは，括弧で囲んで与えます。このフィールドのフォーマットは:

(!)(bank/)program(chord)(*)

フィールドが感嘆符(!)から始まる場合は，ノートはこのサンプル用に出されま
せん。これは，音声や複雑なドラムトラック，あるいはGS sfxバンクを使って
似たようなのを作れない効果音のように，一般的なmidiインスツルメントに割
り当てることができない静寂サンプルに使うことができます。

bankフィールドでは，バンク選択を指定します(オプション)。これは，使用す
るバンクの番号で，プログラム番号と分けるために/で続けます。

program番号は，サンプルに割り当てられているmidiインスツルメントです。サ
ンプルがドラムの場合は，ドラムがドラムセットの中でマップされるノートで
す。

オプションのchordフィールドでは，サンプルがどのタイプのコードで構成され
るかを指定します。4つのタイプのコードがあり，それぞれ3つのサブタイプを
持っています。サポートされているコードタイプは，(M)ajor，(m)inor，
(d)iminished minorおよび(f)ifthです。各コードは，前の行で括弧で囲まれた
文字で指定されます。コードのサブタイプは，標準コードからどれだけ“転回”
したかを0，1，2で表します。“転回”の例として，メジャーコードは0，4，7
のノートの半音オフセットで構成されます。このコードを一つ左に転回すると
-5，0，4となり，二つ左に転回すると-8，-5，0となります。サブタイプを指定
しない場合は，0転回と見なします。

最後の部分は，サンプルがドラムかどうかを指定します。これを示すために，
フィールドの終わりに*を置いてください。ドラムフラグがセットされると，
コード割り当ては無視されます。

例:
8/48M     バンク8，プログラム48(オーケストラ)で標準メジャーコード
!8/48M    このサンプルを静寂とする
8/48M2    コードを二つ下に転回する以外は最初の例と同じ
48        tone bank 0の普通のマルカート
16/38*    パワードラムセットのスネア1
38*       標準ドラムセット0のスネア1



フィールド3: 移調

これは，modファイル中で指定されたオリジナルのノートを，どれだけ移調する
かを指定します。サンプルが真ん中のド(ピッチ60)でチューニングされている
場合，midiインスツルメントが正しいピッチで演奏するように，+24半音移調す
る必要があります。ドラムとしてマークされたサンプルは，ドラムチャンネル
上の単音に固定されるので移調しません。コンフィグファイルのパーザが衝突
しないように，ドラムによって無視されるとしても，移調フィールドに対する
値を入力しなければなりません。



フィールド4: ファインチューニング

このサンプルのピッチベンドのイベントはすべて，与えられたピッチの端数に
よって調節されます。これは，サンプルのチューニングが大きく外れている場
合に時々必要です。MOD作成者の中には，サンプルを正しくチューニングする代
わりに，ピッチベンドを使う人がいます。正しくチューニングされたサンプル
の音楽を演奏するとき，これらのピッチベンドはノートを外して，音痴に鳴り
ます。なので，ファインチューニングの値は，離調するピッチベンドを補うた
めに使用されます。

また，ピッチベンドで調整され*なかった*チューニングサンプルを見つけるこ
とは一般的なので，ピッチベンドの調節を加えると，単にmidiファイルでより
悪く鳴らすことになるでしょう。ファインチューニングを無効にするために，
オプションの!をファインチューニングの値の前に置くことができます。これは
コンフィグファイルの自動生成における*デフォルト設定*です。modがサンプル
のファインチューニングを要求するのを見つけたら，単に!を削除して，変換を
やり直してください。

この機能はまだ完全には実装されていません。既存のピッチベンドのイベント
だけが影響されるので，新しいピッチベンドのイベントは出されません。しか
しながら，これは通常問題ではありません。この機能を適用すべきほとんどの
ケースは，影響を受けるノートの前にピッチベンドが出されるmodを含んでおり，
それらが始まるサンプルを合わせるように意図されるからです。結局，新しい
ピッチベンドのイベントの挿入する実装すれば，真のファインチューニングの
機能になるでしょう。



フィールド5: %音量

各サンプルは，エクスプレッションのイベントを計ることにより，音量を変化
できます。100はデフォルト値で，オリジナルの音量の100%です。150がオリジ
ナルの音量の1.5倍になる一方，50はオリジナルの音量の半分に減少します。エ
クスプレッションの最大値が127であることを忘れないでください。したがって，
これより高く計られるエクスプレッションのイベントは127で切られて，違って
聴こえません。これは主に，midiファイルにおける大き過ぎるインスツルメン
トを静かにしたり，エクスプレッションの値が低すぎるので，始まらないイン
スツルメントを大きくするために使用されます。

最初の5つを越えるフィールドは解析されません。望めばここに何を書いても構
いません。コメントテキストの前に#を置く必要はありませんが，そうするのが
慣習的です。




周波数解析:

そうすると，各サンプルをいくつ移調するか，それがどのコードかをどのよう
に導きますか。サンプルのFFTおよび周波数ピークを表示することができるプロ
グラムに取り込んでみましょう。第1のピークは，常ではないが，たいていはサ
ンプルの基本ピッチです。サンプルがコードの場合，最初の3つの主なピークを
取って，これらからコードをを割り当てます。次に，.m2mファイルに適切なコ
ードおよび移調の値を入力して，それが正しいと思えるかどうか確かめてくだ
さい。これをすべて手動でするとなると，*非常に*時間が掛かります。。。そ
こで，私は割り当てをすべて行うルーチンを書きました:) それは100%正しくあ
りませんが，当たらずしも遠からずです。また，ピッチやコードを誤る場合，
それは常に正確な見かけの解を割り当てます。すなわち，もし視覚的にFFTデー
タを検査するなら，私はアルゴリズムが行うのと同じピッチを取るでしょう。
私はこのエキスパートではありませんが，非常に多くの時間を費やして，ピッ
チを割り当てるのに困難な，多くの異なる試験を費やした末，今はかなり熟練
していると思います:) それを改善できそうなただ一つの方法は，人間の耳がど
のように音を知覚するかを考慮に入れた，ある種の音響心理学のモデルで構築
することです。今は，それをしようとは思いません。。。それは，1つ以上のピ
ッチやコードを持つサンプルへの対処で上記の平均的な仕事を行いますが，雑
音や音が重なったサンプルが正しく割り当てられなくても驚かないように。ゴ
ミのようなデータを入れても，ゴミのような結果が出るだけ:) 自動割り当ては
大多数のサンプルに非常に適していて，手動で変更し始める前に，まず定義的
に試みるべきです。それが混乱する場合，たいてい一つの半音やオクターブの
複合に減らすことにより，そこからそれを調整することは容易です。

私は，自動周波数解析ルーチンを書く以前は，その領域に関する知識をほとん
ど持っていませんでした。ピッチ検出は，音声信号処理論における非常に古い
問題です。私は，1960年代以降の文献を調査しました。実際，その方法が当時
からあまり改善されていないので，以前の資料は現状においても通用します。
これを行う2つの主な道具は「自己相関」と「ケプストラム」分析です。自己相
関は，この問題に対する答えではなかったと判明します。お行儀の良いサンプ
ルでは上手くいく一方，シンセ楽器，雑音の多いインスツルメント，多数の基
本周波数を持つインスツルメントではすぐに破綻します。modファイルに見られ
る多くのサンプルは，これらの特性を示します。私がその調整を試みたり，多
くの良いものを試したりしたことはことごとく，実用サンプルを扱うほど十分
耐えるものになりませんでした。良い理論ですが，実際には使えません。

ケプストラム分析は，より頑丈であることが分かりました。それでも，多くの
ピッチフィルタリングとピークの重み付けを行わないと，上手くいきませんで
した。第2のFFT分析は，第1のFFTスペクトルに存在しなかった周波数ピークを
与えてくれました。しかしながら，それらは実際のピークに非常に接近してい
ました。そこで，私はピッチのピーク部としきい値以下の周波数を捨てて，第
1のFFTスペクトルのフィルタを通過したピッチを単に選び，ケプストラム分析
を行いました。私は，サンプルの最大振幅から2つの零交差を出して，零交差分
析に基づいた最大の周波数をセットします。これは，オクターブを飛び越える
誤差を防ぐために必要でした。さらに，第1のFFTに対応するピッチのピークの
最大値によって，ケプストラムのピーク部の重み付けが重要であることを知り
ました。これは，特に面倒な低音のサンプルを正しく割り当てさせようとする
と，絶望的に思われました。十分に驚いたことに，新たな割り当て誤りを引き
起こすことなく，私のすべてのサンプルが高い成功率で，素晴らしく動作しま
す! ただ一つ読み取れるのは，重み付けは音声解析の2秒以内だけしかきちんと
動作しないということです。それより大きいと，FFTサイズがより大きくなるの
で，ピッチのピークもまた拡散されます。したがって，ピッチ用の最大値は小
さ過ぎ，重み付けは誤った解を与え始めます。mod/midiインスツルメントにピ
ッチを割り当てる必要のない2秒以上のデータを解析したい場合は，既存の周波
数割り当て関数を呼ぶスライディング・ウィンドウの平均を実装することは容
易でしょう。

これは，私が持っている別のサンプル分析ソフトウェアのどれより良く動作す
るようです。私がケプストラム分析を行った方法について，より多くの詳細に
興味をお持ちであれば，freq.cのコードを見てみるか，最終的なアルゴリズム
のより多くの完全な記述をE-mailで求めてください。新しいFFTルーチンは私の
ものではないですが，パプリックドメインです。私が知る限りすべてのベンチ
マークから，これは私が必要とする(そして日々TiMidity++に加えられる将来の
エフェクト処理のための)最良のFFT実装です。オリジナルのFFTパッケージの入
手情報は，fft4g.cを参照してください。




提案?:

modを変換が良くなる方法，m2m.cのTODOやWISHリストの実装方法について何か
提案があれば，自由に私にE-mailしてください。私はこれを単体プログラムに
転用することを考慮していますが，より多くの自由時間と気力を得るまで，そ
れは単にTiMidity++のアドオンとして留まるでしょう。




免責事項:

TiMidity++はGPLの下で配布され，私のコードを利用している，それもGPLの下
にあると思います。よって，つまらん，つまらん，つまらん，免責事項，つま
らん，つまらん，つまらん，などなど。言わずもがな。




Eric A. Welsh <ewelsh@ccb.wustl.edu>
ワシントン大学
ミズーリ州セントルイス校
計算生化学センター
分子設計センター
