TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

CQTでスペクトログラムを描く その2(周波数分解能を上げる)

前回実装した高速化CQTによるスペクトログラムは、周波数分解能が低く、ピークが隣の半音のビンに漏れ出していた。

原因を調べて、周波数分解能を上げる対策を行った。

CQTの高速化による影響

An efficient algorithm for the calculation of a constant Q transform」によるCQTの高速化は、この実装では効率化のためスペクトルカーネルの実部(cos成分)しか扱っていない。
また、カーネルの値がほとんど0の要素を削除して疎行列にしている。

また、位相がずれても、スペクトログラムに時間方向の明暗の縞模様が表れないように、複素数内積の計算で、本来負の周波数で打ち消されるはずの虚部についても、正の周波数にスペクトカーネルを適用している。

これらの効率化による誤差が影響していないか確認するため、CQTを定義通り計算したスペクトログラムを並べて表示するようにした。

周波数分解能を上げる

隣接するビンに漏れるのは、窓関数のサイドロープが隣のビンに被ることが原因のため、窓長を長くするのが直接的対策になる。
CQTで窓長を長くするには、オクターブ当たりのビンの数を増やす必要がある。
合わせて、最小の周波数を変えないようにするにはFFTSIZEも同じ比率で増やす必要がある。

窓長を長くすると、時間分解能が下がるため、トレードオフになる。

オクターブあたりのビン数を前回の2倍(=24)にした場合、時間分解能は、最低周波数(F#1)で 737 ms になる。

スペクトログラムの放物線補間

ピッチがビンの中心周波数からずれる場合、エネルギーが隣接するビンに分散される。
それでは、視覚的にピークが捉えずらくなるため、放物線補間(3点ラグランジュ補間)を行うことにする。

結果

以上の対策を行った結果、スペクトログラムは以下のようになった。


※キーボードのオルガンの音をマイクから入力している。

定義通りCQTを計算した場合と、CQTを高速化した場合で、見た目の違い小さい。
高速化による誤差の影響は実用上はないと言える。

周波数分解能を倍にして、放物線補間を行ったことで、ピークの色が半音の範囲に収まっている。
また、補間により半音を2つのビンに分割していることがわからないようになっている。

まとめ

高速化CQTによるスペクトログラムで、ピークが隣の半音に漏れないように対策を行った。
結果、ピークの色が半音の範囲に収まるようになった。
ただし、時間分解能は前回の半分になった。