2015年2月12日

Go言語で E-MU Proteus Pack for Kontakt 専用リネーマーを作った

わりとただの日記。

以前 E-MU 1616M と Emulator X のバンドルを買ったことがあって、E-MU 1616M は半年前までは使っていたし Emulator X も古臭い音だけど個性的でわりと好きだった。
しかし E-MU 1616M 用のドライバ最終リリースが Windows7 用のベータ版で止まっていたり、64bit 対応した Emulator X3 は日本で出ていなかったり、ここ数年は色々な面で危険な匂いが漂っていた。


去年の後半、マシンを新調するついでにサウンドカードはこのグラフを見ながら懐事情と相談して Focusrite Saffire PRO 14 を FireWire-Thunderbolt 変換ケーブルを経由して Thunderbolt 接続で使うように変えた。
そのグラフを見る限り RME は異常だけど基本的には PCIe > FireWire > USB の構図で、FireWire より更に PCIe に近いであろう Thunderbolt 環境があると将来的にも安泰かもしれない、ということもあって Windows で Thunderbolt 接続することを前提に ThunderboltEX II が使えるマザーボードでマシンを組んだりした。
(だから経路としては現状 Saffire PRO 14 -> FireWire6pin↔9pin 変換 -> Apple Thunderbolt - FireWireアダプタ -> ThunderboltEX II -> マザボ、とアホみたいに遠い)

その結果 Saffire PRO 14 は大変好調で文句ない環境になったのだが、当然 Emulator X の代わりは手元にない。
Emulator X といえば Proteus サウンド、そこで代用品として Digital Sound Factory の E-MU Proteus Pack の Kontakt 版を買うことにした。Proteus 2000 の他に Virtuoso と Mo' Phatt と Planet Earth と Vintage Pro と Xtreme Lead-1 がついて $99 だった(時期によってはセールで$69とかになるらしい)。
実際のところはまあぶっちゃけ買わなくても良かった気もするんだけど。
今となっては小さい波形容量の PCM 音源の音って独特で好きなもので。

で、実際に手に入れてみるとファイル構造がこんな感じになっていて、実機上で表示されていたと思われる 'kb1' のようなカテゴリ名がなく、プリセットの順番もグチャグチャになっていた。


多分 Emulator X の時もこの辺適当だった気がするしこんなもんかな、とは思ったものの、このままだと実際に使う時音色を探すのに苦労する。
そのため実機の順番で並ぶようにファイル名を変えたいのだが、全部で3000個近いファイル数があり、手作業で変えていくのはちょっと面倒臭い。

というわけで、これをある程度少ない手数でリネームするために、専用のツールを作ろうと思った。
ここまでが前置き。

1. 本来のプリセットの順番やカテゴリ名をデータ化する

まずこれをデータにしないと始まらない。
ハード音源のマニュアルは後ろのほうにプリセット一覧があると思ったので少し探してみたところ、Proteus 2000 のマニュアルがアーカイブされていた

この一覧は簡素なリストなので、PDF 版の該当部分をコピーするだけでかなり綺麗な形になった。
0. kb1:DynamicGrand
1. kb4:Yo My Dynos
2. orc:Orchestral
3. gtr:Grusty
4. bs1:A Ku Stq
5. kb3:Rock'in B
.
.
.
これを、プログラムから扱いやすいように CSV フォーマットに変換する。
以下の様な正規表現で変換した(本当はサクラエディタ上でやった)。
$ cat bank0.txt | sed -e "s/\([0-9]\+\)\. \(...\):\(.\+\)/\1,\2,\3/g" > bank0.csv
これだけでわりと上手くいったので、この調子で Proteus 2000 のバンク8個と、Mo' Phatt / Planet Earth / Vintage Pro / Xtreme Lead のバンク4個ずつ、合計 24*128=3072 個分をデータ化した。

ちなみに Xtreme Lead の Bank 2 に「4. bpm:"Carpe Diem"」というダブルクォートが入ったものがあったり、Planet Earth の Bank 2 に「60. pr1:BD,Tm,Sn Set」というカンマを含んだものがあったりして若干罠がある。

