見出し画像

MATLABでGUI付きアプリ開発 ~ App Designer を使おう(1)~フィルター特性を変えてグラフ表示

MATLABでGUI付きアプリ開発 ~ App Designer を使おう(2)~ストリーミングオーディオをフィルター処理

MATLABでGUI付きアプリ開発 ~ App Designer を使おう(3)~タイマー割り込みでスペクトル表示(非同期FIFOを使う)

MATLABでGUI付きアプリ開発 ~ App Designer を使おう(4)~ フィルター周波数・バンド幅をマウスで操作

前書き

MATLABでGUI付きプログラムを書く方法は何種類かあります。

SimulinkDashboardカスタムGUI
SimulinkでカスタムGUI

ちょっと試すなら Live Editor

オーディオ系の処理で、操作GUIのみで良いから高速化したいときは VST化(要 AudioToolbox)、
MATLABでVSTプラグイン開発 [初級編]~数分?で作れるVST~LMSで無相関プラグイン
夏休みはVST! MATLABで楽々(?)VSTプラグイン開発

しかし、もう少しGUIに凝りたい場合や、他の人と共有したい場合は App Designer が適しています。

MathWorks のオススメも App Designer です。
Getting Started with App Designer

複雑すぎると編集動作もかなり遅くなったりとかしますが。(;¬_¬)
(15000行超えたヤツ、エディターが終了できない・・。)

以前の記事 MATLAB/Simulink で気軽に始める音響信号処理 ~ App Designer で GUIアプリも簡単開発!でも App Designer には触れているのですが、そこそこ機能を詰め込んだのにろくに説明もしていなかったので、今回はもっと単純な例で順を追って解説したいと思います。

一部重複する部分もありますがご容赦ください。

デモの関係で Audio Toolbox を使っていますが、App Designer 自体は MATLAB の基本機能なので、同様のやり方で何にでも使えると思います。

MATLAB Compiler があればスタンドアローンアプリ化できますが、HOME版にはMATLAB Compiler製品自体がないので、HOME版では毎回 appdesigner から、もしくはMATLABコマンドウィンドウからmlappファイルを起動(拡張子なしのファイル名で起動)する形になります。


実際にコードを書いてみよう!

オクターブフィルター

スクリプトで

> octFilt = octaveFilter();
> visualize(octFilt);

とすれば、デフォルトの中心周波数 = 1kHz、バンド幅 = 1 octave のフィルターオブジェクトが生成され、その周波数特性が表示されます。

画像
オクターブフィルター
デフォルト周波数特性

ここでさらに、

> octFilt.CenterFrequency = 100;
> octFilt.Bandwidth = '1/12 octave';

とすれば、特性が変わりグラフも更新されます。

画像
オクターブフィルター
特性を変更

このオブジェクトには、
freqz():周波数応答
getFilter():biquadフィルターオブジェクト変換
なども使用できます。

もちろん、オーディオデータに対して処理を掛けることもできます。

とても便利な関数なので、これを題材に使います。

起動

> appdesigner

で起動し、目的に近いテンプレート、もしくは空のテンプレートから作ることができます。ここで短い対話式チュートリアルを見ることもできます。

画像
App Designer スタートページ

メニューの 新規 -> アプリ または アプリタブの「アプリの設計」でも起動できます。

今回は、「空のアプリ」を選択します。
「名前を付けて保存」で、OctaveFilter1.mlapp として保存します。

次回からは、コマンドウインドウで

> appdesigner OctaveFilter1

と打つか、
ファイルビューで mlapp ファイルをダブルクリックします。

GUIコンポーネントの追加

左ペインのコンポーネントライブラリからコンポーネントを選んでキャンバスに置き、右ペインでラベル等プロパティを書き換えます。

画像
コンポーネントライブラリ 1/2
画像
コンポーネントライブラリ 2/2


・ドロップダウン(BandwidthDropDown)
 ラベル:Bandwidth
 Value、Items を消します(後でコード内で設定します)

画像
BandwidthDropDown

・スピナー(CenterFrequencySpinner)
 ラベル:CenterFrequency
 Value:1000
 Limits:20,20000
 Step:100
 RoundFractionalValues:✔
 とします

画像
CenterFrequencySpinner

・座標軸(UIAxes)
 Title String:Octave Filter
 XLavel String:Frequency (Hz)
 YLabel String:Gain (dB)
 とします

画像
座標軸

右ペイン最上部に表示されているのがコンポーネント名ですが、ダブルクリックで書き換えることもできます。コードを書いた後でも、ここで変更するとコードは自動的に修正されるので、自分でいちいち直す必要はありません。


ここから「コードビュー」に切り替えて、実際のコードを書いていきます。

プロパティ

使用する変数やオブジェクト等の宣言をします。

左ペインのコードブラウザー -> プロパティ -> ➕ とすると

Property % Description

と表示されて自動的にそこに移動するので、以下のように書き換えます。

properties (Access = private)
    fs = 44100; % sampling frequency
    octFilt % octave filter object
end


コールバック

各GUIコンポーネントを操作したときの動作を記述します。
一旦「設計ビュー」に戻り、各コンポーネントを右クリック -> コールバック -> ~コールバックの追加、でコールバックを生成します。

作成後は、
 各コンポーネントを右クリック -> コールバック -> ~コールバックに移動
でそのコード部分に飛べます。

・BandwidthDropDown
 
Bandwidth で選択した値をオクターブフィルターにセットし、周波数応答描画関数(後述)を呼び出します。

function BandwidthDropDownValueChanged(app, event)
    value = app.BandwidthDropDown.Value;
    app.octFilt.Bandwidth = value;
    drawFrequencyResponse(app);
end


・CenterFrequencySpinner
 同様に CenterFrequency で設定した値をオクターブフィルターにセットし、周波数応答描画関数を呼び出します。

function CenterFrequencySpinnerValueChanged(app, event)
    value = app.CenterFrequencySpinner.Value;
    app.octFilt.CenterFrequency = value;
    drawFrequencyResponse(app);
end

コールバックを消したいときは右クリックで削除します。

コードビューで勝手に書いたり消したりしてしまうと、コードブラウザーと整合が取れなくなることがあるので注意してください。


内部関数

内部で使うサブルーチンを定義します。
左ペインのコードブラウザー -> 関数 -> ➕
drawFrequencyResponse と入力して、周波数応答グラフを描画する関数を定義します。
返り値は必要ないので削除します。

function drawFrequencyResponse(app)
    [h,w] = freqz(app.octFilt);
    hdB = 20*log10(abs(h));
    semilogx(app.UIAxes, w/(2*pi)*app.fs, hdB);
    grid(app.UIAxes, "on")
    xlim(app.UIAxes, [20, app.fs/2])
    ylim(app.UIAxes, [-80 0])
end


startupFcn

アプリ起動時に実行されるブロックです。

右ペイン[コンポーネント ブラウザー] の階層最上位のアプリノード(OctaveFilter1)を右クリックし、[コールバック] 、 [StartupFcn コールバックの追加] で追加します。

画像
startupFcn の追加

先ほど消した BandwidthDropDown の設定(Items、 Value)と、デフォルト設定での周波数特性グラフを描画します。

function startupFcn(app)
    app.BandwidthDropDown.Items = {'1 octave', '2/3 octave', '1/2 octave', ...
        '1/3 octave', '1/6 octave', '1/12 octave', '1/24 octave', '1/48 octave'};
     app.BandwidthDropDown.Value = '1 octave';

    app.octFilt = octaveFilter; % octave filter object 

    drawFrequencyResponse(app);
end

BandwidthDropDown.Items は「設計ビュー」の右ペインで手動で入れても良いのですが、今回は長いのでコード上で入れています。セル形式で入れます。
こちらも返り値は必要ないので削除します。


UIFigureCloseRequest

最後に、設計ビューのコンポーネントがないところで右クリック -> コールバック で、UIFigureCloseRequest を追加し、
 release(app.octFilt)
を入れておきます。

画像
CloseRequestFcn の追加
function UIFigureCloseRequest(app, event)
  release(app.octFilt)
  delete(app)
end

これでオクターブフィルターの中心周波数とバンド幅を指定して、その周波数応答を表示するGUIアプリができました。

自分で追加したコードは以下の部分のみです。

    fs = 44100; % sampling frequency
    octFilt % octave filter object

    
    function drawFrequencyResponse(app)
        [h,w] = freqz(app.octFilt);
        hdB = 20*log10(abs(h));
        semilogx(app.UIAxes, w/(2*pi)*app.fs, hdB);
        grid(app.UIAxes, "on")
        xlim(app.UIAxes, [20, app.fs/2])
        ylim(app.UIAxes, [-80 0])
    end
    

        app.BandwidthDropDown.Items = {'1 octave', '2/3 octave', '1/2 octave', ...
            '1/3 octave', '1/6 octave', '1/12 octave', '1/24 octave', '1/48 octave'};
        app.BandwidthDropDown.Value = '1 octave';

        app.octFilt = octaveFilter; % octave filter object 

        drawFrequencyResponse(app);

        app.octFilt.Bandwidth = value;
        drawFrequencyResponse(app);

        app.octFilt.CenterFrequency = value;
        drawFrequencyResponse(app);

        release(app.octFilt)


実行結果

GIFがアップロードされないので動画で(音声なし)。


画像
実行結果

まとめ


いかがでしたでしょうか?

フィルターの周波数特性を表示させるだけとは言え、わずか20行足らずで一応インタラクティブな GUI アプリが作れてしまいます。

中には、「MATLABでGUIアプリが作れること自体知らなかった!」という方もいらっしゃるのではないでしょうか?

動作スピードや編集時の反応はイマイチな部分もあるのですが、コードの補間機能等もあるモダンな作りで、昔の GUIDE に比べると各段に開発効率が上がっています。

まだ使ったことがない方がいらっしゃったら、ぜひお試しください!


いいなと思ったら応援しよう!

ピックアップされています

MATLAB関連

  • 84本

コメント

ログイン または 会員登録 するとコメントできます。
MATLABでGUI付きアプリ開発 ~ App Designer を使おう(1)~フィルター特性を変えてグラフ表示|leftbank
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1