c - 在波形文件上使用 KissFFT

标签 c fft wav libsndfile kissfft

我正在尝试使用 KissFFT Librarythis 11 second 44kHz .wav sample file作为测试输入。

然而,当我处理窗口大小为 512 的文件时,我只得到 1 个输出值。这很奇怪,44kHz 的 11 秒 .wav 文件不应该给出 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;
}

我按照这篇文章中的步骤操作:

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

我仍然遇到这些错误:

enter image description here

最佳答案

问题不是来自 KissFFT,而是因为您正在尝试读取以 ASCII 模式打开的 binary wave 文件:

in = fopen(music_file, "r");

当您稍后尝试使用 fread 读取数据时,您最终遇到了一个无效字符。在您的特定示例文件中,读取的第 215th 个字符是 Substitute Character (hex value 0x1A) ,它被 C 运行时库解释为文件结束标记。相应地,fread停止填充更多数据并最终返回 0(在 WIN 设置为 512 的第二次迭代中,稍后将 WIN 设置为 16)。

要解决这个问题,您应该以二进制方式打开文件:

in = fopen(music_file, "rb");

请注意,这将确保二进制数据按原样读入您的输入缓冲区,但不会为您解码 wave 文件头。要正确读取和解码波形文件并获取有意义的数据,您应该考虑使用音频库(例如 libsndfile 等等)。如果你必须推出自己的 wave 文件阅读器,你应该阅读 specifications和/或查看有关该主题的许多教程之一。

关于c - 在波形文件上使用 KissFFT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35735803/

相关文章:

c - 使用字符串表和打印部分名称

c - Tiva C FFT 库

python - Raise_child异常输出

c++ - 播放wav文件后,是否需要删除缓冲区?

c - 如何可靠地比较 Haskell 和 C 的运行时间?

c - 按位与运算不清楚

C:拼写检查算法的奇怪行为

Javascript:如何确定mp3文件的音乐键

c - 试图解决 C 中未知的段错误

c#播放wav文件后启动秒表