3

マイコンの音源プログラムを書いています。

ハードウェアタイマーを使用して割り込みをトリガーし、特定の音符の特定の瞬間に信号をハイまたはローに設定する必要があるかどうかを確認します。

私はかなり限られたハードウェアを使用しているので、タイマーの実行が遅いほど、他のことをしなければならない時間が長くなります (シリアル通信、生成する次のノートのロードなど)。

最適な結果を得るには、タイマーを実行する頻度を見つける必要があります。つまり、十分に正確な頻度を生成し、他のことを計算する時間があります。

これを達成するには、再生する必要があるすべての周波数のおおよその LCM を見つける必要があります (周波数が高くなるほど、人間の耳がエラーに気付くには値を不正確にする必要があるため)、再生する必要があるすべての周波数の LCM:この値は、ハードウェア タイマーを実行する頻度になります。

そのような数を計算するのに十分単純なアルゴリズムはありますか? (編集、「十分に単純」を明確にします:8ビットAVRマイクロコントローラで50未満の値に対して時間t << 1秒で実行するのに十分高速で、最悪でも数十行で実装可能です。)

4

2 に答える 2

1
LCM(a,b,c) = LCM(LCM(a,b),c)

したがって、一度に 1 つの周波数を取り込んで、ループ内で LCM を計算できます。

さらに、

LCM(a,b) = a*b/GCD(a,b)

GCD は、ユークリッド アルゴリズムを使用することで因数分解せずに簡単に計算できます。

これを近似 LCM のアルゴリズムにするには、低い周波数を 10 Hz の倍数に丸め、高い周波数を 50 Hz の倍数に丸めるなどの処理を行います。もう少し原則的な別のアイデアは、最初に周波数をオクターブに変換することです (数式は にfマップされると思いlog(f/16)/log(2)ます)。人間の聴覚を超えているため、おそらく切り捨てることができます)。0 ~ 10 を 0.0、0.2、0.4 などの 50 の間隔に分割し、各数値について、そのオクターブに対応する周波数を事前に計算します (オクターブはf = 16*2^oどこにあるでしょうo)。これらのそれぞれについて、一度だけ手で調べて、いくつかの小さな素因数を持つ近くのラウンド数を見つけます。たとえば、 o = 5.4次にf = 675.58-- 675 に丸めます。if o = 5.8then f = 891.44-- 890 に丸めます。これらの 50 個の数値を並べ替えられた配列に組み立てます。二分探索を使用して、各周波数を配列内の最も近い周波数に置き換えます。

于 2016-01-18T00:25:06.780 に答える