前回、タブ譜からギター奏法に対応したピアノロールを描画するところまで実装した。
今回は、音声入力とリアルタイムに和音を解析する処理を実装する。
検討事項
音声入力
WASAPI共有モードのイベント駆動で入力する。
サンプリングレートは録音再生時にリサンプリングが発生しないように再生デバイスに合わせる。
スクロール処理
録音中に、現在、タブ譜のどの位置かを示すラインを固定位置に描画し、タブ譜をテンポに合わせて横スクロールする。
録音とスクロールを同期させるため、オーディオフレーム数を基準として時間を計算する。
スペクトログラム描画
演奏した音を可視化するため、ピアノロールの鍵盤と現在位置カーソルの間の領域にスペクトログラムを描画する。
スペクトログラムの解析はCQTのFFTによる高速アルゴリズムを使用した。
タブ譜のノートと弾いた音の差が視覚的にわかるようになる。
ピークが強調されるように、ピーク基準で正規化して、しきい値以下のビンは描画しないようにする。
和音判定
NNLS Chromaで、和音構成音を解析し、タブ譜のノートとの一致を判定する。
単音の場合も共通の処理で判定する。
実装
処理が複雑なため、1度に指示してもできない気がしたが、上記の処理はすべて関連するため、後から追加実装で不整合が起きる方が大変な可能性があるので、一度で指示をおこなった。
CQTとNNLS Chromaは、以前に実装したプログラムをサンプルプログラムとして与えた。
プロンプト
リアルタイムに音声入力し、音程を解析して、MIDIの音程との一致を判定する処理を、Gp5TablatureフォルダにあるC++/WinRT(WinUI3)のプロジェクトに実装してください。 ### 条件 - WASAPI Capture(IAudioClient3 + IAudioCaptureClient)のイベント駆動で音声入力する(WASAPI共有モード) - 音声入力デバイスを選択できる - 再生デバイスはシステムデフォルトを使用する - モノラル、再生デバイスのサンプリングレートで入力する - 録音開始ボタンを押すと録音が開始し、オーディオクロック基準でタブ譜・ピアノロールをスクロールする - 停止ボタンで停止できる - 現在の位置は、タブ譜とピアノロールに縦線で示す - 現在の縦線の位置は、タブ譜の1小節目のト音記号、ヘ音記号、拍子の右側があった位置に固定で表示する。現在位置の縦線が移動するのではなく、現在位置の縦線は固定で、タブ譜・ピアノロールが横スクロールする。 - タブ譜とピアノロールはピアノロールのtickを基準に連動してスクロール - 音声は録音し、スクロール位置から再生できる - スクロール位置から上書き録音できる - 音程解析は、下記サンプルプログラムを参考にCQTとNNLS Chromaを使用する(FFTはプロジェクト内のfft4g.cppを使用) - リアルタイムに音程解析を行い、ピアノロールの鍵盤から現在位置の縦線の左側までの範囲に可視化する - 音程解析結果は保存し、録音停止中は、ピアノロールに解析結果を表示する - スクロール位置から録音上書きする場合は、解析結果も上書きする - ピアノロールのMIDIノートと解析結果は重ねて表示する - 解析間隔は、約30FPSとする(オーディオクロック基準でキリの良い値) - 録音中、音程解析結果とMIDIノートの一致を判定し、一致度合いによって、MIDIノートにエフェクトを表示する ### 参考 - samples/WinCqt.cpp: CQTとNNLS Chromaによる音程解析のサンプルプログラム
マイク入力ができなかったが、数回の修正で、動くようになった。
録音中の自動スクロール処理は修正なしで、実装できた。
スペクトログラム描画と和音解析は、はじめは動かなかったので、サンプルプログラムとの差分をチェックさせることで動作するようになった。
CQTのバンク分割や補間処理は、勝手にパラメータが変更されていたので、何度か差分チェックを繰り返した。
音声解析の部分は、サンプルプログラムなしでバイブコーディングで実装するのは難しいと思う。
アルゴリズムを正確に指示するのも難しいため、一度切り出して別プログラムで検証してから、サンプルプログラムとして与えるのが正解だと思う。


