FM音源プログラム (30) -- MIDI デコーダ(4)
コントロール・チェンジのデコード
コントロール・チェンジ (およびモードメッセージ) をデコードする md_cc_func() 関数の本体は、switch 文ひとつです。
メッセージの第2バイト、つまりデータバイトの 1 バイト目の MD_2nd 変数の値がコントローラ・タイプを表していますから、この値で処理を分けます。
デコードしているコントローラ (およびモードメッセージ) は次の通りです。
CC値 | コントローラ・タイプ(10進) |
---|---|
0x01 | MODULATION (1) |
0x05 | PORTAMENTO TIME (5) |
0x06 | DATA ENTRY MSB (6) |
0x07 | VOLUME (7) |
0x0a | PAN (10) |
0x0b | EXPRESSION (11) |
0x26 | DATA ENTRY LSB (38) |
0x40 | HOLD1/DAMPER (64) |
0x41 | PORTAMENT ON/OFF (65) |
0x42 | SOSTENUTO (66) |
0x43 | SOFT (67) |
0x44 | LEGATO SW (68) |
0x47 | TIMBRE/HARMONIC CONTENT (71) |
0x4a | BRIGHTNESS (74) |
0x48 | ENVELOPE RELEASE (72) |
0x49 | ENVELOPE ATTACK (73) |
0x4b | ENVELOPE DECAY (75) |
0x4c | VIBRATO RATE (76) |
0x4d | VIBRATO DEPTH (77) |
0x4e | VIBRATO DELAY (78) |
0x54 | PORTAMENT CONTROL (84) |
0x5b | REVERB SEND LEVEL (91) |
0x60 | DATA INCREMENT (96) |
0x61 | DATA DECREMENT (97) |
0x62 | NRPN LSB (98) |
0x63 | NRPN MSB (99) |
0x64 | RPN LSB (100) |
0x65 | RPN MSB (101) |
0x78 | ALL SOUND OFF (120) |
0x79 | RESET ALL CONTROLLERS (121) |
0x7a | LOCAL ON/OFF (122) |
0x7b | ALL NOTE OFF (123) |
0x7c | OMNI MODE OFF (124) |
0x7d | OMNI MODE ON (125) |
0x7e | MONO MODE ON (126) |
0x7f | POLY MODE ON (127) |
この中には、PAN や SOFT など、デコードするだけで、対応する処理をしていないものも含んでいます。
この switch 文は、もともとは md_data_byte() の中にあったものを独立させたものです。
当初は、少数のコントローラをサポートするだけでしたが、次々にコントローラの種類を増やしていくうちに現在のような、case ラベルが数十個並ぶという状態になってしまいました。
case ラベルとの比較が逐次的に行われるようにコンパイルされる場合には、最後の方の case ラベルに到達するのには時間がかかることになります。
RAM に余裕のある場合には、計 128 個のコントローラの値を記録しておく配列を定義しておき、コントローラ番号をインデクスとして値をストアするのがスマートな方法です。
コントローラの種類によって、
- そのまま 0 〜 127 の値を記録しておけばよいもの
- -64 〜 +63 の値に変換して記録すれば良いもの
- 1. あるいは 2. の後に、後処理が必要なもの
などがあります。
1. の場合には、コントローラ値配列にストアすれば、それで処理は完了です。
ROM に、後処理の関数へのポインタの配列を定義しておけば、後処理の選択も簡単になります。
今後は、この方向で書き換えることを考えています。
データ・エントリ MSB / LSB では、NRPN / RPN デコードのための decode_nrpn() / decode_rpn() 関数を呼び出します。
NRPN / RPN デコードの話は次回にします。