如何正确 FFT 声音阵列?
Posted
技术标签:
【中文标题】如何正确 FFT 声音阵列?【英文标题】:How to FFT a sound array correctly? 【发布时间】:2012-07-11 20:13:32 【问题描述】:我正在尝试获取输入音频样本中存在的频率列表。似乎我需要做一个 FFT 才能得到这个结果,但是当我 FFT 时我得到了奇怪的答案(使用 FFTW):我得到的数组主要包含零和一些不可能的大元素(300+ 位!) - 以及这些大数字无论我改变输入音调的频率还是改变 FFT 的样本长度,总是在同一个地方(最后 5 个位置,最后 46 个位置以及其他一些偶尔出现的位置)。我究竟做错了什么?这是我的代码:
#include <fftw3.h>
#include <sndfile.h>
#include <math.h>
#include <algorithm>
int main (int argc, char * argv [])
char *infilename ;
SNDFILE *infile = NULL ;
FILE *outfile = NULL ;
SF_INFO sfinfo ;
infile = sf_open("test.wav", SFM_READ, &sfinfo);
int N = pow(2, 10);
double samples[N];
sf_read_double(infile, samples, 1);
fftw_complex out[N];
fftw_plan p;
p = fftw_plan_dft_r2c_1d(N, samples, out, FFTW_ESTIMATE);
fftw_execute(p);
fftw_destroy_plan(p);
for (int i=0; i<N; i++)
printf("%f %f\n", out[i][0], out[i][1]);
sf_close (infile) ;
return 0 ;
【问题讨论】:
您确认您的输入数据(即samples
)是正常的吗?
是wav文件,其他媒体播放器正常播放。这是否使它理智?
我确定该文件是有效的,但您确认您已正确读取它吗?例如,如果您打印 samples
的值,它们看起来合理吗?
实际上,他们没有。大部分是0.000000
,里面有一些实际数字。我在使用 libsndfile 的方式上做错了吗?
我以前从未使用过这个库,所以恐怕我对此没有具体的建议。但快速查看文档 (mega-nerd.com/libsndfile/api.html#open) 会发现以下内容:“打开文件进行读取时,格式字段应在调用 sf_open() 之前设置为零”。
【参考方案1】:
问题是双重的:首先,我没有加载所有声音数据,其次,我只是获取了结果的真实部分。此外,我仍然得到 FFT 的不可用部分(高于奈奎斯特频率)。将sf_read_double(infile, samples, 1)
更改为sf_read_double(infile, samples, N)
,将for (int i=0; i<N; i++)
更改为for (int i=0; i<N/2; i++)
并更改
printf("%f %f\n", out[i][0], out[i][1]);
到
printf("%i %f\n", i*21, sqrt(out[i][0]*out[i][0] + out[i][1]*out[i][1]));
给了我想要的好结果。
【讨论】:
以上是关于如何正确 FFT 声音阵列?的主要内容,如果未能解决你的问题,请参考以下文章
阵列麦克风声音定位-代码python实现-二维与三维声音定位