我正在尝试开发一个简单的 C 应用程序,它可以在 WAV 文件中的给定时间戳的某个频率范围内给出 0-100 的值。
示例:我的频率范围为 44.1kHz(典型的 MP3 文件),我想将该范围分成 n 个范围(从 0 开始)。然后我需要得到每个范围的幅度,从 0 到 100。
到目前为止我所管理的:
使用 libsndfile 我现在能够读取 WAV 文件的数据。
infile = sf_open(argv [1], SFM_READ, &sfinfo);
float samples[sfinfo.frames];
sf_read_float(infile, samples, 1);
但是,我对 FFT 的理解相当有限。但我知道为了在我需要的范围内获得振幅是必需的。但是我该如何从这里继续前进?我找到了图书馆 FFTW-3,它似乎适合这个目的。
我在这里找到了一些帮助:https ://stackoverflow.com/a/4371627/1141483
并在这里查看了 FFTW 教程:http ://www.fftw.org/fftw2_doc/fftw_2.html
但由于我不确定 FFTW 的行为,我不知道从这里开始。
还有一个问题,假设您使用 libsndfile:如果您强制读取单通道(使用立体声文件),然后读取样本。那么您实际上只会读取整个文件的一半样本吗?其中一半来自通道 1,还是会自动将其过滤掉?
非常感谢您的帮助。
编辑:我的代码可以在这里看到:
double blackman_harris(int n, int N){
double a0, a1, a2, a3, seg1, seg2, seg3, w_n;
a0 = 0.35875;
a1 = 0.48829;
a2 = 0.14128;
a3 = 0.01168;
seg1 = a1 * (double) cos( ((double) 2 * (double) M_PI * (double) n) / ((double) N - (double) 1) );
seg2 = a2 * (double) cos( ((double) 4 * (double) M_PI * (double) n) / ((double) N - (double) 1) );
seg3 = a3 * (double) cos( ((double) 6 * (double) M_PI * (double) n) / ((double) N - (double) 1) );
w_n = a0 - seg1 + seg2 - seg3;
return w_n;
}
int main (int argc, char * argv [])
{ char *infilename ;
SNDFILE *infile = NULL ;
FILE *outfile = NULL ;
SF_INFO sfinfo ;
infile = sf_open(argv [1], SFM_READ, &sfinfo);
int N = pow(2, 10);
fftw_complex results[N/2 +1];
double samples[N];
sf_read_double(infile, samples, 1);
double normalizer;
int k;
for(k = 0; k < N;k++){
if(k == 0){
normalizer = blackman_harris(k, N);
} else {
normalizer = blackman_harris(k, N);
}
}
normalizer = normalizer * (double) N/2;
fftw_plan p = fftw_plan_dft_r2c_1d(N, samples, results, FFTW_ESTIMATE);
fftw_execute(p);
int i;
for(i = 0; i < N/2 +1; i++){
double value = ((double) sqrtf(creal(results[i])*creal(results[i])+cimag(results[i])*cimag(results[i]))/normalizer);
printf("%f\n", value);
}
sf_close (infile) ;
return 0 ;
} /* main */