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 個のコントローラの値を記録しておく配列を定義しておき、コントローラ番号をインデクスとして値をストアするのがスマートな方法です。
コントローラの種類によって、

  1. そのまま 0 〜 127 の値を記録しておけばよいもの
  2. -64 〜 +63 の値に変換して記録すれば良いもの
  3. 1. あるいは 2. の後に、後処理が必要なもの

などがあります。
1. の場合には、コントローラ値配列にストアすれば、それで処理は完了です。
ROM に、後処理の関数へのポインタの配列を定義しておけば、後処理の選択も簡単になります。
今後は、この方向で書き換えることを考えています。
データ・エントリ MSB / LSB では、NRPN / RPN デコードのための decode_nrpn() / decode_rpn() 関数を呼び出します。
NRPN / RPN デコードの話は次回にします。