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个点。
(这里暂时不解释帧移的情况)。
原始数据:
matlab分析
用matlab进行傅里叶变换:
频域的值:
可以看出除第一个元素(直流, Index=0)外和第481个元素(Index=480)为,其它均为复数。
并且,其它元素以第481个点进行对称,实部相同,虚部符号相反。
比如:
再比如第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分析
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的思想相同,但在存储位置上是有区别的。
而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