真正的IFFT流程的这一部分真的是最优的吗?

时间:2014-11-18 00:43:16

标签: performance math fft microcontroller ifft

当计算(I)FFT时,可以计算" N * 2实数"使用N个数据点的普通复数(I)FFT的数据点。 我不确定我的术语,但这就是我所阅读的内容。 在stackoverflow上有几篇关于这个的帖子。

当只处理这样的"真实"时,这可以加快速度。在处理例如声音(重新)合成时经常出现的情况。

这种速度的提高被某种预处理步骤的需要所抵消......呃... fidaddles?实现这一目标的数据。看起来我甚至都没有试图说服任何人我完全理解这一点,但多亏了前面提到的线程,我提出了以下例程,这很好地完成了工作(谢谢!)。

然而,在我的微控制器上,虽然三角函数已经使用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);
    }
  }

0 个答案:

没有答案
相关问题