如何解释KissFFT的kiss_fftr(用于实数信号的FFT)函数的结果

3
我正在使用KissFFT的实数函数将一些真实音频信号转换。我感到困惑,因为我输入了一个有nfft个样本的实数信号,但结果是nfft/2+1个复杂频率项。
来自KissFFT的README:
实数(即非复数)优化代码仅适用于偶数长度的fft。它会并行地进行两个半长度的FFT(打包到实数和虚数中),然后通过旋转组合它们。结果是从DC到Nyquist的nfft/2+1个复杂频率项。
所以我没有具体的知识来解释结果。我的假设是数据像这样打包:r[0]i[0]r[1]i[1]...r[nfft/2]i[nfft/2],其中r[0]将是DC,i[0]是第一个频率项,r[1]是第二个,依此类推。是这种情况吗?

是的,我认为那可能是正确的 - 如果您输入一个已知信号并查看频域中的结果,那应该很容易验证。 - Paul R
请注意,最后两个值是 r[nfft/2]i[fftn/2](即奈奎斯特)。 - Paul R
好主意@paul。 但是,假设我的假设是正确的,返回的数组有两个额外的“bins”,r [0]i [nfft / 2 +1]。 这些将是直流和奈奎斯特偏移吗? - Steve Barna
1
不完全正确 - 因为你有nfft/2+1个复杂的bin,所以很可能你有一个DC的复杂bin(索引=0)和一个Nyquist的复杂bin(索引=nfft/2),即使这些的虚部是不需要的。 - Paul R
好的,这很有道理。由于它是两个半长度的FFT,所以会有重复的DC和Nyquist值,从而创建一个额外的复杂bin。对不起,我的数组索引偏移了一位。感谢@paul的帮助。 - Steve Barna
2个回答

5
是的。kiss_fftr只生成Nfft/2+1个bin的原因是,实信号的DFT是共轭对称的。与负频率(-pi:0或pi:2pi,无论你喜欢哪种方式来思考)相对应的系数是[0:pi)中的共轭系数。
请注意out[0]和out[Nfft/2] bin(DC和Nyquist)的虚部为零。我见过一些库将这两个实部打包在第一个复杂数中,但我认为这是一种违反契约的行为,会导致难以诊断的几乎正确的错误。
提示:如果您使用浮点类型(default),可以将输出数组转换为float complex*(c99)或std::complex*(c++)。kiss_fft_cpx结构体的打包是兼容的。它不使用这些默认值的原因是,kiss_fft还可以使用除float和double之外的其他类型,并且可以在缺少这些功能的旧版ANSI C编译器上工作。
以下是一个人为制造的例子(假设c99编译器和type==float)。
float get_nth_bin_phase(const float * in, int nfft, int whichbin )
{
  kiss_fftr_cfg st = kiss_fftr_alloc(1024,0,0,0);
  float complex * out = malloc(sizeof(float complex)*(nfft/2+1));
  kiss_fftr(st,in,(kiss_fft_cpx*)out);

  whichbin %= nfft;
  if ( whichbin <= nfft/2 ) 
    ph = cargf(out[whichbin]);
  else
    ph = cargf( conjf( out[nfft-whichbin] ) );
  free(out);
  kiss_fft_free(st);
  return ph;
}

0

fftr结果的r [1]和i [1]构成一个复向量。它们一起给出第一个频率bin的幅度(两个分量平方和的平方根)和相位(通过atan2()计算)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接