見出し画像

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

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

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

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

まえがき

前回で終わる予定でしたが、追加ネタを思い付いたので。(u_u)

マウスでフィルター特性を変えられるようにしてみます。

グラフ上でマウスをクリックするか左右に動かすと、オクターブフィルターのセンター周波数を、上下でバンド幅を切り替えます。

基本的にはマウス操作に対するコールバック関数を生成し、マウス位置を取得してフィルター特性に反映させるだけです。

ただこの辺りの機能に App Designer が対応したのは比較的最近のようなので、R2019a以降?(マウスポインター形状変更はR2020a以降)を対象としています。

アプリ

これまで同様、(3)に追加する形で書いていきます。(3)とは独立なので、(1)(2)に追加でも動くとは思います。

プロパティ


最後に追加します。

"bandWidths" は前回までは直接入れてましたが、今回は2カ所で使うのでここで宣言しておきます。

    CP = [0 0];  CP_old = [0 0];
    bandWidths = {'1 octave', '2/3 octave', '1/2 octave', '1/3 octave', ...
        '1/6 octave', '1/12 octave', '1/24 octave', '1/48 octave'};


内部関数


・changeFilter

マウス操作時に呼び出す本体です。
マウス位置を取得し内部座標に変換、フィルタープロパティとGUI表示を更新し、グラフ更新を呼び出しています。急激にフィルター係数が変わると何が起こるか分からないため、更新前に内部状態をクリアしています。

        function changeFilter(app)
            app.CP = app.UIFigure.CurrentPoint;  % get current mouse position
            axPos = app.UIAxes.InnerPosition;  % get inner axes position

            reset(app.octFilt)  % clear filter states
            % change center frequency
            % mapping from linear to log
            x = (app.CP(1) - axPos(1))/axPos(3) * (log10(app.fs/2) - log10(20)) + log10(20);
            cF = round(10^x);
            cF = min(cF,app.fs/2);
            cF = max(cF,20);
            app.octFilt.CenterFrequency = cF;  % change filter parameter
            app.CenterFrequencySpinner.Value = cF;  % change GUI value

            % change band width
            y = round((app.CP(2) - axPos(2)) / axPos(4) * length(app.bandWidths) + 0.5);
            y = min(y,length(app.bandWidths));
            y = max(y,1);
            fbW = flip(app.bandWidths);  % reverse order  '1 octave', ... -> '1/48 octave', ...
            app.octFilt.Bandwidth = fbW{y};  % change filter parameter
            app.BandwidthDropDown.Value = fbW{y};  % change GUI value

            app.CP_old = app.CP;  % update previous mouse position
            drawFrequencyResponse(app);  % redraw frequency response graph
            drawnow limitrate
        end


startupFcn

プロパティで宣言し直したので、ここも一応書き換えておきます。

app.BandwidthDropDown.Items = app.bandWidths;

最後に、マウスが動いたときのコールバック初期化(クリア)を追加します。

app.UIFigure.WindowButtonMotionFcn = ''; % reset WindowButtonMotionFcn


コールバック関数


・PLAYButtonValueChanged
while app.PLAY の前に、以下を追加します。

app.CenterFrequencySpinner.Limits = [20 app.fs/2];

前回まではCenterFrequencyの上限を20kHz固定にしていましたが、ファイルを読み込んだときに fs/2 に設定するようにしました。

・UIAxesButtonDown
マウスをクリックしたときに呼び出されるコールバック関数です。
マウスポインター形状を "十字矢印アイコン" に変更、マウスを移動したときのコールバックを生成するとともに、クリック位置もフィルター特性に反映させるため changeFilter() を呼んでいます。

上のグラフ(UIAxes)で、右クリック -> コールバック -> ButtonDownFcnコールバックの追加 で生成し、内部のコード3行を追加します。

ButtonDownFcnコールバックの追加 
    % Button down function: UIAxes
    function UIAxesButtonDown(app, event)
        app.UIFigure.Pointer = 'fleur';
        app.UIFigure.WindowButtonMotionFcn = createCallbackFcn(app, @UIFigureWindowButtonMotion, true);
        changeFilter(app)
    end


・UIFigureWindowButtonMotion

マウスをドラッグしたときに呼び出されるコールバック関数です。

「コールバック関数の追加」メニューの中から "WindowButtonMotionFcn" を選択して生成し、内部のコード1行を追加します。

コールバック関数の追加
WindowButtonMotionFcn の追加
    % Window button motion function: UIFigure
    function UIFigureWindowButtonMotion(app, event)
        changeFilter(app)
    end


・WindowButtonUpFcn

マウスのクリックを離したときに呼び出されるコールバック関数です。マウスポインター形状を元に戻し、マウスを移動したときのコールバックをクリアします。

上と同様に「コールバック関数の追加」メニューの中から "UIFigureWindowButtonUp" を選択して生成し、内部のコード2行を追加します。

    % Window button up function: UIFigure
    function UIFigureWindowButtonUp(app, event)
        app.UIFigure.Pointer = 'arrow';
        app.UIFigure.WindowButtonMotionFcn = ''; % reset WindowButtonMotionFcn
    end


比較ツール

App Designer 専用ではなく汎用ですが、「比較」でソースコードの比較が行えます。追加・削除・変更箇所が分かりやすく表示されるため、これで前回のコードと比較すると変更点の確認に便利です。マージもできます。

比較ツールの起動
「比較」結果例


私はMATLABソース以外でも使ったりします。

実行結果

実行結果


動画はこちら。


スクリプト


まとめ


とても簡単にマウスインタラクティブなGUIにできることがお分かりかと思います。

ぜひ、お楽しみください!


この記事が気に入ったらサポートをしてみませんか?