簡體   English   中英

音頻處理C ++ - FFT

[英]Audio Processing C++ - FFT

我可能會錯誤地問這個並讓自己看起來非常愚蠢但是這里有:

我正在嘗試對.wav文件進行一些音頻操作和處理。 現在,我能夠讀取所有數據(包括標題),但需要數據處於頻率,為此,我需要使用FFT。

我搜索了互聯網的高低,找到了一個,這個例子取自“C中的數字食譜”一書,然而,我修改它使用向量而不是數組。 好的,這就是問題所在:

我被給予(作為一個例子使用)一系列數字和采樣率:

X = {50, 206, -100, -65, -50, -6, 100, -135}

采樣率:8000樣本數:8

因此應該回答這個問題:

  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

我重寫的代碼編譯,然而,當試圖將這些數字輸入到等式(函數)中時,我得到了一個分段錯誤。我的代碼有問題,或者采樣率是否過高? (當使用更小,更小的采樣率時,算法不會分段)。 這是代碼:

#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符號”的期望是什么,這是我可能出錯的地方。

有沒有人對這個問題有任何建議或解決方案?

謝謝 :)

我認為問題在於你如何翻譯算法的錯誤。

  • 你的意思是將j初始化為1而不是0嗎?

  • for(i = 0; (i < n/2); i += 2)應該是for (i = 1; i < n; i += 2)

  • 您的SWAP可能應該是

     SWAP(actualData[j - 1], actualData[i - 1]); SWAP(actualData[j], actualData[i]); 
  • 以下什么是SWAP 我不認為他們是需要的。

     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]); } 
  • j >= mwhile (m >= 2 && j >= m) 大概應該是j > m ,如果你打算做位反轉。

  • 在實現Danielson-Lanczos部分的代碼中,你確定j = i*mmax; 不應該是一個加法,即j = i + mmax;


除此之外,您可以做很多事情來簡化代碼。

當你只能使用std::swap時,不鼓勵使用你的SWAP宏......我打算建議使用std::swap_ranges ,但后來我意識到你只需交換真實的部分,因為你的數據都是實數(你的數據)時間序列虛部全部為0 ):

std::swap(actualData[j - 1], actualData[i - 1]);

您也可以使用std::complex簡化整個過程。

我認為它的重新調整了你的向量。

一種可能性:也許重新調整大小會在堆棧中創建臨時對象,然后再將它們移回堆中。

C中的數字配方中的FFT使用Cooley-Tukey算法 ,因此在最后回答您的問題時,傳遞的int sign允許使用相同的例程來計算forward( sign=-1 )和inverse( sign=1 )FFT。 這似乎與您在定義theta = sign * (2*pi/mmax)時使用sign的方式一致。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM