(I)FFT を計算する場合、N データ ポイントの通常の複素数 (I)FFT を使用して、「N*2 実数」データ ポイントを計算できます。ここでの私の用語についてはよくわかりませんが、これが私が説明した方法です。これについては、stackoverflow に既にいくつかの投稿があります。
これにより、サウンドの (再) 合成などを扱う場合によくある「実際の」データのみを扱う場合に、処理が少し高速化されます。
この速度の向上は、何らかの形で前処理ステップの必要性によって相殺されます... うーん... フィダドル? これを達成するためのデータ。これを完全に理解している人を説得するつもりはありませんが、前述のスレッドのおかげで、うまく機能する次のルーチンを思いつきました (ありがとう!)。
ただし、私のマイクロコントローラーでは、三角関数が既に LUT で最適化されているにもかかわらず、これは私が望むよりも少しコストがかかります。
しかし、ルーチン自体は、数学的に最適化して処理を最小限に抑えることが可能であるように見えます。私には、単純な 2D 回転に似ているように思えます。頭を包むことはできませんが、三角関数の呼び出しと算術演算の両方を少なくするだけでこれを実行できるように感じます。
他の誰かが私が知らないことを簡単に見て、この数学がどのように単純化されるかについての洞察を提供してくれることを期待していました.
この特定のルーチンは、ビット反転ステージの前に IFFT で使用するためのものです。
pseudo-version:
INPUT
MAG_A/B = 0 TO 1
PHA_A/B = 0 TO 2PI
INDEX = 0 TO PI/2
r = MAG_A * sin(PHA_A)
i = MAG_B * sin(PHA_B)
rsum = r + i
rdif = r - i
r = MAG_A * cos(PHA_A)
i = MAG_B * cos(PHA_B)
isum = r + i
idif = r - i
r = -cos(INDEX)
i = -sin(INDEX)
rtmp = r * isum + i * rdif
itmp = i * isum - r * rdif
OUTPUT rsum + rtmp
OUTPUT itmp + idif
OUTPUT rsum - rtmp
OUTPUT itmp - idif
それがあなたの毒である場合、元の作業コード:
void fft_nz_set(fft_complex_t complex[], unsigned bits, unsigned index, int32_t mag_lo, int32_t pha_lo, int32_t mag_hi, int32_t pha_hi) {
unsigned size = 1 << bits;
unsigned shift = SINE_TABLE_BITS - (bits - 1);
unsigned n = index; // index for mag_lo, pha_lo
unsigned z = size - index; // index for mag_hi, pha_hi
int32_t rsum, rdif, isum, idif, r, i;
r = smmulr(mag_lo, sine(pha_lo)); // mag_lo * sin(pha_lo)
i = smmulr(mag_hi, sine(pha_hi)); // mag_hi * sin(pha_hi)
rsum = r + i; rdif = r - i;
r = smmulr(mag_lo, cosine(pha_lo)); // mag_lo * cos(pha_lo)
i = smmulr(mag_hi, cosine(pha_hi)); // mag_hi * cos(pha_hi)
isum = r + i; idif = r - i;
r = -sinetable[(1 << SINE_BITS) - (index << shift)]; // cos(pi_c * (index / size) / 2)
i = -sinetable[index << shift]; // sin(pi_c * (index / size) / 2)
int32_t rtmp = smmlar(r, isum, smmulr(i, rdif)) << 1; // r * isum + i * rdif
int32_t itmp = smmlsr(i, isum, smmulr(r, rdif)) << 1; // i * isum - r * rdif
complex[n].r = rsum + rtmp;
complex[n].i = itmp + idif;
complex[z].r = rsum - rtmp;
complex[z].i = itmp - idif;
}
// For reference, this would be used as follows to generate a sawtooth (after IFFT)
void synth_sawtooth(fft_complex_t *complex, unsigned fft_bits) {
unsigned fft_size = 1 << fft_bits;
fft_sym_dc(complex, 0, 0); // sets dc bin [0]
for(unsigned n = 1, z = fft_size - 1; n <= fft_size >> 1; n++, z--) {
// calculation of amplitude/index (sawtooth) for both n and z
fft_sym_magnitude(complex, fft_bits, n, 0x4000000 / n, 0x4000000 / z);
}
}