RX62N 用FM音源プログラム -- TGRX62N (6)

これまで、FM音源プログラムを各種のマイコンに対して移植してきましたが、変更部分は各マイコン固有の差異を吸収する記述、比率で言えば 10 % 程度に限られていました。
音源としての機能本体部分のプログラムについては、この 3 〜 4 年に渡って全く手を入れてませんでした。
RX62N 版のプログラムでは、処理能力に余裕があるので、本体部分の機能拡張にも手を付けることにしました。
まず、大きな「改造」によらず実現できる機能として、

  • オーディオ出力をステレオ化して、コントロール・チェンジ 10 番 (CC#10) の「パンポット」のサポート
  • 内蔵デモ曲を演奏するシーケンサを SMF (Standard MIDI File) 対応のものに変更し、同時発音数の限度まで使った演奏を実現

しました。
ステレオ化といっても、音源自体がステレオの広がりを持つ波形を生成するわけではなく、モノラル、つまり 1 系統の出力を CC#10 のパンポットの指定により L チャンネル側のレベルと R チャンネル側のレベルとのバランスを調整し、ステレオ音場での定位を得るものです。
処理としては簡単なものですが、CPU の処理時間は喰われるので、モノラルの場合に比べて同時発音数が低下することになります。 下に比較の表を示します。

サンプリング
周波数
同時発音数
(モノラル)
同時発音数
(ステレオ)
24 kHz 32 27
30 kHz 25 22
32 kHz 24 20
40 kHz 18 16
48 kHz 15 13

サンプリング周波数により異なりますが、2 〜 5 音分の能力がステレオ化によって低下することになります。
パンポットの値による左右チャンネルの音量変化のカーブは、GM2 (GENERAL MIDI Level 2 Recommended Practice (RP024)) に準拠して、sin/cos カーブのタイプにしてあります。
したがって、パンポットが中央の位置で、L/R チャンネル両方ともレベルは -3 dB となり、L/R を電気信号のまま単純加算すると +3 dB のレベルとなり、元の信号の大きさ 0 dB を超える形となります。
一般に「コムフィルタ」型と呼ばれる、最も簡単なディジタル・エコーの処理を、遅延時間 100 ms 程度のものを 1 本だけ組み込んでありますが、これは変更していないので、エコーの部分についてはモノラルのままです。
内蔵デモ曲のシーケンサとしては、これまでは SMAF (Synthetic music Mobile Application Format) 規格の「Handy Phone Standard」フォーマットのシーケンス・トラック・データを解釈するものを使用していました。
SMAF 形式を採用したのは、シーケンス・データのサイズが小さくなることと、シーケンサの実現が容易であることが大きな理由です。
しかし、そのために、表現能力も低く、「Handy Phone Standard」フォーマットでは、シーケンス・トラックひとつ当たりでは 4 チャンネル分のデータしか格納できません。
これはチャンネル数の制約なので、つまり同時には 4 種類の楽器しか使えないということです。
シーケンス・データとして発音数には制約はありませんから、たとえばピアノ演奏のデータであれば、発音数は多くても楽器はひとつですから、シーケンス・トラックひとつで表現できます。
しかし、現状のFM音源プログラムでは MIDI チャンネルひとつ当たり 1 音しか発音できませんから、「Handy Phone Standard」フォーマットの SMAF シーケンサでは 4 音しか発音できないということになります。
チャンネル数を増やしたい場合には SMF (Standard MIDI File) のフォーマット 1 のように、データを複数のトラックに格納しておき、シーケンサでは各トラックのデータを同期して再生することが必要になります。
当然、これはシーケンサ・プログラムが複雑化することを意味するので、この方向に進むことは選択せず、SMAF シーケンサの代わりにフォーマット 0 の SMF シーケンサを実装することにしました。
SMAF シーケンサの場合には、演奏データの作成法として、

  • ユーティリティーで SMF から SMAF に変換
  • プログラムで SMAF ファイルからシーケンス・トラック・チャンクを抜き出し、C 言語の初期化定数付き配列に変換

というステップを踏んでいました。
今回実装した SMF シーケンサでは、フォーマット 0 の SMF データそのものを受け入れるようになっているので、目的の演奏データの SMF そのものを C 言語の初期化定数付き配列に変換してソース・ファイルに組み込み、コンパイルすればよいようになっています。