TadaoYamaokaの開発日記

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

【Androidアプリ】ビブラートモニターを公開

マイクから入力した音声のビブラートをリアルタイムに解析するアプリを作成して、Google Playで公開しました。

音程の波形と、ビブラートの周期(Hz)と振幅(cent)を同時に可視化できます。

また、周期と振幅が一定かを安定度(0~100%)という指標で確認できます。

カラオケや楽器の練習のお供に使ってみてください。

↓ダウンロードはここから
play.google.com


iOS版もそのうち作成します。

開発の話

ボーカル音程モニターは、Javaで開発していましたが、今回はKotlinで開発しました。
Kotlinはほぼ知らない状態でしたが、GitHub Copilot + GPT-5のAgentモードで、とりあえず動くものを生成して、生成したコードをASKモードで確認していくことで、短時間で必要な機能が理解できました。
AndroidのUIコンポーネントも、Jetpack Composeが標準になっていて、View+XMLの開発とは別物になっていました。
値の変更がUIに自動反映されて、コードでレイアウトするスタイルで、Reactの開発に近くなっていました。

ビブラートの解析

ボーカル音程モニターと同じ方法でピッチを解析して、ピッチの時系列データを使って解析しています。

一般的に声楽や楽器演奏におけるビブラートは、3~9Hzの揺れのため、その帯域の周波数成分のピークを検出することで解析できます。
Goertzelアルゴリズムで特定帯域のDFTを計算するか、自己相関関数を使う方法があります。
DFTでは低周波数帯の分解能が足りないので、自己相関関数を使用しました。

自己相関は、O(N^2)の計算量になるため、フレーム間で差分計算することで、計算を省いています。
ただし、平均ピッチを引くことでDC成分を除いていますが、差分計算する場合、平均ピッチの変動で誤差が生じるため、厳密には正しくないですが、計算量を優先しています。

振幅は、正規化前の自己相関のピークの値から、信号が正弦波と仮定した場合の振幅が逆算できます。

安定度は、正規化した自己相関のピークの係数を使用しています。
一定周波数の正弦波の場合、1になります。

振幅の安定度は、ウィンドウを4分割して、ピーク周波数に限定して自己相関を計算し、変動係数(CV)を算出し、1 / (1 + CV)を安定度としています。
振幅が一定(分散が0)の場合は、1になります。


計算量を優先しているので、誤差がありますが、使った感じでは違和感のない指標になっています。

まとめ

ビブラートをリアルタイムに解析するアプリを作成して公開しました。
GitHub Copilot + GPT-5を活用しながら、メインの処理2日 + 調整1日くらいで作成できました。
ビブラートを数値化して可視化できるアプリは、他にはないと思うので、ぜひ使ってみてください。