⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fft.cpp

📁 用fpga实现dsp 的fft算法 其中有几个文档文件和用vhdl写的1024点的fft代码
💻 CPP
字号:
// fft -- a program to model a Fast Fourier Transform (FFT).//// Copyright (C) 2001 John Dalton//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// Include required libraries#include <vector>#include <math.h>#include <iostream>#include <complex>#include <stdlib.h>//// factor//// Return a factor of a number.//// Inputs:  x = the number to be factored.// Returns: A factor of 'x'.  If 'x' is a//          prime, eith 'x' or the number//          one will be returned.//long factor(long x){  long i;  for(i=2; i<x; i++) {    if(x%i==0) {      return(i);    }  }  return(1);}//Paramatise the type of each element//to allow it to be changed easily#define element_type double_complex//This routine does one stage of an FFT.//// fft_stage//// Do a set of FFTs.  The length of the FFT may be// smaller than the length of the input sequence.// In this case, multiple FFTs will be performed.// If the length of the FFT is a composite number,// it is recusively decomposed into smaller FFTs// whose lengths are prime numbers.  The elements// of each FFT do not need to be consecutive.//// Inputs:  in = A sequence of numbers to be transformed.//          fft_length = The number of points in each FFT//          grouping = The separation between each element//                     within an FFT.// Returns: The transformed sequence.//vector<element_type> fft_stage(vector<element_type> in, int fft_length, int grouping){  int x, y;  vector<element_type> out(in.size());  int f;  //  cout<<"***FFT"<<fft_length<<" Grouping:"<<grouping<<" Array Length:"<<in.size()<<"\n";  // A DFT of length does nothing, so just  // return the input  if(fft_length <=1) {    out = in;    return(out);  }  // Factorise the number of points in the DFT (if possible)  // so we can break it into two smaller DFTs  f = factor(fft_length);  // If the number of points in the DFT is a composite  // number (ie. can be factorised), divide it into  // two smaller DFTs.  Recurse until the DFT has been  // decomposed into DTFs of prime length.  if(f!=fft_length &&f!=1) {    int P = f;    int Q = fft_length / f;    vector<element_type> intermediate(in.size());    //Do a DFT along one dimension    intermediate = fft_stage(in, P, grouping*Q);    //Multiply by twiddle factors    for(int xx=0; xx<intermediate.size(); xx+=P*Q) {      for(int a=0; a<P; a++) {        for(int q=0; q<Q; q++) {	  intermediate[xx+a*Q+q] = intermediate[xx+a*Q+q] * exp(-double_complex(0,1)*2*M_PI/(P*Q)*a*q);        }      }    }    //Do a DFT along a second, orthogonal, dimension    out = fft_stage(intermediate, Q, grouping);    return(out);  }  // Here if the length for the DFT was prime.     for(x=0; x<in.size(); x+=fft_length*grouping) {    for(y=x; y<x+grouping; y++) {      //If the length of the DFT is two, do a butterfly      //operation.      if(fft_length==2) {          out[y         ] = in[y] + in[y+grouping];         out[y+grouping] = in[y] - in[y+grouping];      } else { //do an exhaustive DFT (for the time being)        //For other prime length DTFs (3,5,7,11,...) do a        //full DFT.  I'm still looking for a more efficient        //algorithm to use here.  Any suggestions?        for(int k=0; k<fft_length; k++) {          out[y+k*grouping] = 0;          for(int n=0; n<fft_length; n++){            out[y+k*grouping] += in[y+n*grouping]*exp(-double_complex(0,1)*n*k*2*M_PI/fft_length);	  }	}      }    }  }  return(out);}//// fft//// Do an FFT.  There are no restrictions on the// length of the FFT, but a power of two will// yield the most efficient calculation.// This is the routine you should call to do// an FFT (not fft_stage).//// Inputs:  in = A sequence of numbers to be transformed.// Returns: The transformed sequence.//vector<element_type> fft(vector<element_type> in){  return( fft_stage(in, in.size(), 1) );}//// golden_dft_model//// Do a Discrete Fourier Transform (DFT).// This is the model against which results// of the FFT will be compared.//// Inputs:  in = A sequence of numbers to be transformed.// Returns: The transformed sequence.//vector<element_type> golden_dft_model(vector<element_type> in){  vector<element_type> out(in.size());  for(int k=0; k<out.size(); k++) {    out[k] = 0;    for(int n=0; n<in.size(); n++) {      out[k] += in[n]*exp(-double_complex(0,1)*2*M_PI*n*k/in.size());    }  }  return(out);}//Reproduce the order in which the outputs of the FFT appear//// order//// This function reproduces the order of the// outputs of the FFT.  For an FFT of length a// power of two, the order will be bit reversed.// For other lengths, the ordering will be slightly// more complicated.//// Inputs:  in = A sequence of numbers 1,2,3,...,N-1.//          length = The length of the FFT whose output//                   ordering is to be reproduced.//          grouping = The separation between each element//                     of the FFT.// Returns: A sequence whose order corresponds to the//          order of the FFT's outputs.//vector<int> order(vector<int> in, int length, int grouping){  vector<int> out(in.size());  int f;   if(length <=1) {    out = in;    return(out);  }  f = factor(length);  if(f!=length &&f!=1) {    int P = f;    int Q = length / f;    vector<int> intermediate(in.size());    //    intermediate = order(in, P, grouping*Q);    //out = order(intermediate, Q, grouping);    intermediate = order(in, Q, grouping*P);    out = order(intermediate, P, grouping);    return(out);  }  for(int x=0; x<in.size(); x+=length*grouping) {    for(int y=0; y<grouping; y++) {      for(int k=0; k<length; k++) {        out[x+y+k*grouping] = in[x+y*length+k];      }    }  }  return(out);}//// near//// Check if two complex numbers are equal,// to within some approximation.//// Inputs:  a = The first complex number.//          b = The second complex number.// Returns: One if the two numbers are equal, zero otherwise.//int near(element_type a, element_type b){  const double epsilon = 1e-12;  if( fabs(a.real()-b.real()) <= epsilon && fabs(a.imag()-b.imag()) <= epsilon ) {    return(1);  }  return(0);}//// test_fft//// Do an FFT and compare the results with the// output of the corresponging DFT.  If the// results are not the same, print an// error message.//// Inputs:  in = The complex sequence to be transformed.// Outputs: failed = Non-zero if the test failed, zero if it suceeded.// Returns: The results of the FFT.//vector<element_type> test_fft(vector<element_type> in, int *failed){  vector<element_type> out(in.size()), reference(in.size());  vector<int> index(in.size());  out = fft(in);  reference = golden_dft_model(in);  for(int i=0; i<index.size(); i++) {    index[i] = i;  }  index = order(index, index.size(), 1);     //for(int i=0; i<index.size(); i++) {  //  cout << index[i] << ((i==index.size()-1)?'\n':',');  //}  for(int i=0; i<index.size(); i++) {    if( !near(reference[i], out[index[i]]) ) {      cout << "FFT Test Failed!\n";      cout << i << ": " << reference[i] << " != " << out[index[i]] << "\n";      for(int j=0; j<in.size(); j++) {        cout << j << ": " << in[j] << " " << reference[j] << " " << out[index[j]] << "\n";      }      *failed = 1;      return(out);    }  }  *failed = 0;  return(out);}//// main//// Run a series of tests to verify an FFT.//// Inputs:  None.// Outputs: None.// Returns: Zero if the tests suceed.  Non-zero otherwise.//main(){  int i;  int length;  int failed;  //const double freq = 3.0;  // Do a series of tests using walking tones on a  // series of different length FFTs.  Assuming linearity,  // these tests should prove the FFT correct.  cout<< "Tone Test.\n";  cout.flush();  for(length=1; length<=32; length++) {    vector<element_type> in(length), out(length);    for(double freq=0; freq<length; freq++){      for(i=0; i<length; i++) {        //  in[i] = i;        in[i] = exp(double_complex(0,1)*2.0*M_PI/length*freq*i);      }      for(i=0; i<length; i++) {        //   cout << in[i] << ((i==length-1)?'\n':',');      }      out = test_fft(in, &failed);      if(failed) {        exit(1);      }      for(i=0; i<length; i++) {        //cout << "(" << (int)(out[i].real()*100.0)/100 << "," << (int)(out[i].imag()*100.0)/100 << ")"  << ((i==length-1)?'\n':',');      }    }    }  // Do a series of tests with random data and  // random length FFTs.  These test double check  // that nothing is wrong.  cout<< "Monte Carlo Test.\n";  cout.flush();  int max_length = 100;  for(i=0; i<100000; i++) {    int length = rand()%max_length;    vector<element_type> in(length);    //   cout<< length << " ";    //cout.flush();    for(int i=0; i<in.size(); i++) {      in[i] = 1.0-2.0*(double)rand()/(double)RAND_MAX;    }    test_fft(in, &failed);    if(failed) {      exit(1);    }  }  cout << "PASSED ALL TESTS.\n";  return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -