下記のプログラムはsinwave.wav(2000Hz×1秒間のファイル)から音声データを配列に格納して
その配列をFFTにかけるというプログラムです。
2000Hzの場所でパワースペクトルが上がることを期待していたのですが
なぜか900Hzあたりでパワースペクトルが上がってしまいます。
サンプル数のあたりが間違っているんでしょうか?
お力添えお願いします。
C++
1#include <stdio.h> 2#include <math.h> 3#include <stdlib.h> 4#pragma warning(disable:4996) 5 6typedef struct 7 8{ 9 10 int fs; //サンプリング周波数 11 12 int bits; //量子化bit数 13 14 int L; //データ長 15 16} WAV_PRM; 17 18FILE* fp; // ファイル入出力 19 20#define PI 4.0*atan(1.0) // 円周率 21 22void S_fft(double* x, double* y, int, int); 23#define N 4096 // N=データ総数(2,4,8,16,32,64,128,256,512,1024 のどれか) 24 25double* audio_read(WAV_PRM* prm, char* filename); 26 27double* audiodatasize; 28 29int main(void) { 30 31 WAV_PRM prm_in; 32 double* data; 33 FILE* audio = fopen("sinwave.wav", "rb"); 34 FILE* txt = fopen("data.txt", "w"); 35 char fn[] = "sinwave.wav"; 36 37 int i, Fr = 4096; 38 double dt = 0.00005; 39 double sc; 40 double* x, * y; 41 x = (double*)malloc(sizeof(double) * N); 42 y = (double*)malloc(sizeof(double) * N); 43 44 45 double fq; 46 int pw = 0; 47 printf("STG 01\n"); 48 sc = 2.0 * PI * dt; 49 for (i = 0; i < N; i++) { 50 if (x != NULL && y != NULL) { 51 y[i] = 0.0; 52 } 53 } 54 x = audio_read(&prm_in, fn); //配列xにsinwave.wavの波形データ(2000Hz)を代入 55 printf("STG 02\n"); 56 // Fourier変換 57 S_fft(x, y, N, -1); 58 59 //for (i = 0; i < Fr; i++) printf(" i=%d %f %f \n", i, x[i], y[i]); 60 61 // 計算結果をファイルに格納 62 fp = fopen("fft.txt", "w"); // ファイル名は fft.dat 63 for (i = 0; i < N; i++) { 64 if (x != NULL && y != NULL) { 65 pw = sqrt(x[i] * x[i] + y[i] * y[i]) * 10; // パワースペクトル 66 } 67 fq = i / (dt * Fr); // 周波数 68 //printf("%f = %d / (%f * %d)\n", fq, i, dt, N); 69 fprintf(fp, "%fHz %d\n", fq, pw); 70 } 71 printf("STG 03\n"); 72 fclose(fp); 73 fclose(audio); 74 return 0; 75} 76 77/********* Fourier変換および逆Fourier変換を行う副関数 ***************/ 78/* 入力: x[n]: 被解析波形(振幅) n; 離散データの数 */ 79/* ff: Fourier変換の場合は -1, 逆Fourier変換の場合は 1 */ 80/* 出力: ak[n]:cos関数の係数、 bk[n]:sin関数の係数 */ 81/**********************************************************************/ 82void S_fft(double ak[], double bk[], int n, int ff) { 83 int i, j, k, k1, num, nhalf, phi, phi0; 84 static int rot[N]; 85 double s, sc, c, a0, b0, tmp; 86 for (i = 0; i < n; i++) rot[i] = 0; 87 88 nhalf = n / 2; num = n / 2; sc = 2.0 * PI / n; 89 while (num >= 1) { 90 for (j = 0; j < n; j += 2 * num) { 91 phi = rot[j] / 2; phi0 = phi + nhalf; 92 c = cos(sc * phi); s = sin(sc * phi * ff); 93 for (k = j; k < j + num; k++) { 94 k1 = k + num; 95 a0 = ak[k1] * c - bk[k1] * s; b0 = ak[k1] * s + bk[k1] * c; 96 ak[k1] = ak[k] - a0; bk[k1] = bk[k] - b0; 97 ak[k] = ak[k] + a0; bk[k] = bk[k] + b0; 98 rot[k] = phi; rot[k1] = phi0; 99 } 100 } 101 num = num / 2; 102 } 103 if (ff < 0) { 104 for (i = 0; i < n; i++) { 105 ak[i] /= n; bk[i] /= n; 106 } 107 } 108 109 for (i = 0; i < n - 1; i++) { 110 if ((j = rot[i]) > i) { 111 tmp = ak[i]; ak[i] = ak[j]; ak[j] = tmp; 112 tmp = bk[i]; bk[i] = bk[j]; bk[j] = tmp; 113 } 114 } 115} 116 117 118 119double* audio_read(WAV_PRM* prm, char* filename) 120 121{ 122 123 //変数宣言 124 125 FILE* fp; 126 127 int n; 128 129 double* data; 130 131 char header_ID[4]; 132 133 long header_size; 134 135 char header_type[4]; 136 137 char fmt_ID[4]; 138 139 long fmt_size; 140 141 short fmt_format; 142 143 short fmt_channel; 144 145 long fmt_samples_per_sec; 146 147 long fmt_bytes_per_sec; 148 149 short fmt_block_size; 150 151 short fmt_bits_per_sample; 152 153 char data_ID[4]; 154 155 long data_size; 156 157 short data_data; 158 159 160 161 //wavファイルオープン 162 163 fp = fopen(filename, "rb"); 164 165 166 167 //wavデータ読み込み 168 169 fread(header_ID, 1, 4, fp); 170 171 fread(&header_size, 4, 1, fp); 172 173 fread(header_type, 1, 4, fp); 174 175 fread(fmt_ID, 1, 4, fp); 176 177 fread(&fmt_size, 4, 1, fp); 178 179 fread(&fmt_format, 2, 1, fp); 180 181 fread(&fmt_channel, 2, 1, fp); 182 183 fread(&fmt_samples_per_sec, 4, 1, fp); 184 185 fread(&fmt_bytes_per_sec, 4, 1, fp); 186 187 fread(&fmt_block_size, 2, 1, fp); 188 189 fread(&fmt_bits_per_sample, 2, 1, fp); 190 191 fread(data_ID, 1, 4, fp); 192 193 fread(&data_size, 4, 1, fp); 194 195 196 197 //パラメータ代入 198 199 prm->fs = fmt_samples_per_sec; 200 201 prm->bits = fmt_bits_per_sample; 202 203 prm->L = data_size / 2; 204 205 206 207 //音声データ代入 208 209 data = (double*)calloc(prm->L, sizeof(double)); 210 audiodatasize = (double*)malloc(sizeof(double) * prm->L); 211 212 for (n = 0; n < prm->L; n++) { 213 214 fread(&data_data, 2, 1, fp); 215 216 if (data != NULL) { 217 data[n] = (double)data_data / 32768.0; 218 } 219 220 } 221 222 223 224 fclose(fp); 225 226 return data; 227 228}
出力されたデータがこちらです。
~~~~~~ . . . 888.671875Hz 0 893.554688Hz 0 898.437500Hz 0 903.320313Hz 1 908.203125Hz 4 913.085938Hz 0 917.968750Hz 0 922.851563Hz 0 . . . ~~~~~~
##開発環境
Visual Studio 2019 C++
回答1件
あなたの回答
tips
プレビュー