引き続き、Pure Data→logue SDK変換の話です。
以前、noise~オブジェクトを使うとサイズが大きくなるという話を書きました。hvccが生成するコードを小さくさせる努力をしてみましたが、最終的なユニットのバイナリサイズが28KB超になってしまうのは避けられない感じでした。noise~を使うだけで、許容されるフットプリント上限の32KBの7/8は使い切っていることになるので、なかなか苦しい状況です。
このときの記事で、
[noise~]の代わりになるオブジェクトをlogue SDK側から提供できれば良いのですが、hvccにはコントロール信号は送ることができますが、シグナル(音声信号)を送り込む仕組みは無いようです。
と書いたのですが、シグナルを直接送り込むことはできませんが、[table]オブジェクトのバッファへのポインタを外部から取得することはできることに気づきました。
この機能は、主にPCMデータをPure Dataパッチへ読み込ませるために用意されていると思われますが、バッファを更新し続ければノイズを与えることも可能です。そこで、
名称末尾が”_r”のtableは、バッファの中身を常にホワイトノイズで更新する
という機能を新たに追加してみました。以下がこの機能を使ったノイズ発生パッチです。
ここでは64サンプルのtableを用意しています。64サンプルは、NTS-1においてOSC_CYCLEが1回のコールでレンダリングするサンプル数です。
logue SDK側では、OSC_CYCLEが呼ばれるたびにこのtableのバッファにosc_white()で生成したノイズを書き込みます。
このテーブルから読み出すのは[tabread~]で、[phasor~][* 64]が0~63の読み出し位置を指定します。[phasor~]の周波数は750Hzですが、これはサンプリングレート(48,000)/バッファ長(64)ですので、Pure Data側で1サンプル生成するたびに読み出し位置が1増えるようになっています。
このパッチをhvccでCに変換し、logue SDKでビルドしてみたところ、以下のようなサイズになりました。
$ size build/osc_white.elf
text data bss dec hex filename
16544 2120 3008 21672 54a8 build/osc_white.elf
これなら[noise~]を使う場合よりも6KB以上節約できており、10KB以上のメモリ空間が残っているので、多少は遊べます。
試しに以下のようなKarplus-Strongオシレータを作ってみました。これはCombフィルタを作ったときにちょっと触れましたが、短いディレイを使って共振のシミュレーションをするものです。
これをビルドすると
$ size build/Pluck.elf
text data bss dec hex filename6
19908 2120 10456 32484 7ee4 build/Pluck.elf
となり、32KBぎりぎりです。ディレイラインを30msec(1msecあたり4*48 = 192バイト必要)取っているので、33.3Hz以上の音は一応表現できることになります。
ただ悩ましいのは、前回の記事でちょっと触れたように、NTS-1とprologueではOSC_CYCLEの1回あたりで生成するサンプルの数が異なることです(NTS-1は64、prologueは16)。
この違いはテーブルのサイズに影響しますので、上のパッチのテーブル長も機種ごとに最適化する必要があります。実際、上のNTS-1用にビルドしたユニットはprologueでは異常動作してしまいます。おそらくOSC_CYCLEのたびにosc_white()を64回実行するのが重すぎるのだと思われます。テーブルのサイズを16にしてphasor~を3000Hzにすると正常に動作しました。サイズが16のものをNTS-1で動かした場合は異常動作は起こりません。
機種ごとに異なるPure Dataパッチを用意するか、より条件の厳しいprologueに合わせるのが手っ取り早いですが、何か他に方法が無いか、考えているところです。
Pure dataからKORG logue SDKに変換したオシレータの続き。ちょっと無理して30msec分のバッファを確保し、Karplus-Strongのオシレータをやってみました。これで32736バイト使っているのでほぼ限界・・・。 pic.twitter.com/t4bwTplCic
— boochowp (@boochowp) March 21, 2025
コメント