VSTプログラミング feat.MATLAB

Unagi DTM Advent Calendar 2020 6日目です。

この記事は

  • MATLAB を使って VST プラグインを自作する記事です
  • ボリューム変えるくらいしかやりません(信号処理詳しくないので)

    • 最後にリンクをおいておきますので、詳しく知りたい方はそちらを参照ください

はじめに

VSTって何さ

Steinberg's Virtual Studio Technology のことで音源やエフェクタのプラグイン形式の一つです。DTMerはこれに金を溶かす現象が報告されています。

高いんですけど、ないと明らかに曲がしょぼい。DTMerのジレンマですね。

なら自分で作るしかないじゃない。こう考えた人は私だけではないはず...

VST を作る(C++ 挫折編)

天下の Steinberg 様なので、 VST を作るために必要な SDK は公開してくれてます。が。

数年前に VST2 制作に挑んだときは Visual Studio でしかビルドができず、情報も少なく、技術力も作りたいものもなかったのであっさり投げました。

今は主力が VST3 に切り替わり、こちらにて公開されています。 日本語のドキュメントは皆無ですが、C++VST作り 様の解説が非常に丁寧です。(ここ VST2 の時から解説をしてくれてます。神。)

また再挑戦しようかなと思っていたところ、今年の春くらいに「MATLABVST が作れる」という話で盛り上がっているところを Twitter で見かけました。

ちょっと調べてみたら VSTi は難しそうなのですが、エフェクタならかんたんに作れそうです。やってみましょう。

VST を作る(MATLAB編)

そもそも MATLAB って?

  • Mathworks 社が開発している科学技術計算言語
  • Python っぽい書き方をするけれど違う部分も結構ある
    • 配列の index が1から始まるとか
    • */演算子は行列演算なので、.*./を使わないといけないとか
  • 行列計算や機械学習などは公式ライブラリが手厚いので簡単に動かせる
  • Simulink と併用すれば組み込み系との連携も強い
  • 基本年ごとのサブスクリプション制で有料
    • 学校によってはライセンス購入しているかも…?

ざっとこんな感じです。有料なのがネックなのですが、環境構築がなくて楽ですね。

体験版でもいけます(30日の制限あり)が、生成に必要なツールボックスMATLAB Online では対応していないため、ダウンロードを行う必要があります。体験版登録した後、ライセンスセンター(https://jp.mathworks.com/licensecenter/trials)にアクセスして取得しましょう。

実装

コピペ編

早速やってみましょう。

せっかく公式がドキュメント書いてくれてるのでそれをパクってきたほうが楽そうです。

jp.mathworks.com

MATLAB を起動し、スクリプトの名前を stereoWidth.m にし、公式サンプルのコードを張っ付けます。

コンソールで

>> audioTestBench stereoWidth

と入力すると、MATLAB 上でテストできます。

f:id:mjtakenon:20201206235549p:plain
audioTestBench を使えば MATLAB 上でテストできます

これまたコンソールで

>> generateAudioPlugin stereoWidth

と入力すると、stereoWidth.dllが生成されるので、こいつを読み込んでみます。

f:id:mjtakenon:20201206224143p:plain
諸事情により VSTHost を使っていますが、もちろん DAW でもちゃんと動きます。

もう VST ができてしまいました。ちょろい。

コーディング量としてはかなり少なめなので、直感的にわかります。

自作編

もう少し踏み込んだ内容で自作VSTとか書きたいですが、諸事情により今度にして、簡単なフェーダーを実装します。(本当はフィルタとか作ろうとしたんですけど忘れてて正しい解説できる気がしなかったのでまた今度やります)

フェーダー、要はボリュームつまみです。 オーディオを入力してつまみが0dBだとそのまま出力、マイナス方向にしていくと音量が小さくなってくあれです。 -96dB から +6dB 操作できればいいでしょうか。(-96dB って 16bit 符号付整数の値で表せる最小の数らしいので)

ここを参考にさせてもらいました。

My Tube Amp Manual

入力を in としたとき、dB を求める式は \displaystyle{dB = 20 \times \log_{10} in} です。電気関係のときは20が10になるっぽいですが。

なので、逆に dB から入力を求めるときは\displaystyle{in = 10^{\frac{dB}{20}}}でしょうか。(ここらへん調べながら書いたのですごく怪しいです。間違ってたら教えてください。)

完成したものがこちらになります。

classdef Fader< audioPlugin
  properties
    Volume = 1;
  end
  properties (Constant)
    PluginInterface = audioPluginInterface( ...
      audioPluginParameter('Volume', 'Mapping', {'lin', -96.0, 6.0}) ...
    );
  end
  methods
    function out = process(plugin,in)
      out = in .* (10^(plugin.Volume/20));
    end
  end
end

パラメータと出力のところだけ変えました。 ただ、このままだとオーバーフローの値を考慮していないですね。どうなるか調べてなかったので鼓膜割れたらごめんなさい。

Fader.mで保存し、出力すると、

f:id:mjtakenon:20201206232705p:plain
フェーダー。ボリュームが 0 ならそのまま。下げると小さく、上げると大きく。

できますね。よしよし。

できないこと

今回のような用途であればいいんですが、いろいろと制約があるようです。

  • Audio Test Bench 上ならできるMIDI 入出力ですが、VST出力するとできないようです(VSTiが作れないやん...)
  • 画像とか使う場所や大きさに結構制限がありそう
    • アニメーションGIF入れたら Audio Test Bench では動き回りましたが、VST 出力したら地蔵になりました
  • Web系の通信もできないようです

VSTi、作りたかったなぁ...

いろいろやりたくなってくると C++ のが自由なのですが、環境構築とかのお手軽さという点では MATLAB よかったです。信号処理用の関数も超大量にありますし。

練習もかねて、遊んでみてはいかがでしょうか。

本文中で参考にしたサイト