前回に引き続き、カスタムコントロールパネルのAPIを使うサンプルを紹介していきます。
前回はメッセージハンドラのプログラミングと、OSCの個数の取得、各OSCの名称などの情報取得を行いましたが、今回はShapeパラメータの送信、OSCのエディットパラメータの取得などを試してみます。
メッセージハンドラは登録可能な7つのハンドラ(パラメータチェンジ、ノートON、ノートOFF、Tick、Value、ユニット情報、エディットパラメータ情報)を全て使用します。
動作としては、コントロールパネルとして使用しているNucleo-F030にはユーザボタンとユーザLEDが1つずつありますので、
●ボタンON
・新しいオシレータを選択
・LED消灯
・ノートオン(ノートNOは64、ベロシティは127で固定)
・現在のOSCの情報をシリアルポートに出力
●ボタンOFF
・LED点灯
・ノートオフ
●常時
・Shapeパラメータを0から1023まで増やす
・MIDIインタフェース経由でのパラメータチェンジをシリアルポートに出力
という処理をさせてみました。
◆◆◆
使用するAPIは以下のものです。
nts1.paramChange(k_param_id_osc_type,k_invalid_param_subid, osc_number);
nts1.reqParamValue(k_param_id_osc_type,k_invalid_param_subid);
nts1.paramChange(k_param_id_osc_shape, k_invalid_param_subid, shape);
paramChangeはメインボードのパラメータを設定し、reqParamValueは現在の設定値をメインボードから取得します。対象となるパラメータはメインIDとサブIDの2つを引数で与えて指定します。
上の最初の二つのメインIDとサブIDの組み合わせは、使用するオシレータを指定します。
3つ目の例は、Shapeパラメータの値を設定します。
2つ目の引数がk_invalid_param_subid
となっていますが、これはサブIDが存在しない場合に使用するようです。
nts1.noteOn(note_num, velocity);
nts1.noteOff(note_num);
ノートオンとノートオフです。
nts1.reqOscEditParamDesc(param_num);
現在使用中のオシレータのパラメータ情報を取得します。引数はパラメータの番号(0~5)です。
情報を取得するAPIでは、前回も書いたとおり、情報はメッセージハンドラ経由で受信します。
今回は、メッセージハンドラでは以下のように情報をグローバル変数に保存するだけです。
nts1_rx_value_t s_rx_value;
nts1_rx_unit_desc_t s_rx_unit;
nts1_rx_edit_param_desc_t s_rx_param;
int s_rx_avail = 0;
void rx_value(const nts1_rx_value_t *val) {
s_rx_value = *val;
s_rx_avail = 2;
}
void rx_unit_desc(const nts1_rx_unit_desc_t *desc) {
s_rx_unit = *desc;
s_rx_avail = 3;
}
void rx_edit_param_desc(const nts1_rx_edit_param_desc_t *desc) {
s_rx_param = *desc;
s_rx_avail = 4;
}
s_rx_availは情報を受信できたことを表すフラグとして用います。(前回の記事参照)
このほか、以下のような4つのメッセージハンドラを用意します。
void rx_param_change(const nts1_rx_param_change_t *param) {
s_rx_avail = 1;
fmtprint("param_change: %d %d %d %d\r\n", param->param_id, param->param_subid, param->msb, param->lsb);
}
void rx_note_on(const nts1_rx_note_on_t *evt) {
fmtprint("note_on: %d %d\r\n", evt->note, evt->velocity);
}
void rx_note_off(const nts1_rx_note_off_t *evt) {
fmtprint("note_off: %d\r\n", evt->note);
}
void rx_tick() {
if (++s_tick % 40 == 0) {
fmtprint("tick: %d\r\n", s_tick);
}
}
最初の3つはコントロールパネルではなくMIDIからイベントを受信した場合にも呼び出されます。例えばNTS1にMIDIキーボードをつないで、モジュレーションホイールを操作するとrx_param_changeが呼ばれます。
最後の1つは周期的に呼びだされるメッセージハンドラです。呼び出し周期はアルペジエイターのテンポと連動しています。NTS1のLEDは最後の桁の小数点がアルペジエイターのテンポと連動して点滅していますが、これにはこのクロックが使われているのでしょう。
テンポは電源ON時は120.0(パラメータ値としては1200)になっています。このとき1 tickは1/8秒(四分音符が1/2秒なので、16分音符相当)となっています。従って、上のコードでは40 tick=5秒ごとに1行メッセージを出力します。なお、アルペジエイターのテンポ設定は上述のparamChangeで行えます(メインIDはk_param_id_arp_tempo、サブIDはk_invalid_param_subid)。
◆◆◆
今回作成したスケッチを動かしている様子です。ボタンを押すたびに新しいオシレータが選択され、その情報がターミナルに表示されます。また、Shapeパラメータはボタンを押さなくても勝手に変化していきます。
最後にコード全体を載せておきます。ちょっと長いですが、前回との重複部分も多いです。
コメント