ATMEL社のワンチップマイコンATtiny2313/ATtiny45をfck= MHzの内蔵クロックで動作させ8ビットPhase Correct PWM機能を用いた場合、

PWM波形の周期はts= /fck= μsで、その周波数成分はfs=1/ts= Hzおよびその整数倍である。この波形自体を音として聴きとるわけではなく、積分回路などの低域通過型フィルタを通して平均値VAVを得る。
出力するアナログ値をサンプリング周期ts= μs毎に変化させることにより、任意のアナログ波形を出力することができる。この性能( Hz 8ビット サンプリング)だけを見れば、CDの品質(44.1kHz 16ビット サンプリング)には及ばないものの、電子オルゴールに用いるには十分な品質の信号を作り出す可能性を持っている。

カウンタを用いて単純な矩形周期信号を生成する場合は、周波数を高い精度で決めることができる。
下図はf= Hzの矩形波を生成する例を示している。周期を
周波数に換算すると

いくつかの周波数について、最大誤差は次のとおりである。
| ノート | 周波数 f(Hz) | N' | 周波数の最大誤差(%) |
|---|
サンプリング周期ts= μsごとに周期波形のアナログ値を出力する場合の周波数の精度について検討する。「私だけの電子オルゴール」では、この方法で減衰矩形波を生成している。
下図はf= Hzの矩形波を生成する例を示している。周期を
周波数に換算すると

いくつかの周波数について、最大誤差は次のとおりである。
| ノート | 周波数f(Hz) | N' | 周波数の最大誤差(%) |
|---|
半音の周波数の違いが約6%であることを考慮すれば(21/12=1.05946)、高い周波数での誤差は無視しがたい大きさである。
以下は誤差をグラフで示したものである。実際に生成される信号の周波数(赤色)は最大誤差を示す青色の線の範囲となる。
110Hz〜1760Hzの各音に対する誤差の計算値を以下に示す。青色の線は生じうる最大の誤差である。
上の方法では1周期の時間Tをサンプリング周期tsの整数倍T'で近似した。ここでは、M周期の時間MTをサンプリング周期tsの整数倍で近似する方法について検討する。以下、M=256とする。
下図はf= Hzの矩形波を生成する例を示している。M周期の時間を
周波数に換算すると

M個の個々の波形の開始時刻XnはM倍の値XnMを

このように、この方法では周期の平均値の誤差を1/Mに改善できるが、各々の波形は±ts/2以内のジッタ(時間軸のゆらぎ)を含んだものとなっていることに注意する必要がある。
M=28=256とすることにより、XnMに(1/2)×256=(0000000010000000)を加えて丸め処理を行うと、上位バイトにXnが得られる。

これまでは波形を矩形波とし、その周期や周波数、あるいは波形の開始時刻だけを問題にした。ここでは、正弦波や三角波など任意の波形を生成する方法を検討する。
1周期分の波形データを予めメモリに用意し(ルックアップテーブル)、それを参照して出力する。
ここでは正弦波のサンプル値として、次のようなNc= 個のデータを用意する。
周波数fの正弦波信号v(t)を生成したい。
下図はf= Hzの正弦波を、サンプリング周期 ts= μsの離散値で表す例を示している。ここでは、周期

このように作られる信号の周期T'は
周波数に換算すると
いくつかの周波数について、最大誤差は次のとおりである。
| ノート | 周波数f(Hz) | N | 周波数の最大誤差(%) |
|---|
半音の周波数の違いが約6%であることを考慮すれば(21/12=1.05946)、高い周波数での誤差は無視しがたい大きさである。
以下は誤差をグラフで示したものである。実際に生成される信号の周波数(赤色)は最大誤差を示す青色の線の範囲となる。
110Hz〜1760Hzの各音に対する誤差の計算値を以下に示す。青色の線は生じうる最大の誤差である。
ルックアップテーブルのNc個のデータは、 T/Nc= μs毎のサンプル値とみなすことができる。しかし、実際のデータ出力はts= μs毎に行われるので、図のように±T/2Nc=± 以内のジッタ(時間軸のゆらぎ)を含んだものとなる。ジッタは、周波数fが高いほど、そして波形のテーブルサイズNcが大きいほど小さくなる。

ここでは、Nc= 個の中からステップ幅
Xsw MはM Nc ts fに対して±1/2以内の誤差とすることができ、作られる信号の周波数をf'とすると、
| ノート | 周波数f(Hz) | Xsw M | 誤差(%) |
|---|
M=28=256とすることにより、XnMに(1/2)×256=(0000000010000000)を加えて丸め処理を行うと、上位バイトにXnが得られる。
Ncを2のべき乗(ここではNc=27=128)とすることにより、AND演算でXnのビット7を0にするだけでXn%128のモジュロ演算ができる。

