3

I am trying to use the KissFFT Library with this 11 second 44kHz .wav sample file as a test input.

However as I process the file with a window size of 512, I am getting only 1 output value. Which is weird, the 11 sec .wav file at 44kHz should not give 1 value as an output with a windows size of 512. A smaller windows like 16 would give me 5 values, which is still a low count.

Does anyone know what I am doing wrong?

This is my code:

#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;
}

This is the output I get:

 42.7577

This is the Updated Code version, but I am getting errors at compile:

#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;
}

I followed the steps on this post:

"error LNK2019: unresolved external symbol" error in Visual Studio 2010

And I still get these errors:

enter image description here

Community
  • 1
  • 1
Joseph Azzam
  • 105
  • 1
  • 14
  • Solved it, I had to add at the top of my code: #pragma comment(lib, "C:/Program Files (x86)/Mega-Nerd/libsndfile/lib/libsndfile-1.lib") then did this: http://stackoverflow.com/questions/17672025/trying-to-add-reference-to-project-in-visual-studio-2012-no-items-found then did that: http://stackoverflow.com/questions/12767820/visual-studio-2010-dll-missing – Joseph Azzam Mar 04 '16 at 04:19

1 Answers1

4

The problem does not comes from KissFFT, but rather from the fact that you are trying to read a binary wave file opened in ASCII mode on the line:

in = fopen(music_file, "r");

As you later try to read data with fread you eventually hit an invalid character. In your specific sample file, the 215th character read is the Substitute Character (hex value 0x1A), which is interpreted as an end of file marker by your C runtime library. Correspondingly, fread stops filling in more data and eventually return 0 (at the second iteration with WIN set to 512 and a little later with WIN set to 16).

To get around this problem, you should open the file in binary more with:

in = fopen(music_file, "rb");

Note that this will ensure the binary data is read as-is into your input buffer, but would not decode the wave file header for you. To properly read and decode a wave file and get meaningful data in, you should look into using an audio library (such as libsndfile to name one). If you must roll your own wave file reader you should read the specifications and/or check out one of many tutorials on the topic.

SleuthEye
  • 14,379
  • 2
  • 32
  • 61
  • Ok, I am trying your solution to use the libsndfile. If I got this straight my solution would work for a raw file, but since the wave file has a header, I need to use the libsndfile to get usable results? I tried adding the library to my project, but I am missing one small piece of code. What do I replace this line with: `while (fread(buf, 1, WIN * 2, in))` ? This is what I have so far: `char *music_file = "C:/voice.wav"; SNDFILE *infile; SF_INFO sfinfo; int readcount; infile = sf_open_read(music_file, &sfinfo);` – Joseph Azzam Mar 02 '16 at 19:15
  • Yes. Try `while (sf_read_short(infile, buf, WIN))` for a single channel wav file (number of channels would be obtained from `sfinfo` filled with wav file header information by the `sf_open_read` call). – SleuthEye Mar 02 '16 at 20:03
  • I tried it but it is not working, I updated the main post to show the errors I got – Joseph Azzam Mar 03 '16 at 03:39
  • you need to 1) change `sf_open_read` to `sf_open(music_file, SFM_READ, &sfinfo)` 2) include `libsndfile-1.lib` as an input library in VS. It would also be a good idea to clear the remaining warnings such as the one about `sscanf` – SleuthEye Mar 03 '16 at 04:01
  • I cleared the other warning, but how can I include the libsndfile-1.lib as an input library in VS? If you mean add it to the VC++ directories, i already did – Joseph Azzam Mar 03 '16 at 19:29
  • Have a look at [How to fix unresolved external symbols](http://stackoverflow.com/q/12573816/2994596), and in particular [this answer](http://stackoverflow.com/a/12574400/2994596). – SleuthEye Mar 03 '16 at 21:05
  • I tried that, but I still get the same errors, I even tried this: http://stackoverflow.com/questions/23276399/error-lnk2019-unresolved-external-symbol-error-in-visual-studio-2010 – Joseph Azzam Mar 04 '16 at 03:56