KORG NTS-1で自作オシレータを鳴らしてみたいっ!
最近KORGさんとDOTEC-AUDIOさんが絡んで面白い企画をやってるんです。自作エフェクタを作ろうっていう。
ハードウェアを自作するというわけではなく、NTS-1というKORGさんが作ってる組み立て式の小さなシンセを使ってその上で動くエフェクタをソフトウェア的に作っていく企画です。面白そうなのでぼくも乗ってみました!
NTS-1とは
KORGさんが発売しているコンパクトな組み立て式のシンセです。さらにはカスタマイズ可能で自分好みのシンセを作れちゃうんです!KORGからは電子機器版のレゴブロックのようなlittleBitsというものが発売されていますがこちらはあくまでシンセ。もっと音楽的でプロダクションレベルで使えてしまうほどイイ音します。
Logue SDK
KORGさんから提供されているLogue SDKというソフトウェア開発用のライブラリを利用すると自分でオシレーターやエフェクタを作って、SDKに対応している実機に読み込ませて使うことができるんです。
ぼくは今までオーディオプログラミングなんてしたことなかったんですが今回の企画を見て面白そうだからやってみようと早速手を出してみた次第です。NTS-1は値段的にも手頃で気軽にチャレンジできるのが嬉しいですね。
NTS-1の組み立て
ぜんぜん難しくないです。食玩のプラモデルくらい。けれど入らないネジが一本。ま、このくらいはいいんじゃないかと。
で、組み上がって普通のシンセっぽく音も出たので組み立て完了です!なかなか図太い音が出るんですよ。
Logue SDKの環境整備
さて、ソフトウェアを組み込んでいくためにはSDKを使ってビルドしたものをライブラリアンと呼ばれるソフトウェアを使ってNTS-1に転送する必要があります。
XcodeはもうMacに入っているのであとはLogue SDKの環境を整備していきます。
ドキュメントに書いているんですけど
* gitのサブモジュールもちゃんと取ってくる
* GNU Arm Embedded Toolchainもスクリプト叩いてインストールしておく
これらを忘れないように。
あとは
platform/nutekt-digital/demos/waves
でmakeコマンド叩いてきちんとビルドできるかを確認します。
ここにだいたい必要な情報が書かれているので何度も読みなおしました。
カスタムオシレーターを読み込ませてみる
モジュラーシンセの有名メーカーMutable Instrumentsでは、作者のÉmilieさんがオープンソースで製品情報を公開してくれています。その中にPlaitsというオシレーターモジュールがあり、ArturiaのMicroFreakというシンセなんかにも利用されています。
オープンソースということはこれを利用してNTS-1に組み込めちゃうんじゃないかなーと調べてみたらすでに先人が移植してくれていました。
ここからソースをローカルマシン上にGit cloneしてsubmoduleを整えてmakeコマンドを打つだけでPrologueやMinilogue XD、それとNTS-1用のPlaitsオシレータが生成されます。
なんとかんたんな・・・。
ほかにも有志の方によりLogue SDK用に有償無償含めいろんなカスタマイズソフトウェアが提供されています。
Visual Studio Codeで環境構築
さて、もうちょっと開発しやすくしたいなと思ってVisual Studio Codeで使えるようにならないかなーと調べてみたらやはりここにも先人が。
ありがたく使わせていただいてます。VSCode用の設定も済んでるし、Logue SDKのソースもいい感じに整理されています。さらにはデバッガとの接続も考慮されているようです(さすがにデバッガ揃えるまでには至らないですけど)
使い方はとっても簡単で、Templateと名のついているディレクトリを複製して自分の都合の良い名前に変更してソースを作成しメタファイルの記述を修正してmakeコマンドを叩くだけです。
この環境では
$ make PLATFORMS=nutekt-digital
という感じにmakeコマンドを利用するとNTS-1用のものだけビルドできて便利。
自作オシレーターへの道
KORGさんとDOTEC-AUDIOさんの企画ですでにFXをやっているので自分はオシレーターを作ってみようと思い、サンプルソースを見て勉強しています。オーディオプログラミング自体初めてだしC++もついこないだかじり始めたばかりだしでいろいろわからないところだらけですが少しづつ進んでいるような気が・・・してます。
Logue SDKでオシレーターを書く際のキモはOSC_CYCLEという周期的(?)に呼ばれる関数で、その中でいろいろと計算してバッファにサンプルを書き込んでいく必要があります。
ハードウェアに書き込む必要があるだけにいろいろとお約束的なものがあって苦労しました。それでもだんだんとソースを読めるようになってきましたよ。
まずはサイン波を出力するオシレーターのサンプルファイルを見て勉強するところから始めました。
で、ちょっと難しかったのでハードウェアに書き込まずとも手元で何をしているかわかるように、Logue SDKを使わずに動くようソースをいろいろ組み替えてみました。
void OSC_CYCLE(const user_osc_param_t * const params, const uint32_t frames) {
const uint8_t flags = s_state.flags;
s_state.flags = k_flags_none;
// pitchは16bitなんだけど上位8bitがnoteを表すのに使われて下位8bitはファインチューニング
const float w0 = s_state.w0 = osc_w0f_for_note((params->pitch)>>8, params->pitch & 0xFF);
std::cout << "w0:" << w0 << std::endl;
// リセットフラグが立っていればフェーズは0にリセットされる
// ちなみにNOTE_ONでリセットフラグが立つ
float phase = (flags & k_flag_reset) ? 0.f : s_state.phase;
for (int i = 0; i < frames; i++) {
// フェーズを元にosc_sinfで今のオシレーターの出力を取り出す。
// osc_sinfの出力範囲は -1.0 から 1.0 まで
// osc_softclipfに0.05が渡されているので sig は -0.95 から 0.95 までの範囲にクリップされる
const float sig = osc_softclipf(0.05f, osc_sinf(phase));
std::cout << "sig " << i << ": " << sig << std::endl;
std::cout << "phase" << i << ": " << phase << std::endl;
phase += w0;
phase -= (uint32_t)phase;
}
s_state.phase = phase;
}
こんな感じの関数を作って観察して何をしているのかようやくわかるようになりましたよ!sigとphaseをグラフにプロットしてみたら綺麗に正弦波が出力されているのが分かります。(ちなみにosc_sinfはsin(2 * M_PI * x)を返すようにしたので当然と言えば当然なのですが・・・)
osc_softclipのおかげでsigに0.05ぶんの余裕ができているのもだいたい分かります。
Logue SDKに含まれている元のosc_sinfはルックアップテーブルを利用して計算量を減らしています。要するにsin関数を使って計算しないようにしているんですね。取りうるphaseとsigの組み合わせを全て格納しておいてphaseを渡すとO(1)でsigを返せるようになっています。さらにいうと上のグラフでいうところの左半分にあたる部分しかルックアップテーブルに格納していません。左と右で違うのは正か負の違いしかないですから半分でいいですよね。さらに突き詰めれば1/4でもいいはず。パズルみたいで楽しい。たぶんウェーブテーブル使う場合もこんな感じなんだろうなー。ちなみにルックアップテーブルを利用することで正弦波の形を作り込めるので往年のアナログシンセの正弦波の波形を取り込めばその形で出力できますね。アナログモデリングシンセってこういうことなのかな。
で、上のソースを見るとわかるようにパラメータで渡ってくるピッチが大きいとフェーズが進むのが速くなります。噛み砕いてみると以下のような処理になっています。
float phase = 0.f;
float w0 = params->pitch;
for {
folat sig = osc_sinf(phase)
phase += w0;
// 整数桁をマイナスすることでphaseの取りうる範囲を1.f未満にする
phase -= (uint32_t)phase;
}
周期が早いってことはつまり高い音が出るってことなんですね!最初は息巻いて自作オシレーターだと思っていましたが、今はもう少しじっくりと理解しながら進めるのが自分にあっているようです。
ちょっと難しいけどめっちゃ楽しい!
さいごに
サンプルソースのサイン波オシレーターをNTS-1に読み込ませて、MacのDAWから鳴らしてみるところまではできました。もっといろいろ調べて自作のオシレーターを作れるようになりたいな。