Использование 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< /а>

И я все еще получаю эти ошибки:

введите здесь описание изображения


person Joseph Azzam    schedule 01.03.2016    source источник
comment
Решил это, мне пришлось добавить в начало кода: #pragma comment(lib, C:/Program Files (x86)/Mega-Nerd/libsndfile/lib/libsndfile-1.lib), затем сделал следующее: stackoverflow.com/questions/17672025/ затем сделал это: stackoverflow.com/questions/12767820/   -  person Joseph Azzam    schedule 04.03.2016


Ответы (1)


Проблема возникает не из-за KissFFT, а скорее из-за того, что вы пытаетесь прочитать двоичный волновой файл, открытый в режиме ASCII, в строке:

in = fopen(music_file, "r");

Когда вы позже попытаетесь прочитать данные с помощью fread, вы в конце концов наткнетесь на недопустимый символ. В конкретном примере файла 215-й символ считывается как замещающий символ (шестнадцатеричное значение 0x1A), который интерпретируется вашей библиотекой времени выполнения C как маркер конца файла. Соответственно, fread прекращает заполнение дополнительных данных и в итоге возвращает 0 (на второй итерации с WIN установленным на 512 и чуть позже с WIN установленным на 16).

Чтобы обойти эту проблему, вы должны открыть файл в двоичном формате с помощью:

in = fopen(music_file, "rb");

Обратите внимание, что это гарантирует, что двоичные данные будут считаны как есть во входной буфер, но не будет декодировать для вас заголовок волнового файла. Чтобы правильно прочитать и декодировать волновой файл и получить значимые данные, вам следует изучить возможность использования аудиобиблиотеки (например, libsndfile, чтобы назвать один). Если вам необходимо установить собственную программу для чтения волновых файлов, прочтите спецификации и/или ознакомьтесь с одним из многочисленных руководств по этой теме.

person SleuthEye    schedule 02.03.2016
comment
Хорошо, я пытаюсь использовать ваше решение для использования файла libsnd. Если бы я понял это прямо, мое решение работало бы для необработанного файла, но, поскольку волновой файл имеет заголовок, мне нужно использовать libsndfile для получения пригодных для использования результатов? Я попытался добавить библиотеку в свой проект, но мне не хватает одного небольшого фрагмента кода. Чем заменить эту строку: while (fread(buf, 1, WIN * 2, in)) ? Вот что у меня есть на данный момент: char *music_file = "C:/voice.wav"; SNDFILE *infile; SF_INFO sfinfo; int readcount; infile = sf_open_read(music_file, &sfinfo); - person Joseph Azzam; 02.03.2016
comment
да. Попробуйте while (sf_read_short(infile, buf, WIN)) для одноканального wav-файла (количество каналов будет получено из sfinfo, заполненного информацией заголовка wav-файла с помощью вызова sf_open_read). - person SleuthEye; 02.03.2016
comment
Я пробовал, но это не работает, я обновил основной пост, чтобы показать полученные ошибки. - person Joseph Azzam; 03.03.2016
comment
вам нужно 1) изменить sf_open_read на sf_open(music_file, SFM_READ, &sfinfo) 2) включить libsndfile-1.lib в качестве входной библиотеки в VS. Также было бы неплохо удалить оставшиеся предупреждения, такие как предупреждение о sscanf - person SleuthEye; 03.03.2016
comment
Я снял другое предупреждение, но как включить libsndfile-1.lib в качестве входной библиотеки в VS? Если вы имеете в виду добавить его в каталоги VC++, я уже сделал - person Joseph Azzam; 03.03.2016
comment
Посмотрите Как исправить неразрешенные внешние символы и, в частности, этот ответ. - person SleuthEye; 04.03.2016
comment
Я пробовал это, но все равно получаю те же ошибки, я даже пробовал это: studio-2010" title="ошибка lnk2019 неразрешенная ошибка внешнего символа в Visual Studio 2010"> stackoverflow.com/questions/23276399/ - person Joseph Azzam; 04.03.2016