logue SDKで文字列型パラメータにprintfで出力する

logue SDK v2では、パラメータの値の表示に任意の文字列を用いる機能が用意されています。これはheader.cの中で以下のようにパラメータのタイプとしてk_unit_param_type_stringsを指定します。

{0, 4, 0, 0, k_unit_param_type_strings, 0, 0, 0, {"VAR"}},

この例ですと、値としては0~4ですが、それぞれの値に対して任意の文字列を表示させることができます。文字列への変換は、API関数

__unit_callback const char * unit_get_param_str_value(uint8_t index, int32_t value)

を定義して行います。

この機能を使うと、作成したユニットの動作中に任意の文字列を表示することができますので、デバッグに便利です。logue SDKでは出力としては音声チャネルしか使えないのでデバッグがなかなか難しく、SDK1ではデバッグ用の情報を音声データにエンコードしている方もいました。

KORG NTS-1 の audio out でデジタル通信して内部をのぞく方法 :: オシレータ編 - Qiita
はじめにLogue SDK を使うと KORG NTS-1 上で動くカスタム・モジュールを作ることができます。しかし、デバッグ環境などがまだそれほど充実していないので、実機上の動作を手探りで見つけ…

文字列表示の機能を使えば、パラメータ設定のつもりでノブを回せばその時点で上記のコールバック関数が呼ばれますので、観察したいデータをコールバック関数が文字列に変換して返してやればよいわけです。

それでここから本題ですが、この文字列に変換するところでsprintf()が使えれば、フォーマット文字列を使って様々な形式に簡単に変換できて便利です。(実際には、sprintfではなく文字列の長さに上限を設けられるsnprintf()を使います。)

この機能はdrumlogueでの開発の際にも時々使っていました。#include <cstdio>しておけばstd::snprintf()が使えますので、これで内部変数の値を表示させてデバッグしていました。

NTS-1 mkIIでも同じことができるかと試してみたのですが、ビルドは通るものの、それをNTS-1に転送するためにKONTROL Editorにドラッグ&ドロップするとエラーになってしまいました。

objdumpでバイナリを調べてみたところ、*UND*(undefined)になっている関数があり、おそらくこれらをKONTROL Editor側で解決しようとして失敗しているのかと思われます。

$ objdump -t build/printf.elf |grep UND
00000000  w      *UND*	00000000 __sf_fake_stderr
00000000  w      *UND*	00000000 _printf_float
00000000  w      *UND*	00000000 __sf_fake_stdin
00000000  w      *UND*	00000000 __sf_fake_stdout
00000000         *UND*	00000000 midi_to_hz_lut_f

そこで、config.mkに設定を追加して_printf_floatをビルド時に解決するよう明示的に指定すると、動作するようになりました。

ULIBS  =  -lm -lc -u _printf_float

ただ、残念ながらこれによってprintf関連のコードがリンクされる結果、バイナリサイズが22KB弱増えます。(実測、9502バイトが32019バイトに増えました。)許容できないサイズではありませんが、全体で48KBのサイズの半分近くを占めてしまいますので、かなり大きいです。自分で必要なだけの変換用の関数を書けばサイズはかなり節約できると思われます。本当はライブラリで変換関数を提供するか、ファームウェア本体の側にsnprintfをリンクしてもらえると良いのですが。

なお、NTS-1 mkIIでは表示できる最長の文字列は7文字(末尾\0も含めて8バイト)のようでした。

コメント