MATLABでIR(Impulse Response) Speaker Simulator VST Plugin 3

Impulse Response(IR)から応答特性のシステム同定を行って、同等の特性のエフェクトを作ってみる話の第3弾で、いよいよVST Pluginを生成した。

###前の記事
[MATLABでIR(Impulse Response) Speaker Simulator VST Plugin 1]
(https://qiita.com/SacredTubes/items/7ddc99edf33e91ef6c0e)
[MATLABでIR(Impulse Response) Speaker Simulator VST Plugin 2](https://qiita.com/SacredTubes/items/6342b8000251194a921d)

##MATLAB Class
MATLABからVST Plugin生成するにはクラスファイルを作成する必要がある。これは通常の関数型のMATLABファイルではなく、オブジェクト指向で書いたコードで、propertiers, methodsに各種属性があったり、文法が若干異なったりしてちょっと難しい。
親クラスを継承して、機能を引き継ぐという概念があって、それを行頭に書く。
例えば信号処理用のクラスSystem ObjectとVST Plugin生成に必要なaudioPluginを継承するとこんな感じ。

```matlab:
classdef IRSpeakerSim < matlab.System & audioPlugin 
end
```
System ObjectはSimulinkに取り込むことができたり、中でSystem Objectクラス（dsp.FIRFilter）を使っていたり、setup/step/resetといったメソッドが予め定義されていて使いやすいため使っている。

処理用のコードはたった1行

```matlab:
out = step(obj.hFilter, in, temp)*10^(obj.inputVol/20);
```
だけだけど、VST Pluginにしたときのパラメータ等々入れるとこんなコードになった。


```matlab:
classdef IRSpeakerSim < matlab.System & audioPlugin 
    properties
        SpeakerType = 'VHTVintage2x12';
        inputVol = 0;
    end
    properties (Constant)
        PluginInterface = audioPluginInterface(...
            'PluginName', 'IR Speaker Simulator', ...
            'InputChannels', 1, ...
            'OutputChannels', 1, ...
            'VendorName', 'SacredTubes', ...
            'VendorVersion', '1.0.0', ...
            audioPluginParameter('SpeakerType','DisplayName', 'Speaker Type', 'Label', 'Type', 'Mapping',...
            {'enum', 'VHTVintage2x12', 'BoogieRectiVintage2x12', 'BoogieRectiModern2x12', 'SealedVintage4x12',...
            'OpenVintage2x12'},'Layout',[2,2], 'DisplayNameLocation','Left'),...
            audioPluginParameter('inputVol','DisplayName', 'Input Volume', ...
            'Label', 'dB', 'Mapping', {'lin',-20,+20},...
            'Style','rotaryknob', 'Layout',[4, 2], 'DisplayNameLocation','Left'),...
            audioPluginGridLayout('RowHeight',[20,20 20 150 10],...
                'ColumnWidth',[100 200])...
            )
    end
    properties(Access = private)
        hFilter
        num
    end

    methods
        % Constructor
        function obj = IRSpeakerSim(varargin)
            % Support name-value pair arguments when constructing object
            setProperties(obj,nargin,varargin{:})
        end
    end

    methods(Access = protected)
        %% Common functions
        function setupImpl(obj)
            % Perform one-time calculations, such as computing constants
            obj.hFilter = dsp.FIRFilter('NumeratorSource', 'Input port');
            temp = coder.load('filterCoef.mat');
            % temp.num = [ones(5,1) zeros(5, 10)];    % for test
            obj.num = temp.num;

        end

        function out = stepImpl(obj,in)
            % Implement algorithm. Calculate y as a function of input u and
            % discrete states.
            switch obj.SpeakerType
                case 'VHTVintage2x12'
                    spSel = 1;
                case 'BoogieRectiVintage2x12'
                    spSel = 2;
                case 'BoogieRectiModern2x12'
                    spSel = 3;
                case 'SealedVintage4x12'
                    spSel = 4;
                case 'OpenVintage2x12'
                    spSel = 5;
                otherwise
                    spSel = 1;
            end
            temp = obj.num(spSel, :);
            out = step(obj.hFilter, in, temp)*10^(obj.inputVol/20);
        end

        function resetImpl(obj)
            % Initialize / reset discrete-state properties
            reset(obj.hFilter);
        end
    end
end
```
##オーディオ信号を入力してテスト
まずはこれに音楽信号を入力してテストする。
テストは
```>> audioTestBench```
でテストベンチを起動。下のようなGUIが出てきて、入出力ファイル/デバイスを設定してテストできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/d700931b-3091-b29f-2a18-2d7c998c40ea.png)

##VST Plugin生成
ちゃんと動作したらいよいよプラグイン生成。たったこれだけでVST Effectが作れてしまう。。。
```>> generateAudioPlugin('IRSpeakerSim')```

コードにエラーが無ければフォルダにVST Pluginのファイル*.dllが生成されているので、それをDAWのEffect用フォルダにコピーすれば使える。

MATLABで実行しているのと見た目は変わらないが、こっちはDAW上で自動生成されたVSTでエフェクトをかけている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/befcc8ce-6e3d-f2bc-8fba-78ade47b78d3.png)

終わり