ともあれ、いくつかの修正を経て Virtuoso 以外のデータ化がサクッと完了した。
Virtuoso だけはファイル名と実機上のパッチ名が目視でわかるレベルで差が大きく、かつファイル名から音が大体想像つくネーミングになっているので今回の変換処理の対象からは除外することにした。

2. Kontakt 用 nki ファイルとパッチの対応付けをどうやるか考える

実機上のパッチ名と Kontakt 用ファイル名が 100% 一致しているなら非常に簡単に済むのだが、Proteus 2000 の Bank 0 の一番最初の「DynamicGrand」がそもそも「Dynamic Grand.nki」とスペースが入ったファイル名になっており、完全に一致していることは期待できそうにない。

とはいえ似た名前にはなっているようなので、今回はレーベンシュタイン距離が近いものを候補として挙げる方向で作業を進めることにした。

また、元々のパッチ名にはファイル名として使用できない事が多いダブルクォートやスラッシュなどを含んでいるものが存在しているので、レーベンシュタイン距離を求める前にパッチ側の記号はアンダースコアに置換しておくことにする。

3. リネームプログラムを作る

ここで説明した内容に合わせてプログラムを作ると、実機上パッチ名と実際のファイル名から拡張子を取り除いたもので完全一致しているファイルの数が出せる。
完全一致した数は2663件、つまり409件が完全一致しなかった。

エラー率としては13%程度なのでそんなに悪くないが、もう少し改善したい。
ここからは泥臭い戦いを繰り広げていく。

4. 検出率の改善

「DynamicGrand」の例のように完全に一致していないが正解しているパターン、Proteus 2000 の Bank 3 「84. str:Section」「125. brs:Section」のようにパッチ名が被っていて誤検出してしまうパターンなど、失敗のパターンはいくつかあるようだ。

まずは完全一致していないが正解しているパターンを成功として扱えるようにしていきたい。
名前が惜しいケースでは以下の様なものがあった。
  • 単語の間にスペースが入っているもの
  • 記号が「_」に変換ではなく取り除かれているもの
  • 「Drms」が「Drums」になるなど短縮形が戻されているもの
  • 実機のパッチ名の後ろの「 w」が省略されているもの(パンが左右に振られていたパッチ?)
  • 実機のパッチ名の後ろの「 mono」が省略されているもの(同時発音数が1だったパッチ?)
  • 実機のパッチ名の後ろの「 MW」が省略されているもの(モジュレーションホイールで特殊効果があったパッチ?)
上記のパターンの中で、最後の3つは簡単に機械的な対応できそうだ。
実機上のパッチ名が「Pizz&Sct MW」のように「 w」「 mono」「 MW」で終わる場合、それを外した名前で完全一致するものがある場合はそれを採用するように変えてみることにする。

この修正によって71件が成功として扱われるようになった。一部「w」や「MW」の前にスペースがないパッチもあり、現状これらは漏れているがひとまずスルーしておく。

短縮形が戻されているものについても対応したいが、これらはスペースの有無も関係しており、両方を同時に対応しないと作業量の割に成功率があまり上がらなそうだった。
そのためこれに対しては、実機上のパッチ名の短縮形の単語を長いものに展開を試みる処理を加え、更に nki ファイルの名前からスペースや記号を取り除いた名前で比較するようにし、これによって完全一致するようになったものを成功として扱うようにする。

この修正によって更に111件が成功として扱われるようになった。
細かい処理を変えることでここの件数もまだ少し増やすことができると思うが、ひとまず保留とする。

5. 最後の悪あがき

一定のルールに従って修正できそうなものはある程度丸め込むことができた。

まだ残っているものは法則性が薄いか、正しいかどうかがすぐに判断できないものが多い。
ここからはリネーム対象にならないまま残った nki ファイルのリストと対象ファイルが見つけられなかったパッチのリストを見比べ、手作業で対応付けを行っていくことにする。
そのため、対応するパッチが見つからないまま余ったファイル一覧を見ながら、目視で正しい変換をどうかを「認定」あるいは間違っている場合は手動で正しいものを「指定」することにする。

しかし作業を始めてみるとこれがなかなかつらい。
0-127 までの128種類あるはずなのにファイルが 127 個しかないディレクトリがあったり、他のバンクに探している音色用のファイルがあるように見えるものなど、どう対応していいのか微妙なものが少なくない。
何より、実機での音がわからないので本当に正しいのか確証が持てない。

