先日来、製作していた MSP430-CQ によるオルゴールプログラムにエンベロープを付けて取り敢えず完成。相変わらず汚いコードのままなのは御容赦を。
前回の記事で書いたようにエンベロープをリアルタイム計算すると処理が間に合わないため、あらかじめレベルを変えた波形データを用意するという荒業に出てしまった。このデータだけで 4KB 使用してしまうため、4KB 制限版の IAR-EW では Build できない。このため、IAR Systems から 30 日限定の評価版を取得し、これを用いて Build した。近いうちに mspgcc 用に修正する予定。
プログラム補足。
エンベロープは 1/256 秒毎に変化し、約1秒間で減衰、消音する。 波形テーブルの切り替えは波形データ値を設定している16KHz周期の割込み処理内でおこなっているが、これはエンベロープ値の切り替わる時だけにすれば良い。周波数の高い音のエンベロープは短くしたほうがそれらしくなる。const signed char *const wavTbl[] = {...};
ticks は発音タイミング。128tick で約1秒。この例では60tick を4分音符ひとつ分としている。note は4音まで。同じタイミングの最後の音には EON (最上位ビット)を立てて識別フラグとする。次のタイミングの発音で一番目の音から切り替わるため、長い音は後に並べる。発音にエンベロープを適用して、シーケンスのデュレーションを省略している。曲の最後は note = EOS (0xff) とすると、シーケンスを初期化して再生を繰り返す。また、BASEFREQ を 512 としているが、実際には 256 であるため、再生音は楽譜データより1オクターブ下になる。ticks(LSB), ticks(MSB), note1 .. noteN | EON,
[追記]
サンプル曲の再生データを FFT 解析すると、この図のように 16KHz 辺りにもピークがあるが、これは量子化ノイズ。サンプリング周波数が 16KHz であるから再生は 8KHz が限度であるし、実際に使用している音はその半分以下だ(理想的な正弦波であり、高調波を含まないものとして)。
そこで 8KHz 以上をばっさりカットし、4KHz 以上もレベルを下げたものが [Menuet-01.mp3] 。やはりローパスフィルタとサブソニックフィルタも入れるべきだろう。DA変換後の波形がもう少し鈍っていたほうがこうした用途には良いのかも知れない。
再生データのキャプチャには MSP430 の DAC0 に 0.1μF(大容量のケミコンのほうが良い) のコンデンサを挟んで PC のオーディオライン入力につなげている。
[2007.02.17 追記]
MSP430F15x/16x ならば、こんな技が使えるらしい。
[2007.02.26 後田さんと hamayan さんに取り上げていただいた記念追記]
上にもちらっと書いていますが、コードが最適化されていないこともあって処理能力を目一杯使ってます。トラ技誌のサンプルでは 6MHz くらいまでで使っているのを 8MHz にしても、音程計算のブレゼンハム処理で基本周波数から上の方に離れていくと計算量が増えて処理時間が割り込み周期を越えるために音程が保てなくなります。高音用には予め間引いたデータを用意して置く手もありかも。更に言えば、このプログラムでは割込みだけで処理をおこなっていますが、別ルーチンでバッファに書き込んで、割込みではそこから出力すればもっと余裕が取れます。
右は FViewD というソフトで音階表示解析をしてみたところ。曲のエンディング部分です。最大4音が同時に鳴っている様子が判るかと思います。
おそらく携帯電話等からは投稿できません。日本語文字列を含まないコメントやトラックバック、および当サイトへの言及を含まないトラックバックは御遠慮いただいております。また、90日以上経過した記事へのコメントはできません。