首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >音频处理C++

音频处理C++
EN

Stack Overflow用户
提问于 2012-08-08 01:41:09
回答 3查看 2.8K关注 0票数 6

我可能会问错这个问题,让自己看起来很愚蠢,但这里是这样的:

我正在尝试对一个.wav文件进行一些音频操作和处理。现在,我能够读取所有数据(包括报头),但需要数据是频率的,为此,我需要使用FFT。

我在网上到处搜索,找到了一个例子,这个例子取自“C中的数值配方”一书,然而,我修改了它,使用向量而不是数组。好了,现在的问题是:

我已经被给出了一系列数字和采样率(作为使用的示例):

代码语言:javascript
复制
X = {50, 206, -100, -65, -50, -6, 100, -135}

采样率: 8000样本数:8

因此应该回答这个问题:

代码语言:javascript
复制
  0Hz     A=0       D=1.57079633
  1000Hz     A=50      D=1.57079633
  2000HZ     A=100     D=0
  3000HZ     A=100     D=0
  4000HZ     A=0       D=3.14159265

我重新编写的代码可以编译,但是,当尝试将这些数字输入到等式(函数)中时,我得到了一个分段错误。是我的代码有问题,还是采样率太高?(当使用小得多的采样率时,算法不会进行分段)。代码如下:

代码语言:javascript
复制
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;

#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr;
#define pi 3.14159

void ComplexFFT(vector<float> &realData, vector<float> &actualData, unsigned long sample_num, unsigned int sample_rate, int sign)
{
    unsigned long n, mmax, m, j, istep, i;
    double wtemp,wr,wpr,wpi,wi,theta,tempr,tempi;

    // CHECK TO SEE IF VECTOR IS EMPTY;

    actualData.resize(2*sample_rate, 0);

    for(n=0; (n < sample_rate); n++)
    {
        if(n < sample_num)
        {
            actualData[2*n] = realData[n];
        }else{
            actualData[2*n] = 0;
            actualData[2*n+1] = 0;
        }
    }

    // Binary Inversion
    n = sample_rate << 1;
    j = 0;

    for(i=0; (i< n /2); i+=2)
    {
        if(j > i)
        {
            SWAP(actualData[j], actualData[i]);
            SWAP(actualData[j+1], actualData[i+1]);
            if((j/2)<(n/4))
            {
                SWAP(actualData[(n-(i+2))], actualData[(n-(j+2))]);
                SWAP(actualData[(n-(i+2))+1], actualData[(n-(j+2))+1]);
            }
        }
        m = n >> 1;
         while (m >= 2 && j >= m) {
          j -= m;
          m >>= 1;
         }
         j += m;
     }
     mmax=2;

     while(n > mmax) {

        istep = mmax << 1;
        theta = sign * (2*pi/mmax);
        wtemp = sin(0.5*theta);
        wpr = -2.0*wtemp*wtemp;
        wpi = sin(theta);
        wr = 1.0;
        wi = 0.0;

        for(m=1; (m < mmax); m+=2) {
            for(i=m; (i <= n); i += istep)
            {
                j = i*mmax;
                tempr = wr*actualData[j-1]-wi*actualData[j];
                tempi = wr*actualData[j]+wi*actualData[j-1];

                actualData[j-1] = actualData[i-1] - tempr;
                actualData[j] = actualData[i]-tempi;
                actualData[i-1] += tempr;
                actualData[i] += tempi;
            }
            wr = (wtemp=wr)*wpr-wi*wpi+wr;
            wi = wi*wpr+wtemp*wpi+wi;
        }
        mmax = istep;
    }

    // determine if the fundamental frequency
    int fundemental_frequency = 0;
    for(i=2; (i <= sample_rate); i+=2)
    {
        if((pow(actualData[i], 2)+pow(actualData[i+1], 2)) > pow(actualData[fundemental_frequency], 2)+pow(actualData[fundemental_frequency+1], 2)) {
            fundemental_frequency = i;
        }

    }
}
int main(int argc, char *argv[]) {

    vector<float> numbers;
    vector<float> realNumbers;

    numbers.push_back(50);
    numbers.push_back(206);
    numbers.push_back(-100);
    numbers.push_back(-65);
    numbers.push_back(-50);
    numbers.push_back(-6);
    numbers.push_back(100);
    numbers.push_back(-135);

    ComplexFFT(numbers, realNumbers, 8, 8000, 0);

    for(int i=0; (i < realNumbers.size()); i++)
    {
        cout << realNumbers[i] << "\n";
    }
}

另一件事(我知道这听起来很愚蠢),但我真的不知道通过ComplexFFT函数传递的"int sign“有什么用,这就是我可能出错的地方。

有没有人对这个问题有什么建议或解决方案?

谢谢您:)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-08 02:30:43

我认为问题在于你如何翻译算法的错误。

  • 您的意思是要将j初始化为1而不是0
  • for(i = 0; (i < n/2); i += 2)可能应该是for (i = 1; i < n; i += 2).
  • Your 1SWAP可能应该是

actualDatai);

  • What (actualDataj- 1,actualDatai - 1);SWAP(actualDataj,SWAP是以下SWAP的?我不认为他们是必要的。

如果((j/2)<(n/4)){ SWAP(actualData(n-(i+2)),actualData(n-(j+2);SWAP(actualData(n-(i+2))+1,actualData(n-(j+2))+1);}

  • 如果您打算进行位反转,while (m >= 2 && j >= m)中的j >= m可能应该是j > m

  • 在实现Danielson-Lanczos部分的代码中,您确定j = i*mmax;不应该是加法吗

除此之外,你还可以做很多事情来简化代码。

当您可以只使用std::swap时,应该不鼓励使用SWAP宏...我本打算推荐std::swap_ranges,但后来我意识到您只需要交换实际部分,因为您的数据都是真实的(您的时间序列虚部都是0):

代码语言:javascript
复制
std::swap(actualData[j - 1], actualData[i - 1]);

您也可以使用std::complex来简化整个过程。

票数 4
EN

Stack Overflow用户

发布于 2012-08-08 01:57:55

我认为这归结于你的载体的重新调整。

一种可能性是:我认为调整大小可能会在将临时对象移回堆之前在堆栈上创建临时对象。

票数 2
EN

Stack Overflow用户

发布于 2012-08-08 02:29:29

C中Numerical Recipes中的快速傅立叶变换使用Cooley-Tukey Algorithm,因此在回答您最后提出的问题时,传递的int sign允许使用相同的例程来计算正向(sign=-1)和逆向(sign=1)快速傅立叶变换。这似乎与您在定义theta = sign * (2*pi/mmax)时使用sign的方式一致。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11851245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档