0

在计算 (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);
    }
  }
4

0 回答 0