WAVファイルの特定のタイムスタンプで特定の周波数範囲で0〜100の値を与えることができる単純なCアプリケーションを開発しようとしています。
例: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 */