hvccをlogue SDK向けに拡張する(4)

引き続き、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に合わせるのが手っ取り早いですが、何か他に方法が無いか、考えているところです。

コメント