Speex 中傅里叶变换spx_fft的秘密

Speex中用spx_fft将信号从时域转换到频域。

/** Forward (real to half-complex) transform */
void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out);

调用方式:

/* Convert x (echo input) to frequency domain */
        spx_fft(fft_table, x, &X[0]);

频域分析

采样率48k,10ms的数据480个点,处理buffer长度为960个点。
(这里暂时不解释帧移的情况)。
原始数据:


Speex 中傅里叶变换spx_fft的秘密_第1张图片
原始数据 960个点
matlab分析

用matlab进行傅里叶变换:
频域的值:


Speex 中傅里叶变换spx_fft的秘密_第2张图片
频域的值

可以看出除第一个元素(直流, Index=0)外和第481个元素(Index=480)为,其它均为复数。
并且,其它元素以第481个点进行对称,实部相同,虚部符号相反
比如:

Speex 中傅里叶变换spx_fft的秘密_第3张图片
对称举例

再比如第2到4个元素(Index: 1~3):

1   62.208 +     7.4152i
2   -57.477 +     49.925i
3   -6.7527 -      45.79i

与第958~960个元素(Index: 957~959)

957 -6.7527 +      45.79i
958 -57.477 -     49.925i
959 62.208 -     7.4152i

逐个对称。

由于对称性,其实第482~960个元素的值其实是没有必要保存的。

spx_fft分析
Speex 中傅里叶变换spx_fft的秘密_第4张图片
spx_fft分析结果
matlab vs spx_fft
Speex 中傅里叶变换spx_fft的秘密_第5张图片
matlab vs spx_fft

可以看出matlab是real to complex,而spx_fft是real to half-complex.
spx_fft的结果依次存的是实部和虚部。

查看spx_fft的定义:

/** Forward (real to half-complex) transform */
void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out);

到底 half-complex是什么呢?

The Halfcomplex-format DFT

以下介绍的Halfcomplex与spx_fft的思想相同,但在存储位置上是有区别的。

Speex 中傅里叶变换spx_fft的秘密_第6张图片
The Halfcomplex-format DFT

而spx_fft的存储顺序是这样的:

r0, r1, i1, r2, i2, ..., r(n+1)/2-1, i(n+1)/2-1, rn/2

References:

http://www.fftw.org/fftw3_doc/The-Halfcomplex_002dformat-DFT.html#The-Halfcomplex_002dformat-DFT

你可能感兴趣的:(Speex 中傅里叶变换spx_fft的秘密)