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行を追加します。
% 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行を追加します。
% 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にできることがお分かりかと思います。
ぜひ、お楽しみください!
この記事が気に入ったらサポートをしてみませんか?