【问题标题】:Caculating the PSD using FFTW使用 FFTW 计算 PSD
【发布时间】:2014-06-18 11:56:58
【问题描述】:

我是使用“ALSA”库使用以下设置录制的声音文件:

Fs = 96000; // sample frequency 
channelNumber = 1 ;
format =int16 ; 
length = 5sec;

意思是我得到 480000 16bit 值。现在我想计算该集合的 PSD 以获得类似的结果:

我想要做的是将结果作为一堆双精度值保存在一个额外的数据中,这样我就可以绘制它们来评估它们(我不确定这是否正确):

   #include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fftw3.h>

int main(){
    char fileName[] = "sound.raw";
    char magnFile[] = "data.txt";
    FILE* inp = NULL;
    FILE* oup = NULL;
    float* data = NULL;
    fftwf_complex* out; 
    int index = 0;
    fftwf_plan  plan;
    double var =0;
    short wert = 0;
    float r,i,magn;
    int N = 512;

    data =(float*)fftwf_malloc(sizeof(float)*N);



    out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex)*N);
    //Allocating the memory for the input data 
    plan = fftwf_plan_dft_r2c_1d(N,data,out, FFTW_MEASURE);
    // opening the file for reading 
    inp = fopen(fileName,"r");
    oup = fopen(magnFile,"w+");

    if(inp== NULL){
        printf(" couldn't open the file  \n ");
        return -1;
    }
    if(oup==NULL){
        printf(" couldn't open the output file \n");
    }
    while(!feof(inp)){

            if(index < N){
                fread(&wert,sizeof(short),1,inp);
                //printf(" Wert %d \n",wert);
                data[index] = (float)wert;
                //printf(" Wert %lf \n",data[index]);
                index = index +1;
            }
            else{

                index = 0;
                fftwf_execute(plan);
                //printf("New Plan \n");
                //printf(" Real \t imag \t Magn \t  \n");
                for(index = 0 ; index<N; index++){
                    r=out[index][0];
                    i =out[index][1];
                    magn = sqrt((r*r)+(i*i));
                    printf("%.10lf \t %.10lf \t %.10lf \t \n",r,i,magn);
                    //fwrite(&magn,sizeof(float),1,oup);
                    //fwrite("\n",sizeof(char),1,oup);
                    fprintf(oup,"%.10lf\n ", magn);
                }
                index = 0 ;
                fseek(inp,N,SEEK_CUR);

            }
    }
    fftwf_destroy_plan(plan);
    fftwf_free(data); 
    fftwf_free(out);
    fclose(inp);
    fclose(oup);
    return 0 ; 
}

我遇到的问题是如何在我的代码中实现缠绕功能? 而且我认为结果不准确,因为我的幅度值很多为零? ?
如果有人有一个例子,我将不胜感激。

【问题讨论】:

  • 三分 * 你的截图看起来像 Windows。在这种情况下,您必须使用“rb”打开文件。在任何情况下都应该这样做以提高兼容性。 * 使用已知输入(已知频率的正弦函数)测试您的代码 * 您可能还需要记录幅度的日志
  • 那么您的代码应该可以工作(您只处理前 512 个样本)。
  • 如果您在 FFT 之前应用合适的window function,您将获得更好的结果。关于这个主题已经有很多关于 SO 的问题,并且有一些很好的答案,所以您不必再次涉足相同的领域,您只需搜索这些即可。
  • 英文叫“本末倒置”! ;-)
  • @Engine 尝试增加 N。512 个样本对应 5 ms。我建议 10 毫秒才能捕捉到较低的频率。如果您怀疑您的代码:加载一个长样本并将其转换为 24kHz 的纯正弦波。如果这行得通,您可以继续并实施重叠加法之类的。

标签: c signal-processing fftw


【解决方案1】:

以下是在 FFT 之前将"Hanning" window 应用于您的数据的简单示例:

for (int i = 0; i < N; ++i)
{
    data[i] *= 0.5 * (1.0 + cos(2.0 * M_PI * (double)i / (double)(N - 1)));
}

【讨论】:

  • 所以现在我将在频域中获得这 512 个值的值,我是否应该只用我的窗口到第 513 个元素并一次又一次地这样做,以及如何知道哪个值准确我的新数据 [] 向量中的频率是多少?非常感谢你的回答!
  • 您为每个 N 个样本块应用窗口函数 FFT,即在时域。然后将 FFT 应用于加窗数据,计算输出 bin 的幅度等。如果您担心幅度数据的绝对值,则可以应用合适的校正因子来补偿窗函数,但对于大多数在实际应用中,通常不会这样做,或者将其作为整体校准常数的一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 2019-01-16
  • 1970-01-01
  • 2020-01-09
  • 1970-01-01
  • 2016-08-12
相关资源
最近更新 更多