2011-05-31 116 views
1

我一直花費相當多的時間研究FFT的。我特別喜歡使用KISSFFT,因爲它是一個非常便攜的C實現。kiss FFT bin幅度

我還很不清楚如何將i [x]和r [x]變成頻率箱的幅度。於是創建了一個有符號的int 16版本的罪。我有512個我的正弦波樣本。我期望看到一個Bin有數據,其餘的都是零。事實並非如此......

這裏是我的代碼...

- (IBAction)testFFT:(id)sender{ 
NSLog(@"testFFT"); 

static double xAxis = 0; 
static int sampleCount = 0; 
static double pieSteps; 
static double fullSinWave = 3.14159265*2; 
static double sampleRate = 44100; 
static double wantedHz = 0; 
int octiveOffset; 
char * globalString = stringToSend; 
SInt16 dataStream[512]; 

// Notes: ioData contains buffers (may be more than one!) 
// Fill them up as much as you can. Remember to set the size value in each buffer to match how 
// much data is in the buffer. 
for (int j = 0; j < 512; j++) { 
    wantedHz = 1000; 
    pieSteps = fullSinWave/(sampleRate/wantedHz); 
    xAxis += pieSteps; 
    dataStream[j] = (SInt16)(sin(xAxis) * 32768.0); 
    NSLog(@"%d) %d", j, dataStream[j]); 
} 

kiss_fft_cfg mycfg = kiss_fft_alloc(512,0,NULL,NULL); 
kiss_fft_cpx* in_buf = malloc(sizeof(kiss_fft_cpx)*512); 
kiss_fft_cpx* out_buf = malloc(sizeof(kiss_fft_cpx)*512); 
for (int i = 0;i < 512;i++){ 
    in_buf[i].r = dataStream[i]; 
    in_buf[i].i = dataStream[i]; 
}  
kiss_fft(mycfg,in_buf, out_buf); 
for (int i = 0;i < 256;i++){ 
    ix = out_buf[i].i; 
    rx = out_buf[i].r; 
    printfbar(sqrt(ix*ix+rx*rx));); 
} 

}

我得到的結果是這樣的....

 

***** 
********************* 
**************************** 
********************* 
************************ 
********************* 
**************************** 
********************* 
***** 
********************* 
**************************** 
********************* 
***************** 
********************* 
**************************** 
********************* 
***** 
********************* 
**************************** 
********************* 
************************ 
********************* 
**************************** 
********************* 

+0

我創造了這個輸出的一個簡單的ASCII圖形,我發現一個規律。我只是不明白這個模式... – 2011-05-31 16:45:09

+4