結局100個程度手動で対応したが、80個以上の分類不能なままのファイルが残った。
最後に手作業で割り当てた分が全部正しいと仮定すればここまでで300個近くが成功になっていて、10% 近く改善できたので今回はこれで我慢しようと思う。

今回作ったプログラムはこちら。

http://github.com/oov/proteus-pack-renamer
多分使う人はほとんどいないと思う。

6. おまけ:全てのリバーブを外したい

なんかしばしばイマイチなリバーブが深めにデフォルトで入ったりしているので、全部切ってしまいたい。
全ての nki ファイルを書き換える必要があるので、これも nki ファイルの中身を解析して、リバーブをなしに差し替えるツールを……作るのは辛いので、ここは AutoIt でクリアすることにする。
Local $sPath = "T:\EMU_Proteus_Pack_Kontakt\Proteus 2000\Proteus 2000 Bank 0\"
Local $hWnd = WinWait("[TITLE:Kontakt 5; REGEXPCLASS:NINormalWindow.*]")

ReverbBypassDir($hWnd, $sPath & "*.nki")

Func ReverbBypassDir($hWnd, $pattern)
   Local $h = FileFindFirstFile($pattern)
   If $h = -1 Then
      Return False
   EndIf

   Local $s = "", $iResult = 0
   While 1
      $s = FileFindNextFile($h)
      If @error Then ExitLoop
   ReverbBypass($hWnd, $sPath & $s)
   WEnd
   FileClose($h)
EndFunc

Func ReverbBypass($hWnd, $sPath)
   WinActivate($hWnd)

   ; Open an instrument
   ControlClick($hWnd, "", "", "left", 1, 315, 23)
   ControlClick($hWnd, "", "", "left", 1, 315, 93)
   Local $hOPWnd = WinWait("[CLASS:#32770]")
   ControlSetText($hOPWnd, "", "[CLASS:Edit; INSTANCE:1]", $sPath)
   Send("!O")
   Sleep(1500)

   ; Select the tab "Proteus 2000"
   ControlClick($hWnd, "", "", "left", 1, 60, 303)
   Sleep(200)

   ; Select the FX Type <<Bypass>>
   ControlClick($hWnd, "", "", "left", 1, 376, 188)
   Sleep(200)
   ControlClick($hWnd, "", "", "left", 1, 376, 209)
   Sleep(200)

   ; Save and close
   ControlClick($hWnd, "", "", "left", 1, 632, 97)
   Sleep(200)
   Send("!Y")
EndFunc
処理内容はかなり簡単で、$sPath に指定されたディレクトリ内にある *.nki ファイルを起動済みの Kontakt 5 で開いて(Files メニューをクリック → Load... をクリック → 入力欄にファイルへのフルパスを指定 → Alt+O)、FX Type を選択しなおして閉じる。
閉じる時に保存するか聞かれるので、そこで「はい」と答えるだけの単純なスクリプト。
本当は Proteus 2000 タブを選択する処理も必要ないはずだったのだが、Proteus 2000 バンク 0 「L.V.'s Worm.nki」のように初期状態で開いているタブが異なっている音色が一部あったので、タブを選ぶ処理も加えた。
128個処理するのに大体400秒程度なので、そんなに時間も掛からずほぼ放置で全てのパッチの設定を変えることができた。
Proteus 2000 以外も画面上の配置は変わらないのでこのスクリプトはそのまま流用できた。

また、この処理中、他にも nki ファイル側で問題があるものが見つかった。

  • Proteus 2000 バンク 3「Huge Brass.nki」はサンプルファイルの参照先が間違った場所のままリリースされている
    (ただし本来の場所にファイル自体はあるので修正すれば問題なく使える)
  • Virtuoso の Orchestral  Winds, Brass, & Percussion の Timpani.nki は対応するサンプルファイルの一部が存在しない
ティンパニの問題は少し気になるけど、この音源パック自体何年も前からあるはずだし「まあいいか」レベルで誰かが見つけても放置されてるのかなあ…。

更におまけ: Go言語に似たパッチ名があった。リネームしたおかげで「bas」でベースだとわかる。

Clip to Evernote