2017年10月12日

Open.Theremin@半音階ドリフトの謎

昨日からテルミンの楽器としての運用試験を本格化しているが、例の半音階だけ音がズレる現象を考えると、ランダムな周波数の変動ではなく「ほぼ正確に半音分ズレる」ところに問題があり、これはバグの匂いがする。

プログラム上、音階の関係は半音単位で以下のように関数化しているのだが、

double pitch1 = 1.0600;
double pitch2 = 1.1236;
double pitch3 = 1.1910;
double pitch4 = 1.2625;
double pitch5 = 1.33823;
double pitch6 = 1.41852;
double pitch7 = 1.50363;
double pitch8 = 1.59385;
double pitch9 = 1.68948;
double pitch10 = 1.79085;
double pitch11 = 1.8983;


double pitchInc = 0.00006103515625;

これはあくまで基音に対して相対化された値であり、A=440Hzといった厳密なものではない。

音源の音程は、Wavetableを読みだすポインターにオーディオクロックの周期で追加される「データを読み飛ばす係数」によって決定される。 add_valというのがそれだが、そこにピッチの変動を掛けることで、音階を決定していく。

case 35: pointer = pointer + (add_val);
pointer2 = pointer + (add_val);
pointer3 = pointer3 + (add_val * pitch5);
pointer4 = pointer4 + (add_val * pitch7);
pointer5 = pointer5 + (add_val * pitch9);
pointer6 = pointer6 + (add_val * pitch11);
break;


一方、半音階に規定されない自由な音程関係をプリセットする機能はこのような形で実現しているのだが、、、

case 41: pointer = pointer + (tuner);
pointer2 = pointer2 + (tuner * (pot3a * pitchInc ));
pointer3 = pointer3 + (tuner * (pot3b * pitchInc ));
pointer4 = pointer4 + (tuner);
pointer5 = pointer5 + (tuner * (pot10a * pitchInc ));
pointer6 = pointer6 + (tuner * (pot10b * pitchInc ));
break;

この機能を選択し、pot_x を呼び出し、tuner が乗算された結果が”ゼロ”からそれ以上に転じた瞬間に、何故か変動が生じないはずの tuner * (potx * pitchInc) が加算されない pinter2 や pointer5 において音程が変化するのが謎なのだ。

追記:


今一度コードを解析した結果、pointerのデータを元にWavetableを読み込むルーチン

uint16_t offset = (uint16_t)(pointer>>5) & 0x3ff;
uint16_t offset2 = (uint16_t)(pointer2>>5) & 0x3ff;
uint16_t offset3 = (uint16_t)(pointer3>>5) & 0x3ff;
uint16_t offset4 = (uint16_t)(pointer4>>5) & 0x3ff;
uint16_t offset5 = (uint16_t)(pointer5>>5) & 0x3ff;
uint16_t offset6 = (uint16_t)(pointer6>>5) & 0x3ff;
                    
の ”後 ”に、ピッチの設定を行っていることが原因と判明した。 

対策は単純で、pointerの値からWavetableの読み出しを行うoffsetが確定する ”前” に switch/case を選択してしまえば良い。

追記2:

ついでに、pointerに行っていたbitshift命令で1bit分過剰にデータを削っていたことが発覚している。本来は2048ステップのところを1024ステップでデータを扱っていたわけで、大変にマヌケである。 修正後は周波数の再生レンジが広くなり、調整がやり易くなった。

追記3:

追試を行ったところ、若干のピッチドリフトが発生している模様。 つまり、処理に伴う負荷が影響しているものと推測される。
posted by Yasuski at 15:06| open.Theremin