Использование KissFFT для волнового файла
Я пытаюсь использовать библиотеку KissFFT с этим 11-секундным образцом.wav 44 кГц в качестве тестового ввода.
Однако, когда я обрабатываю файл с размером окна 512, я получаю только 1 выходное значение. Что странно, 11-секундный WAV-файл с частотой 44 кГц не должен давать 1 значение в качестве выходного с размером окна 512. Меньшие окна, такие как 16, дали бы мне 5 значений, что по-прежнему мало.
Кто-нибудь знает, что я делаю не так?
Это мой код:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <math.h>
#include "kiss_fft.h"
#define WIN 512
int main()
{
char *music_file = "C:/MSin44W16-13.wav";
FILE *in;
char buf[WIN * 2];
int nfft = WIN, i, fx;
double intensity = 0;
kiss_fft_cfg cfg;
kiss_fft_cpx cx_in[WIN];
kiss_fft_cpx cx_out[WIN];
short *sh;
cfg = kiss_fft_alloc(nfft, 0, 0, 0);
in = fopen(music_file, "r");
if (!in) {
printf("unable to open file: %s\n", music_file);
perror("Error");
return 1;
}
fx = 0;
while (fread(buf, 1, WIN * 2, in))
{
for (i = 0;i<WIN;i++) {
sh = (short *)&buf[i * 2];
cx_in[i].r = (float) (((double)*sh) / 32768.0);
cx_in[i].i = 0.0;
}
kiss_fft(cfg, cx_in, cx_out);
//Display the value of a position
int position = 511;
intensity = sqrt(pow(cx_out[position].r, 2) + pow(cx_out[position].i, 2));
printf("%9.4f\n", intensity);
//Display all values
/*
for (i = 0;i<WIN;i++) {
//printf("Joe: cx_out[i].r:%f\n", cx_out[i].r);
//printf("Joe: cx_out[i].i:%f\n", cx_out[i].i);
intensity = sqrt(pow(cx_out[i].r,2) + pow(cx_out[i].i,2));
printf("%d - %9.4f\n", i, intensity);
}
*/
}
free(cfg);
scanf("%d");
return 0;
}
Это вывод, который я получаю:
42.7577
Это обновленная версия кода, но я получаю ошибки при компиляции:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <math.h>
#include "kiss_fft.h"
#include "sndfile.h"
#define WIN 512
int main()
{
char *music_file = "C:/voice.wav";
SNDFILE *infile;
SF_INFO sfinfo;
//int readcount;
short buf[WIN * 2];
int nfft = WIN;
double intensity = 0;
kiss_fft_cfg cfg;
kiss_fft_cpx cx_in[WIN];
kiss_fft_cpx cx_out[WIN];
short *sh;
cfg = kiss_fft_alloc(nfft, 0, 0, 0);
if (!( infile = sf_open(music_file, SFM_READ, &sfinfo) ))
{ /* Open failed so print an error message. */
printf("Not able to open input file %s.\n", "input.wav");
/* Print the error message fron libsndfile. */
sf_perror(NULL);
return 1;
}
while ((sf_read_short(infile, buf, WIN)))//fread(buf, 1, WIN * 2, in)
{
//system("cls");
for (int i = 0;i<WIN;i++) {
sh = (short *)&buf[i * 2];
cx_in[i].r = (float) (((double)*sh) / 32768.0);
cx_in[i].i = 0.0;
}
kiss_fft(cfg, cx_in, cx_out);
//Display the value of a position
int position = 511;
intensity = sqrt(pow(cx_out[position].r, 2) + pow(cx_out[position].i, 2));
printf("%9.4f\n", intensity);
//Display all values
/*
for (i = 0;i<WIN;i++) {
//printf("Joe: cx_out[i].r:%f\n", cx_out[i].r);
//printf("Joe: cx_out[i].i:%f\n", cx_out[i].i);
intensity = sqrt(pow(cx_out[i].r,2) + pow(cx_out[i].i,2));
printf("%d - %9.4f\n", i, intensity);
}
*/
}
sf_close(infile);
free(cfg);
int temp;
scanf_s("%d", &temp);
return 0;
}
Я следовал за шагами на этом посте:
Ошибка "LNK2019: неразрешенный внешний символ" в Visual Studio 2010
И я все еще получаю эти ошибки:
1 ответ
Проблема не в KissFFT, а в том, что вы пытаетесь прочитать двоичный волновой файл, открытый в режиме ASCII, в строке:
in = fopen(music_file, "r");
Как вы позже попытаетесь прочитать данные с fread
вы в конце концов ударили недопустимого персонажа. В вашем конкретном примере файла 215-й прочитанный символ - это замещающий символ (шестнадцатеричное значение0x1A
), который интерпретируется как маркер конца файла вашей C-библиотекой времени выполнения. Соответственно,fread
перестает заполнять больше данных и в конечном итоге возвращает 0 (на второй итерации с WIN
установить на 512 и чуть позже с WIN
установить на 16).
Чтобы обойти эту проблему, вы должны открыть файл в двоичном формате с помощью:
in = fopen(music_file, "rb");
Обратите внимание, что это обеспечит чтение двоичных данных как есть в ваш входной буфер, но не расшифрует заголовок волнового файла. Чтобы правильно читать и декодировать волновой файл и получать значимые данные, вы должны изучить использование библиотеки аудио (например, libsndfile, чтобы назвать ее). Если вам нужно накатить собственное устройство для чтения волновых файлов, вы должны прочитать спецификации и / или проверить один из множества руководств по этой теме.