1. 初めに
C++ を使って存在しないサウンドチップのエミュレータ(?!)を作りました。
チップチューンに触れていると、「こんな機能があったらもっと多彩な表現ができたのに」だとか、「こんなサウンドチップがあったらこんな音楽ができるな」とかなどの妄想を膨らませてしまいます。それを実現するために、サウンドエンジンを一から設計し、(Roo Codeの力を借りながら)MIDIに対応させました。
フレームワークにはJUCEを使用しています。 JUCEは AGPLv3/JUCE License のデュアルライセンスですが、今回はAGPLv3として使用します。
リポジトリ
2. 仕様
自作サウンドチップの名前は3HS88PWN4です。 (src3453's Harmonic Synthesizer, 8 channels × 8 operators, PCM, Wavetable, Noise × 4 channels)
基本的にはFM音源ですが、FM以外にもいろいろな合成モードがあるので Harmonic Synthesizer と命名しています。
3. 設計
3HS88PWN4 をJUCEから呼び出し (AudioCallback()), JUCEの processBlock() から 3HS88PWN4 の内部レジスタを更新して音を鳴らします。
PluginProcessorで、 MIDIメッセージの処理、3HS88PWN4のAudioCallback()の呼び出し等を行います。
パッチバンク (MIDIプログラム番号とレジスタ値のセット) はJSONから読み込みます。
また、ドラム再生に使用するPCMサンプルも、直下のディレクトリから読み込んで、8bit PCMに変換し使用します。
3HS88PWN4の実装はAIをあまり使わずにほとんど人力で行いましたが、JUCEに移植するにあたってのコードはRoo Codeをかなり使いました。
ソースに付属しているパッチエディタはPythonとtkinterで作っています。
4. Roo Codeの問題点
実装にはRoo Codeを多用していますが、Roo Codeに限らずAI系のコーディングアシスタントは、(モデルにもよるけれど)ある程度複雑なコードになると、コードの本質を理解できず同じ過ちを繰り返すという問題があります。ほとんどのロジックはAIに生成してもらい、どうしてもAIが生成できなかったところは、手直しをしたり手動で実装をしました。
Claude Sonnet 系列のほうが性能は圧倒的にいいのですが、VSCode LM API経由で利用しているので、プレミアム要求が切れた場合はGPT-4.1とかを使うことになります。
5. 機能
- General MIDI Level1, GS (一部)に対応 (予定)
- メロディ16音 + ドラム8音 (ちなみにこれはGM Level1の必須最低要件です)
内部的には 1つ12音の 3HS88PWN4 を2つ同時に使うことで24音使えるようになっています。 (この構成を3SGUC2Xと呼んでいます)
MIDI信号を入力すると音が鳴ります。MIDIプレイヤーなどで使うときはloopMIDIなどを使ってループバックします。
6. 問題点
- MIDIの処理をprocessBlockごとにしているため、音声バッファのサイズが変わるとMIDIのタイミングが不正確になる
- サウンドエンジンが重い
- エンベロープの管理に問題がある
- GUIが洗練されていない
- バグがいっぱい
- ...
7. まとめ
現状複雑でニッチなプロジェクトでバイブコーディングをするのはちょっときついかも...
ある程度まではやってくれますが、難しくなると人間の補助が必要だと思います。
(これが初のQiita記事でした。読んでくれてありがとうございました!)