5

私はCでマイクロコントローラーDDSプロジェクトに取り組んでおり、出力値を平滑化するために線形補間を計算する方法を理解するのに問題があります。現在のプログラムで
は、24ビットアキュムレータの上位8ビットを、8ビット出力値の配列へのインデックスとして使用しています。アキュムレータの中間バイトと下位バイトを取得し、配列の「前」と「次」の値の間に値を生成する関数を考え出す必要があります。これは高速ハードウェアでは十分に簡単ですが、マイクロコントローラーを使用しているので、浮動小数点演算や除算を行わないようにする必要があります。

これらの制限があるため、2つの8ビット入力番号と2つの入力値の間の「距離」を表すアキュムレータの下位2バイから8ビット補間値を取得する方法がわかりません。アドバイスをよろしくお願いします!

明確化

DDS=ダイレクトデジタルシンセシス

DDSでは、位相アキュムレータを使用してルックアップテーブルから波形が生成されます。位相アキュムレータには通常、整数成分と小数成分が含まれています。整数コンポーネントは、ルックアップテーブルへのインデックスとして使用されます。単純なDDS実装では、小数部分は無視されますが、高品質の出力では、小数コンポーネントを使用して、隣接するルックアップテーブル値間の補間(通常は線形補間)が行われます。上記の質問では、特定の分数fの2つのルックアップテーブル値間でこの線形補間を効率的に実行する方法を検討しています。ここで、は0 <= f < 1です。

4

5 に答える 5

7

波形値のテーブル(1つの象限または4つの象限のいずれか、それは重要ではありません)があると仮定すると、1つの可能な最適化は、連続するテーブル値の間にデルタ値を格納することです。つまり、egN = 256と波形テーブルLUT[N]がある場合は、デルタ値のテーブルもありますLUT_delta[N]。2つの事前計算されたテーブル間の関係はですLUT_delta[i] = LUT[i+1] - LUT[i]。したがって、2つの連続するテーブル値を検索し、これらを減算してデルタを取得してから補間を実行する代わりにLUT[i]LUT[i+1]最初のテーブル値LUT[i]、、およびデルタを検索するだけです。LUT_delta[i]次に、補間値を計算します。これには、同じ数のテーブルルックアップが必要ですが、数学演算は少なくなります。DSPを使用している場合は、単一の積和命令で補間を実行できるはずです。それ以外の場合は、汎用CPUで乗算+スケール+加算です。また、との値をインターリーブするLUTと、1回の読み取りで検索し、2つの値を解凍LUT_deltaできる場合があります。LUT[i]LUT_delta[i]

擬似コード:

extract integer LUT index, i, from accumulator // just need a shift for this
extract fractional part of accumulator, f // mask or subtract to get f
get p = LUT[i] // lookup waveform value
get delta = LUT_delta[i] // lookup delta
calculate p_interp = p + p_delta * f // single multiply-accumulate instruction on most DSPs - need scaling on general purpose CPUs
于 2010-10-11T11:58:25.253 に答える
4

除算を行わずに線形補間を行うには、分母が2の累乗であることを確認する必要があります。

value(x)=前、
value(x + 1)=次の値(x + dx)=前+(次-前)* dx

あなたの質問は、どうやってdxを計算するのですか?秘訣は、最大値(dx = 1)が2の累乗になるように、補間インデックス(アキュムレータの下位16ビット)を計算することです。

value(x + dx) = previous + ((next - previous) * index) / 1024

ここでは、ステップ値を計算したので、最大ステップは1024であり、dx=1に対応します。インデックス=512は、dx=0.5などの場合です。

于 2010-10-11T12:23:06.487 に答える
1

より高い精度が必要な場合は、最初にアキュムレータの下位ビットを確認することをお勧めします。たとえば、1ではなく4つの出力値が必要な場合。

Acc += 0x2000;
uint lower_bits = Acc & 0xffff;
int rl = LUT[ Acc >> 16];
int rh = LUT[(Acc >> 16) + 1];
if (lower_bits < 0x4000)
    return rl;
if (lower_bits < 0x8000)
    return (rl * 3 + rh) >> 2;
if (lower_bits < 0xC000)
    return (rl + rh) >> 1;
return (rl + rh * 3) >> 2;
于 2010-10-11T11:38:20.900 に答える
0

本当にスピードが必要な場合は、AVRアセンブラーをチェックしてください。

于 2010-10-11T11:36:12.963 に答える
-2

2つの値abの間の線形補間は、(a + b)/2です。

これは単純なハードウェアでは簡単で、除算や浮動小数点は必要ありません。

2で割る==右に1ビットシフトします。

于 2010-10-11T11:21:10.313 に答える