保存在文件中的双样本的FFTW

时间:2016-04-06 11:45:31

标签: c fft fftw libsndfile

我正在尝试使用FFTW库计算53k双样本的FFT,并在此基础上猜测信号的基频是多少。样本由sndfile库根据wav输入文件生成(程序在wav文件中加载,生成双数据样本并将它们保存到文本文件中)。每个样本的数量级范围为-0.0009至+0.0009。在使用下面给出的函数计算FFT之后,我在[0] [0] = -2.142中接收。这是一种检索数据的错误方法,或者输入文件不正确。我究竟做错了什么?传递给FFTW函数的数据是错误的,存储在文件中的数据是不正确还是我写的函数不正确? Buffer是一个包含样本的float数组。

static fftw_complex* calculateFourier(float* buffer, const unsigned int bufferLen)
{

    unsigned int i;
    //const unsigned short windowSize = 1024;
    fftw_plan result;
    fftw_complex *out, *in;

    in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * bufferLen);
    out = (fftw_complex*) fftw_malloc( sizeof(fftw_complex) * bufferLen);

    double* doubleBuffer = castToDouble(buffer, bufferLen);

    for(i = 0; i < bufferLen; i++)
    {
        in[i][0] = doubleBuffer[i];
        in[i][1] = 0.000000000000;
    }

    result = fftw_plan_dft_1d(bufferLen, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
    //result = fftw_plan_dft_r2c_1d(fileSize, castToDouble(buffer, bufferLen), out, FFTW_MEASURE);

    fftw_execute(result);

    fftw_destroy_plan(result);

    return out;
}
static double* castToDouble(float* buffer, const unsigned int bufferLen)
{
    unsigned int i;
    double* doubleBuffer = (double*)malloc( sizeof(double) * bufferLen); 

    for(i = 0; i < bufferLen; i++)
        doubleBuffer[i] = (double)buffer[i];

    return doubleBuffer;

}

2 个答案:

答案 0 :(得分:1)

我认为问题在于您没有对原始数据应用window function。因此,傅里叶变换具有与样本缓冲区长度相对应的强频率分量。

尝试通过替换此行来应用汉宁窗口:

in[i][0] = doubleBuffer[i];

用这个:

in[i][0] = doubleBuffer[i] * 0.5 * (1.0 - cos(2.0 * M_PI * i / (bufferLen - 1)));

(显然,如果你需要重复使用它,可以缓存这个窗口函数。)

答案 1 :(得分:0)

仔细查看以下代码的错误:

#include <stdio.h>

void prn (float *a, int n);

int main (void)
{
    float floatarray[] = { 0.0, 5.0, 10.0, 15.0, 20.0, 25.0 };

    prn (floatarray, sizeof floatarray/sizeof *floatarray);

    return 0;
}

void prn (float *a, int n)
{
    int i;
    double *d = (double *)a;

    for (i = 0; i < n; i++)
        printf (" a[%d] : %01.0lf\n", i, d[i]);
}

运行它,会发生什么?为什么呢?

sizeof一个float是什么?什么是sizeof a double?演员double *d = (double *)a;发生时会发生什么? d的每个元素中预计有多少字节?那里有多少?你的

double* doubleBuffer = castToDouble(buffer, bufferLen);

导致完全相同的问题。

逐个元素转换/分配

无论您使用分配了double(或malloc)的新calloc数组,都必须执行逐个元素转换/赋值完成数组的强制转换。下面是使用可变长度数组添加一些内容的相同代码,以避免动态分配内存:

#include <stdio.h>

void castfloatdouble (double *d, float *f, int n);
void prn (float *a, int n);
void prndouble (double *d, int n);

int main (void)
{
    float floatarray[] = { 0.0, 5.0, 10.0, 15.0, 20.0, 25.0 };
    int n = (int)(sizeof floatarray/sizeof *floatarray);
    double doublearray[n];  /* memset is a good idea to zero a VLA */

    prn (floatarray, n);  /* incorrect results due to typesize mismatch */
    putchar ('\n');

    castfloatdouble (doublearray, floatarray, n);

    prndouble (doublearray, n);  /* correct results after deep cast/assign */
    putchar ('\n');

    return 0;
}

void castfloatdouble (double *d, float *f, int n)
{
    int i;

    for (i = 0; i < n; i++)
        d[i] = (double)f[i];
}

void prn (float *a, int n)
{
    int i;
    double *d = (double *)a;

    for (i = 0; i < n; i++)
        printf (" a[%d] : %01.0lf\n", i, d[i]);
}

void prndouble (double *d, int n)
{
    int i;

    for (i = 0; i < n; i++)
        printf (" a[%d] : %01.0lf\n", i, d[i]);
}

输出显示不正确&amp;正确的结果

$ ./bin/castfloatdouble2
 a[0] : 2048
 a[1] : 16777220
 a[2] : 805306499
 a[3] : 0
 a[4] : 0
 a[5] : 0

 a[0] : 0
 a[1] : 5
 a[2] : 10
 a[3] : 15
 a[4] : 20
 a[5] : 25