電子工作の教材として定番中の定番、電子オルゴールです。今回は機械式オルゴールの音を真似るために、WaveTable方式での音声合成にトライしてみました。その結果、何とかオルゴールのような音を出すことに成功しました。
WaveTable方式のシンセサイザでは、予めサンプリング(または合成)された波形データを種にして音を合成します。これはデジタルシンセ黎明期からある方式で、PC上で最初に普及したのはAMIGAのMODサウンドが最初だったと思います。現在、WaveTable方式はPCのサウンド・ドライバの主流になっています。原理はとても単純で計算量も少なくて済むのですが、波形データをメモリに保持するため、データ量が膨大になってしまう欠点があります。したがって、実際のWaveTable音源ではデータ量を削減するため、主に次のような工夫が加えられています。
オルゴールの音は他の楽器と比べて単純なため、シミュレーションは簡単な方です。アタック期間(櫛歯が弾けた瞬間)は波形の変化が大きく倍音も多く含まれますが、後は単調な減衰振動となり、ノートOFFの処理も必要ありません。WaveTableはアタック期間と持続(減衰)期間に分けられ、図に示すように持続期間はループ再生します。
ノートONにより、トーン・レジスタ(ω)、リード・ポインタ(φ)とエンベロープ・ジェネレータが初期化されます。リード・ポインタはサンプル毎にトーン・レジスタで決まる速度で増加していくので、発生する音階はトーン・レジスタの値で任意に選ぶことができます。この辺の原理はDDSと同じですね。WaveTable参照のとき、ポインタの小数部を使ってインターポレーションをすれば、エイリアスの発生を抑えることができます(今回はしていません)。エンベロープ・ジェネレータは、読み出された波形のレベルを時間と共に変化させて音の減衰を作り出します。減衰速度はωに比例しています。
オルゴールの演奏を真似るためには和音を出せることが絶対条件になります。したがって、WaveTable音源を複数チャネル用意する必要があります。チャネル数の増加ですが、WaveTableは全チャネル共通だから問題ないとしても、CPU負荷には直接影響してきます。このため、チャネル数はサンプリング周波数とのトレード・オフとなります。サンプリング周波数を下げると同時発音数を増やせますが、オルゴールの金属質な響きが犠牲になります。今回は、32kspsで6チャネルとしました。
プログラムの動作は、フォアグランド・プロセスで楽譜データを読み出し、各チャネルを順繰りに叩いていくだけです。WaveTable音源はバックグランド(32kHz割り込み)で処理し、各チャネルの出力を合成、飽和処理してPWM変調器にサンプル値を設定します。何分、同時発音数が少ないので、音符が詰まっているところでは発音中の古いノートが上書きされて消えてしまいます。特に減衰時間の長い低音がぷっつり切れるのが目立つことがあります。
以上の処理をを8ピンAVRのATtiny45に何とか実装することができました。tiny45は内蔵PLLで16MHz動作が可能で、4KBのROMと250kHzの高速PWMを持っているので、外付け部品無しでいけます。WaveTable音源部のCPU負荷率は80%以上になっています。乗算器のあるmegaシリーズならチャネルをもっと稼いだり、演算精度を上げたりできるでしょう。