音階の設定
マイコンと音階設定の関係をまとめるとともに、今回の手法の問題点を考察する。
マイコン(ATMEGA168P)での音階を設定する際に、以下の手順に従った。
1) 基準の音となるドの音を定める
2) チューニングを行い、マイコンでドの音を出すループ回数を探索
3) 関係式より相対的に音のループ回数を割り出す
1) 基準の音となるドの音を定める
「ドの音を思い浮かべて下さい」と言われたらどんな音を思い浮かべるだろうか?
ほとんどの方が思い浮かべる「ふつうのド」こそ440Hzのドであり、今回はこのドの音を基準にしてチューニングを行っていく。なお1オクターブ(ドレミファソラシド1周)で周波数は2倍となるので、次の高いドは880Hz、逆に低いドは220Hzとなる。
2) チューニングを行い、マイコンでドの音を出すループ回数を探索
佐瀬くんによるとタイマを使うのが一般的な方法ということだが、今回のオルゴールではfor文で音の出力を行っている。以下が440Hzのドを出力する関数となる。
void DO(int k){ ... for(m = 0; m < k; m++){ for(i = 0; i < 51; i++) PORTD=0x10; for(i = 0; i < 51; i++) PORTD=0x00; } ... }
今回 上のソースコード中の"51"にあたる数字をLabVIEWを用いて調整を行った。パラメータを変更して(物理的には波長を変えることにあたる)51のときに振動数がほぼ440Hzになることを突き止めたので、こちらの数字をドとして採用する。
なお引数にとっているkは音の長さであり、これをそのままループ回数に用いている。このままでは音の長さが音の高さに依ってしまうので、音によって長さが変わらないように上記の関数内であらかじめ規格化を行っている。
3) 関係式より相対的に音のループ回数を割り出す
最後に音を相対的な位置から割り出す。先程書いた通りオクターブでは周波数が2倍になる。全ての音がこの法則に従うには2の累乗に乗る必要がある。値の割り振り方を考えるために鍵盤から音の"離れ具合"について考えてみる。全音を1、半音を0.5として計算すると5(ドレ、レミ、ファソ、ソラ、ラシ)、1(ミファ、シド)の和は6となるので、1オクターブの離れ具合は6と定義する。6を累乗の分母にして計算を行うと(便宜上0.5を分子に乗せたくないので分母を12としている)
のような計算となる。つまり
( 求めたい音の周波数 ) = ( 基準音 ) × ( 2 の累乗[(離れ具合)/12] ))
となる。プログラム内ではfor文のループ回数が調整する対象であり、これは波長にあたるパラメータである。上記の式は周波数を求める式なのでループ回数を求めるときは、2の累乗を掛けるのではなく逆数をとることになる。
問題点
これらの方法では高音においての分解能の粗さが問題となる。グラフが2の累乗にフィットしているので音が高くなると当然勾配が大きくなってくる。つまり高音領域において、for文中の値を1変えるだけで音の高さが大きく変わることを意味している。半音ずれるのは当たり前、むしろ半音の違いが出せないといった問題に直面している状態である。
これらの問題を解決する方法として今後タイマの導入を検討したい。