Rustやっつけフェーズ(5) FFT

前回まででアナログクロックはボタン操作での時刻合わせと、ショボいながらもトースト通知が出来るようになった。 そうなると次はボタンに触れずに時刻合わせをするリモコン操作が視野に入ってくる。
「基礎から学ぶ組込みRust」に掲載のmic_fftを流用し、音でのボタン操作を行う。

まずはこのお方のように正弦波のピッチを周波数表示できるところまでやってみる。 ピッチを取る際の基本的な考え方、閾値や補正を参考にさせてもらった。

また、こちらのお方からは、ダウサンプリング時のポイントを、

こちらのお方からは、双2次(BiQuad)フィルタの作り方を、参考にさせてもらった。

やっつけフェーズとは

規約やモダンな書き方に拘らず作りたいものを作り、動けばいいというフェーズ。

FFT

出来上がり

正弦波の発音は、こちらのお方のページを使用させてもらった。 12平均律と周波数

デザイン

以下の設定でピッチ周波数をLCDに表示する。

項目 設定
サンプリングレート 83333.33hz(固定)
サンプリングデータ 4096個
ダウンサンプリング比 1/4
バンドパスフィルタ 880hzを中心として上下1オクターブ以外をカットオフ
窓関数 ハニング窓(通称ハン窓)
FFT用配列 1024個
閾値 25000以上(単位はよくわからん:経験値)
FFT配列インデックスあたりの周波数幅 20.344hz

フィルタ、窓関数をかけるタイミングは以下のとおり。

  • サンプリングデータ取り出し
    データがなくなるまで以下繰返し
    • バンドパスフィルタ
      カットオフ周波数:800(単位:Hz)
      帯域幅:1(単位:octave)
    • データ間引き
      カウント % 4 = 0なら、ハン窓系数を掛けて
      FFT用配列に格納

この後rfft_1024を呼び出し→512個の結果に対してノルムの二乗を取り、閾値以上かつ現在までの最大値であれば、その配列インデックスをピッチとする。

そして最後に謎の補正をかける。

コード

LCDへの周波数表示はatsamd-wio_terminalのexamplesにあるTerminalを流用。
wio-mic-pitch(main)

wio_fft(FFT)

wio_biquad(双2次(BiQuad)フィルタ)

wio_term(ターミナル表示)

今回はここまで。