FFTで20000Hzまで計算できるようにしたい
C++でFFTのプログラムを下記のサイトを参考にして作っています。
http://www-in.aut.ac.jp/~minemura/pub/Csimu/C/FFT.html
周波数は25000Hzくらいまで表示できるのですが
パワースペクトルが周波数と対応しません。
どなたかご教示お願い致します。
該当のソースコード
C++
1#include <stdio.h> 2#include <math.h> 3#include <stdlib.h> 4#pragma warning(disable:4996) 5 6FILE* fp; // ファイル入出力 7 8#define PI 4.0*atan(1.0) // 円周率 9 10void S_fft(double* x, double* y, int, int); 11#define N 32768 // N=データ総数(2,4,8,16,32,64,128,256,512,1024 のどれか) 12 13int main(void) { 14 int i, count, Fr = 128; 15 double dt = 0.01; 16 double sc; 17 double* x, * y; 18 x = (double*)malloc(sizeof(double) * N); 19 y = (double*)malloc(sizeof(double) * N); 20 21 22 double fq, pw; 23 24 sc = 2.0 * PI * dt; 25 for (i = 0; i < N; i++) { // 1Hzに60Hzのノイズが重なった波形の例 26 x[i] = sin(sc * i); 27 y[i] = 0.0; 28 } 29 // Fourier変換 30 S_fft(x, y, N, -1); 31 32 //for (i = 0; i < Fr; i++) printf(" i=%d %f %f \n", i, x[i], y[i]); 33 34 // 計算結果をファイルに格納 35 fp = fopen("fft.txt", "w"); // ファイル名は fft.dat 36 for (i = 0; i < N; i++) { 37 if (i % 256 == 0) { 38 pw = sqrt(x[i] * x[i] + y[i] * y[i]) * 100; // パワースペクトル 39 } 40 fq = i / (dt * Fr); // 周波数 41 //printf("%f = %d / (%f * %d)\n", fq, i, dt, N); 42 fprintf(fp, "%fHz %f \n", fq, pw); 43 } 44 fclose(fp); 45 return 0; 46} 47 48/********* Fourier変換および逆Fourier変換を行う副関数 ***************/ 49/* 入力: x[n]: 被解析波形(振幅) n; 離散データの数 */ 50/* ff: Fourier変換の場合は -1, 逆Fourier変換の場合は 1 */ 51/* 出力: ak[n]:cos関数の係数、 bk[n]:sin関数の係数 */ 52/**********************************************************************/ 53void S_fft(double ak[], double bk[], int n, int ff) { 54 int i, j, k, k1, num, nhalf, phi, phi0; 55 static int rot[N]; 56 double s, sc, c, a0, b0, tmp; 57 for (i = 0; i < n; i++) rot[i] = 0; 58 59 nhalf = n / 2; num = n / 2; sc = 2.0 * PI / n; 60 while (num >= 1) { 61 for (j = 0; j < n; j += 2 * num) { 62 phi = rot[j] / 2; phi0 = phi + nhalf; 63 c = cos(sc * phi); s = sin(sc * phi * ff); 64 for (k = j; k < j + num; k++) { 65 k1 = k + num; 66 a0 = ak[k1] * c - bk[k1] * s; b0 = ak[k1] * s + bk[k1] * c; 67 ak[k1] = ak[k] - a0; bk[k1] = bk[k] - b0; 68 ak[k] = ak[k] + a0; bk[k] = bk[k] + b0; 69 rot[k] = phi; rot[k1] = phi0; 70 } 71 } 72 num = num / 2; 73 } 74 if (ff < 0) { 75 for (i = 0; i < n; i++) { 76 ak[i] /= n; bk[i] /= n; 77 } 78 } 79 80 for (i = 0; i < n - 1; i++) { 81 if ((j = rot[i]) > i) { 82 tmp = ak[i]; ak[i] = ak[j]; ak[j] = tmp; 83 tmp = bk[i]; bk[i] = bk[j]; bk[j] = tmp; 84 } 85 } 86}
試したこと
mallocを使ってみましたが、下記の警告が出て異常終了してしまいます。
警告
NULLポインター'x'を逆参照しています。
NULLポインター'y'を逆参照しています。
補足情報(FW/ツールのバージョンなど)
Visual Studio 2019
x[1024], y[1024]
rot[1024]
これらも変更してますか。
変更してみました!
(質問が編集されましたが、以前のエラーは出なくなったのですか? ソースコードはなにも変更していないようですが、なにが変わったのですか?-最新の更新しか見ていなかった勘違いなのでここまで削除)
一致っていうのは、二つ以上のなにかとなにかが同じであることをいいます。
一つはこのプログラムの結果として、それとなにが一致しないと言っているのですか?
直流、正弦波、矩形波、鋸歯状波など、既知の波形を入力したらその結果は妥当なのですか?
>#define N 32768
・・・・
> double sc, x[N], y[N]; ←これ、スタック壊してませんか?
>>thkanaさん
言葉足らずですみません。
周波数とそれに対応するパワースペクトルが一致しないという意味です。
Nをいじってサンプリング周波数?は変えられたと思うのですが、パワースペクトルの範囲が0〜99.9Hzになっているようで……
>>cateyeさん
壊れてはいないと思いますが……
なぜですか?
私が、あなたがやったのと同じ比較をして「一致していない」ことを確認しようとするなら、
どうすれば比較する二つのデータを入手できますか?
もう一つ、比較対照しているデータが間違っていない、ということは確かなのですか?
>なぜですか?
遅くなりましたが・・・以下を参考に
https://teratail.com/questions/255528
>>thkanaさん
データは以下のようになります。
0.000000Hz 0.001109
0.781250Hz 0.001109
1.562500Hz 0.001109
2.343750Hz 0.001109
3.125000Hz 0.001109
.
.
.
0.781250Hzのところで高いパワースペクトルが取り出せることを期待していたのですが
0になってしまいます。多分データがずれてるんだと思います。
追記:もしかするとcateyeさんの仰るようにスタックオーバーフロー?を起こしてるのかもしれません
>>cateyeさん
mallocについても調べてみましたが初心者でよく分かりません……
お力添えをお願いします
回答1件
あなたの回答
tips
プレビュー