因爲你在這裏是一個老成員,但從來沒有投過票,從來沒有接受過答案,讓我提醒我們在這裏通常做的三件事:1)當你得到幫助時,試着給它**在您的專業領域回答問題** 2)[閱讀常見問題](http:// tinyurl。3)當你看到很好的問答時,用['灰色三角形](http://i.imgur.com/kygEP.png)「來投票,因爲系統的可信度是基於用戶通過分享知識獲得的聲譽。還請記住接受更好地解決您的問題的答案,[按下複選標記符號](http://tinyurl.com/4srwe2t) – 2011-06-02 03:37:44

回答

2

一對夫婦的編程改變,首先:

xAxis += pieSteps; 
if (xAxis >= fullSinWave) 
    xAxis -= fullSinWave; //wrap x back into 0-2pi period 

將有助於減少數字錯誤。

in_buf[i].r = dataStream[i]; 
in_buf[i].i = 0; 

將輸入緩衝區設置爲sin(x),以前你必須將其設置爲sin(x) + j*sin(x),其中j = sqrt(-1)

wantedHz = 1000;移出循環看起來更好。

還有一個更基本的問題:你設置了wantedHz = 1000。採樣率爲44.1 kHz時,這對應於44100 points/sec * (1/1000) sec/cycle = 44.1 points/cycle。使用512點的緩衝區,您將在緩衝區中獲得11.6個正弦波週期。非整數週期導致leakage

然而,在進入此之前,嘗試設置wantedHz = 12*44100.0/512在緩衝區中準確給出12個週期。您應該在變換中看到兩個尖峯:一個在索引12,另一個在索引511-12。

您會看到兩個尖峯的原因是sin(w_0*x)的變換是j*{-delta(w-w_0) - delta(w+w_0)}。也就是說,你可以在變換的虛部獲得w_0和-w_0的脈衝函數。他們在這些地方的原因是轉換從0到2 * pi。

完成此操作後,請返回wantedH = 1000,在緩衝區中給出非整數個週期數。你應該看到一個寬大的帳篷形結果,圍繞箱11和511-11。您應該通過窗口函數(Hann很好)乘以dataStream來減少這種影響。

+0

非常感謝您抽出時間! – 2011-06-02 15:08:17

+0

這是否意味着我的箱的振幅計算是正確的? – 2011-06-02 15:08:37

2

我一直在與這個圖書館搏鬥,這段代碼可以幫助你測試。這是我在互聯網上閱讀的一段代碼的混合體,看看它是否可能會包含在一個項目中。工作正常。它用原始信號,FFT和逆FFT的波形和值寫入一個文件,只是爲了測試。它與VS2010

#include "kiss_fft.h" 
#include "tools\kiss_fftr.h" 
#include <stdio.h> 
#include <conio.h> 
#define numberOfSamples 1024 

int main(void) 
{ 
    struct KissFFT 
    { 
      kiss_fftr_cfg forwardConfig; 
      kiss_fftr_cfg inverseConfig; 
      kiss_fft_cpx* spectrum; 
      int numSamples; 
      int spectrumSize; 
    } fft; 

    static double dospi = 3.14159265*2; 
    static double sampleRate = 44100; 
    static double wantedHz = 0; 
    int j,i,k; 
    float dataStream[numberOfSamples]; 
    float dataStream2[numberOfSamples]; 
    float mags[numberOfSamples]; 
    FILE * pFile; 

    //Frequency to achive 
    wantedHz = 9517; 

    fft.forwardConfig = kiss_fftr_alloc(numberOfSamples,0,NULL,NULL); 
    fft.inverseConfig = kiss_fftr_alloc(numberOfSamples,1,NULL,NULL); 
    fft.spectrum = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * numberOfSamples); 
    fft.numSamples = numberOfSamples; 
    fft.spectrumSize = numberOfSamples/2+1; 


    pFile = fopen ("c:\\testfft.txt","w"); 
    //filling the buffer data with a senoidal wave of frequency -wantedHz- and printing to testing it 
    for (j = 0; j < numberOfSamples; j++) { 

      dataStream[j] = 32768*(sin(wantedHz*dospi*j/sampleRate)); 
      //Draw the wave form 
      for (k=-64;k<(int)(dataStream[j]/512);k++) fprintf(pFile," "); 
      fprintf(pFile,"*\n"); 
    } 

    //spectrum 
    kiss_fftr(fft.forwardConfig, dataStream, fft.spectrum); 
    //inverse just to testing 
    kiss_fftri(fft.inverseConfig, fft.spectrum, dataStream2); 
    for(i=0;i<fft.spectrumSize;i++) { 
     mags[i] = hypotf(fft.spectrum[i].r,fft.spectrum[i].i); 
     fprintf(pFile,"[Sample %3d] ORIGINAL[%6.0f] -SPECTRUM[%5dHz][%11.0f]",i,dataStream[i],i*(int)sampleRate/numberOfSamples,mags[i]); 
     dataStream2[i] = dataStream2[i]/(float)fft.numSamples; 
     fprintf(pFile,"  -INVERSE[%6.0f]\n",dataStream2[i]); 
    } 
    //end 

    //free and close 
    fclose (pFile); 
    kiss_fft_cleanup(); 
    free(fft.forwardConfig); 
    free(fft.inverseConfig); 
    free(fft.spectrum); 

    getch(); 
    return 0; 

}編譯

+0

請在回答中明確說明如何解決OP的問題。 – meyumer 2013-03-22 18:59:09