MATLABでVSTプラグイン開発 [初級編]~数分?で作れるVST~LMSで無相関プラグイン
電子書籍発売しました!(2023/01/22)
動画・音声リンク付き紹介記事はこちら。
Amazon Kindle 電子書籍「MATLAB で簡単オーディオ プラグイン開発」
スクリプトはどなたでも無料でダウンロードできます。
だいぶ前に
「夏休みはVST! MATLABで楽々(?)VSTプラグイン開発」
という記事を書き、おかげさまでこのnote中ぶっちぎりの一番人気(あっ、いや、HRTFの記事がトップに躍り出てました!(^-^; )なのですが、色々詰め込んだため3万字超えになってしまいました。
そのため、
「やはり簡単にはできそうにないな・・」
と思われてしまった方もいるのではないかと思い、今回は
「MATLABなら本当に簡単にVSTが作れる!」
を趣旨に書いてみたいと思います。
生成できるのは、Windowsでは VST2(64/32bit)、Macでは AUv2 です。
単体起動可能なスタンドアローン版も生成できます。(R2022aで、VST3も生成可能となりました)
開発環境
MATLAB 本体以外に必要な Toolbox は
DSP System Toolbox
Signal Processing Toolbox
Audio Toolbox
です。
最初の2つは "Audio Toolbox" の動作に必要なので、"Audio Toolbox" が動く状態ならVSTプラグインが作れます。HomeライセンスでもOKです。
それとCコンパイラが必要です。
MinGWであれば、MATLABメニューの 「環境 -> アドオン」 からもインストールできます。
VST_simple1
まずは、音量を変えるだけのプラグインを作ってみましょう。
classdef VST_simple1 < audioPlugin
properties
inputGain = 1;
end
properties (Constant)
PluginInterface = audioPluginInterface(audioPluginParameter('inputGain'));
end
methods
function out = process(plugin,in)
out = in * plugin.inputGain;
end
end
end
これだけです!
あとは、
>> generateAudioPlugin VST_simple1
で、(もちろん規模によって変わりますが)1分程度でVSTプラグインが生成されます。(私が今作ってるのは、40分以上掛かります・・)
デバッグは audioTestBench を使います。
>> audioTestBench(VST_simple1)
ファイルから読みたい場合は "Input" を "Audio File Reader"、オーディオI/F等にしたい場合は "Audio Device Reader" にしてから、横の歯車アイコンでさらに詳細を決定します。
"Output" も同様に、ファイルに書き込みたい場合は "Audio File Writer"、スピーカーやオーディオI/F等に出力したい場合は "Audio Device Writer" を選択します。音を出しながらファイル出力したい場合は "Both" です。
単に見た目を確認するだけであれば
>> parameterTuner(VST_simple1)
でも表示されます。
VST_simple2
さすがにこれだけだと何なので、次はゲインをdBに、スライダーをロータリーノブにしてみましょう。
classdef VST_simple2 < audioPlugin
properties
inputGaindB = 0;
end
properties (Constant)
PluginInterface = audioPluginInterface( ...
audioPluginParameter('inputGaindB', ...
'DisplayName','Gain', 'Label','dB','Mapping',{'pow', 1/3, -80, 6}, ...
'Layout',[1,1], 'Style','rotary'), ...
audioPluginGridLayout);
end
methods
function out = process(plugin,in)
gain = 10^(plugin.inputGaindB/20);
out = in * gain;
end
end
end
ロータリーノブを表示するには、audioPluginGridLayout を使用して配置する必要があります。
また、DAWに読み込んだときにロータリースライダーを表示させるには、カスタムGUI対応のDAW(Reaper等)が必要です。
VST_simple3
少し長くなりますが、ピーク&ノッチフィルターも追加してみましょう。
classdef VST_simple3 < audioPlugin
properties
channelMode ='LR';
PEQ_ON = false;
inputGaindB = 0;
PEQ
centerFreq = 4000; peakGain = 0; Q = 1.6;
end
properties (Constant)
PluginInterface = audioPluginInterface( ...
audioPluginParameter('inputGaindB', ...
'DisplayName','Input Gain', 'Label','dB','Mapping',{'pow', 1/3, -80, 6}), ...
audioPluginParameter('channelMode', 'DisplayName','Process Channel', 'Mapping',{'enum','LR','L','R'}), ...
audioPluginParameter('PEQ_ON', 'Mapping',{'enum','OFF','ON'}, 'DisplayName','PEQ'), ...
audioPluginParameter('centerFreq','Mapping', {'log',20,20000}, 'DisplayName','Frequency'), ...
audioPluginParameter('peakGain','Mapping', {'lin',-40,40}, 'DisplayName','Peak Gain'), ...
audioPluginParameter('Q','Mapping', {'lin',0.2,20}, 'DisplayName','Q') ...
);
end
methods
function plugin = VST_simple3 % クラス名と同じ名前を使ってコンストラクタを定義する
plugin.PEQ = multibandParametricEQ('NumEQBands',1, ...
'Frequencies',plugin.centerFreq, 'PeakGains',plugin.peakGain, 'QualityFactors',plugin.Q);
end
function set.centerFreq(plugin,val)
plugin.centerFreq = val;
plugin.PEQ.Frequencies = val; %#ok
end
function set.peakGain(plugin,val)
plugin.peakGain = val;
plugin.PEQ.PeakGains = val; %#ok
end
function set.Q(plugin,val)
plugin.Q = val;
plugin.PEQ.QualityFactors = val; %#ok
end
function visualize(plugin) % for audioTestBench's "Visualize Plugin"
visualize(plugin.PEQ, 2048);
end
function out = process(plugin,in)
gain = 10^(plugin.inputGaindB/20);
% FrameSize = length(in);
% for fi=1:FrameSize
% Lin = in(fi,1); Rin = in(fi,2);
% out(fi,1) = Lin * gain; out(fi,2) = Rin * gain;
% end
if plugin.PEQ_ON
out = plugin.PEQ(in * gain);
switch plugin.channelMode
case 'LR'
% do nothing
case 'L'
out(:,2) = in(:,2) * gain;
case 'R'
out(:,1) = in(:,1) * gain;
otherwise
% do nothing
end
else
out = in * gain;
end
end
function reset(plugin) % I/F のサンプルレートが変わったときに呼び出される
plugin.PEQ.SampleRate = getSampleRate(plugin);
end
end
end
multibandParametricEQ() を使うと、パラメータを代入するだけで特性がリアルタイムに変わります。
その定義はコンストラクタ内で行います。
GUIを操作すると function set~ が呼び出されますので、ここでGUIの値をフィルターにセットします。
”Process Channel” で、フィルターを掛ける対象を、LR/L/Rから選択することができます。
plugin.PEQ(in * gain) はL/R両方に一遍に掛かるのですが、そこでサイズが決定されて片chだけに掛けるのには使えないため、一旦両chに掛けてから戻しています。処理量は増えるので、それが気になる場合は片ch用のフィルターを別に定義して使います。
また、multibandParametricEQ() は、function visualize(plugin) にこの一行を書いておくと、audioTestBench でのデバッグ時に周波数特性を表示させることができます。
これらは全てフレーム単位の処理でしたが、サンプル単位で処理したい場合は、コメントアウトしてあるforループの中で処理を行います。
VST_LMS
最後に、LMSフィルターを使ってステレオイメージを強調するプラグインを作ってみましょう。
classdef VST_LMS < audioPlugin
properties
inputGaindB = 0;
LMS_ON = false;
lms1, lms2
end
properties (Constant)
PluginInterface = audioPluginInterface( ...
audioPluginParameter('inputGaindB', ...
'DisplayName','Input Gain', 'Label','dB','Mapping',{'pow', 1/3, -80, 6}), ...
audioPluginParameter('LMS_ON', 'Mapping',{'enum','OFF','ON'}, 'DisplayName','Decorrelation') ...
);
end
methods
function plugin = VST_LMS % クラス名と同じ名前を使ってコンストラクタを定義する
plugin.lms1 = dsp.LMSFilter('StepSize',2^-12,'WeightsOutput','None');
plugin.lms2 = dsp.LMSFilter('StepSize',2^-12,'WeightsOutput','None');
end
function out = process(plugin,in)
gain = 10^(plugin.inputGaindB/20);
Lin = in(:,1) * gain; Rin = in(:,2) * gain;
if plugin.LMS_ON
[ylms1,elms1] = plugin.lms1(Rin,Lin);
[ylms2,elms2] = plugin.lms2(Lin,Rin);
M_in = (ylms1 + ylms2)/2;
out = [M_in + elms1, M_in + elms2];
else
out = [Lin Rin];
end
end
end
end
LMSフィルターとは、二つの入力に対し誤差が最小となるようなフィルター係数を求めながらフィルタリングを行うアダプティブフィルターです。LMS(Least Mean Square)自体はシステム同定のための演算手法の一つです。
古くから知られたアルゴリズムですが、LMSフィルターによりLRの相関(誤差最小)成分と無相関(残差)成分を分離し、相関成分をM、無相関成分をL/Rそれぞれに振ることにより、LRの分離を向上させます。
効果がある場合とかえって悪さをする場合もあります。モノラルでは効果がありません。
LMSを、わざわざMATLAB関数を使ってやる必要はないかもしれませんが、デバッグが不要というのは大きなメリットです。まあ、過去にも使ったことあるんでアレですが、本当に数分でできました。(u_u)
いかがでしたでしょうか?
他の言語ではかなり手間の掛かるVSTプラグイン開発が、極めて簡単に行えることが分かっていただけたのではないかと思います。
MATLABとアイデアさえあれば、即VSTプラグインが作れます。
欲しいプラグインは自分で作ってみませんか?(-_☆)