スペクトログラム編:wxPythonで信号処理のGUIアプリをつくろう④

  • このエントリーをはてなブックマークに追加
Advertisements

Pythonによる信号処理のGUIアプリ作成挑戦記第4弾は「スペクトログラム編」です。平均化フーリエ変換ができるとすぐ実装可能なSTFT計算を復習しながら、どうやってGUIプログラミングに組み込んでいくか、特有の例外処理も含めて紹介します。

こんにちは。wat(@watlablog)です。ここでは信号処理分野でとりあえず見ておこうというくらいポピュラーなスペクトログラム表示をGUIで書きます

バックナンバー

この記事は以下の記事の内容を前提とした続きものです。
是非こちらの記事も読んでみてください。

①アプリ構想とフレーム構築編

フレーム構築編:wxPythonで信号処理のGUIアプリをつくろう①」の記事で信号処理のGUIアプリを作り始めました。

この記事はどんなコンセプトでアプリを作るのか、各GUIをどうやって作っていくのか、開発環境や実際に作ったGUIコードを紹介しています。

②波形読み込み編

波形読み込み編:wxPythonで信号処理のGUIアプリをつくろう②」の記事ではファイル読み込み部分を実装しました。ボタンによるファイル選択、拡張子制限、matplotlibへのデータ渡しといったコードを紹介しています。

③周波数波形編

周波数波形編:wxPythonで信号処理のGUIアプリをつくろう③」の記事は平均化フーリエ変換を扱いました。平均化フーリエ変換はフレームサイズの条件次第で計算がかからない(オーバーラップ処理ができない)ため、関連の例外処理を施す必要がありました。

この辺りからGUIプログラミングは例外処理がなんとも面倒に感じる部分だと思います。

この記事でやること

Advertisements

STFT計算

スペクトログラム表示はSTFTShort-Time Fourier Transform)という計算を行います。

STFT計算についての詳細や、自作のPythonコードは「Pythonで音のSTFT計算を自作!スペクトログラム表示する方法」という記事で紹介していますので、是非中身を知りたい方はこちらの記事をご覧ください。

スペクトログラムの記事と前回の記事をお読みいただくと気付くと思いますが、STFT計算は平均化フーリエ変換を行う処理をほぼ流用しています(最後に平均化しないで2Dマップとして扱うところが差異)。
↓STFT計算のイメージはこちら。

STFT計算のイメージ図

つまりこれまでの記事でdspToolkit.pyに実装したcalc_overlap()fft()といったメソッドをそのまま(一部追加)使うことが可能です。

下図がGUI上でスペクトログラム表示を実装するイメージ図です。
時間波形を読み込んだタイミングで、設定に基づき計算を行うというものです。

GUI上でスペクトログラムを表示させるイメージ図

matplotlibwxPythonで扱うので表示がおかしくならないように自分でコーディングする必要があります(何も考えないとカラーバー無限増殖、プロットが段々小さくなる…といった症状が出ます!)。

それでは早速コードの紹介をしていきましょう!

スペクトログラム表示をGUIで行うPythonコード

Advertisements

dspToolkit.py

def calc_overlap()

最後にdspToolkit.pyに記載した全コードを示していますが、今回のスペクトログラム表示機能実装のためにはcalc_overlap()を少し編集しただけです。

編集箇所はfinal_timeの計算部分です。STFTはフレーム移動をさせながら計算しますが、オーバーラップを考慮してもちょうどよくフレームで割り切れない時は端っこの計算をしません。そのためmatplotlibで正しい横軸の設定を行うためにスペクトログラム用の時間長情報を取得しているというわけです。

全コード

コピペ用の全コードはこちら。

wlFrontPanel.py

def clear_spec_plot(self):

このメソッドはスペクトログラムのプロットをクリアするためのものです。GUI操作中にエラーが発生する等の例外処理時に多用します。

プロットをクリアしないとデータ解析していないのに前の情報が残ってしまうことになるので、ユーザーが誤った判断をしてしまう可能性があります。

これまで書いたclear_freq_plot()のある場所に追記しておきます。

def spectrogram_plot(self, fft_array, final_time):

ここで実際のスペクトログラム表示をします。主にmatplotlibによる表示を行っています。

一度remove()を行ってからプロットするにはこれまでの波形と同様です(カラーバーもcbar.remove()しています)。

このメソッドはフーリエ変換をする時と同じタイミングで使うので、def freq_data_plot(self):の中で呼びだすようにしました。

全コード

全コードはこちら。今回は編集箇所が少ないように思いました。

スペクトログラム表示動作のデモ

YouTube動画による動作確認結果

動作確認はやはり動画が良いということで、いつも通りYouTubeに動画を投稿してみました。

今回は時間波形やcsv波形を読み込んだ時のスペクトグラム表示の挙動を確認しています。フレームサイズのミスマッチ等で計算ができない場合のクリア動作もありますので、是非動画で確認してみてください。

結構サクサク動いてよきですね。

まとめ

今回は平均化フーリエ変換部分のコードをちょっと拝借してスペクトログラム表示機能を実装しました。

多くの例外処理はフーリエ変換と共通しているため、今回はそんなに作業量がなかったと思います。

簡単に実装できましたが、信号のスペクトログラムから得られる情報はかなり多いと思っていますので、GUIでサクサクとファイルを切り替える機能ができたことで便利なアプリになりそうです。

次回はいよいよフィルタリングです。細々とした設定値をやりくりすることになると想定しますが、お楽しみに。
筆者が途中で挫折しなければ…

一つずつ機能実装ができてきました!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

SNSでもご購読できます。

コメントを残す

*