<< 目次に戻る

YM2203・YMZ294・SP0256を使ったハードウエアMIDI音源の製作
音程のデータを求める

音階の周波数を求めるには…

基本中の基本、チューニングに使うラの音は(一般的に)440Hzです。ここから上のドの周波数を求めてみましょう。
数式は以下のとおりです。

式

x にはラから何音上下しているかを指定するので、440*(2^(3/12)) = 523Hz という具合で求めます。
式を見れば一目瞭然ですが、この数式で出現する小数はおろか乗除算ははPICでは扱えませんのでソフトで対応する必要があります。

さて、MIDIのキホンを読んだ方は分かると思いますが、ノートオンのイベントは960usかかります。 これは20MHzで動作するPIC16F877では4,800ステップに相当します。ただし、これを16チャンネル全てで計算を行った場合、 1チャンネルはわずか300ステップしかありません。ランニングステータスルールが適用されると33%減になるので200ステップです。

200ステップ以内でそれなりの精度の小数演算を行い、ベロシティの計算をして音源ICにセットするのは確実に無理でしょう。


音階データはテーブルから読み出すようにする

そこでテーブルリードです。1オクターブ分の音階テーブルを作っておき、そこから値を読み出してレジスタにセットします。 テーブル上の位置を計算するだけなので整数の割り算ルーチンを使えば何とかなりそうです。 オクターブの変更は、テーブルから読み出した値に2を掛ける・割る(1ビットシフトさせる)だけで完成です。

MIDIデータのノートオンイベントについてくるノートナンバーは、0=ド・1=ド#・2=レ…と並んでいます。 これを12で割った値の余りが音階テーブル読み出し用の番号、12で割った商がオクターブになります。 わずか数十ステップで値を求めることができますね。

実際のプログラムでは、ピッチベンド用に半音を64段階に分けた768音階のテーブルを作っています。
数式で表すと、
式
となりますが、12音階の時と比べてもわずかなステップ数しか変わりません。

計算の例

条件
ノートナンバー = 60 (C)
ピッチベンドMSB = 112(+48)
ピッチベンドセンシティビティ = 4
  1. ノートナンバーを64倍(6ビット左シフト)して内部トーンに変換する。60 * 64 = 3,840(F00h)
  2. ピッチベンドの中央からの差分とピッチベンドセンシティビティを乗算する。48 * 4 = 192(C0h)
  3. 基準音からの差を内部トーンに加算する。F00h + C0h = FC0h
  4. 計算が終わった内部トーンを768で除算し、商をオクターブ = 5、余りをトーン番号 = 192とする。
  5. 768通りのトーンテーブルからトーン番号192を読み取る。
トーン番号192とは D#+0 の音になります。

定数テーブルのノウハウ

PICで文字列などの定数をプログラムに埋め込む場合、RETLWを使った定数テーブルを構成することがあります。 Microchipに掲載されているアプリケーションノート「AN556 - Implementing a Table Read」ではデータテーブルをいかにして作るかという内容が書かれており、大変勉強になります。

今回のプログラムでは、768音階のデータをFM音源とSSG音源の2通り持っています。 しかもチューニングが440Hzと444Hzの2種類あるので合計で4つのテーブルが存在することになり、 さらにテーブルに入れるデータは12ビット(つまり2バイト)のデータなので、RETLWで入れようとすると 768 * 2 * 4 で6,144ワードもの巨大なデータになってしまいます。 6,144ワード中のデータには、いらない4ビットのおまけがつくので1,536ワード分のメモリは無駄になります。

今回はPICNICで使われていた手法で、「プログラムEEPROMに生データを埋め込む」方法でテーブルを作りました。 プログラムEEPROMは14ビットで構成されるので、これだけでデータサイズは半分の3,072ワードになります。ただし、PIC自体がプログラムEEPROMを読み出す機能をもっていないとこの方法は使えません。 分かりやすく言えば、データEEPROMの14ビット版という感じです。


<< 目次に戻る