114 lines
3.4 KiB
C
114 lines
3.4 KiB
C
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef FFTCodeH
|
||
|
#define FFTCodeH
|
||
|
|
||
|
|
||
|
#define M_2PI 6.28318530717958647692
|
||
|
#define MAXIMUM_FFT_SIZE 1048576
|
||
|
#define MINIMUM_FFT_SIZE 8
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Must retain the order on the 1st line for legacy FIR code.
|
||
|
typedef enum {wtFIRSTWINDOW = 0, wtNONE, wtKAISER, wtSINC, wtHANNING,
|
||
|
wtHAMMING, wtBLACKMAN, wtFLATTOP, wtBLACKMAN_HARRIS,
|
||
|
wtBLACKMAN_NUTTALL, wtNUTTALL, wtKAISER_BESSEL, wtTRAPEZOID,
|
||
|
wtGAUSS, wtSINE, wtTEST } TWindowType;
|
||
|
|
||
|
typedef enum {FORWARD = 0, INVERSE} TTransFormType;
|
||
|
|
||
|
|
||
|
int RequiredFFTSize(int NumPts);
|
||
|
int IsValidFFTSize(int x);
|
||
|
//void FFT(double *InputR, double *InputI, int N, TTransFormType Type);
|
||
|
void ReArrangeInput(double *InputR, double *InputI, double *BufferR, double *BufferI, int *RevBits, int N);
|
||
|
void FillTwiddleArray(double *TwiddleR, double *TwiddleI, int N, TTransFormType Type);
|
||
|
void Transform(double *InputR, double *InputI, double *BufferR, double *BufferI, double *TwiddleR, double *TwiddleI, int N);
|
||
|
void DFT(double *InputR, double *InputI, int N, int Type);
|
||
|
void RealSigDFT(double *Samples, double *OutputR, double *OutputI, int N);
|
||
|
double SingleFreqDFT(double *Samples, int N, double Omega);
|
||
|
double Goertzel(double *Samples, int N, double Omega);
|
||
|
void WindowData(double *Data, int N, TWindowType WindowType, double Alpha, double Beta, bool UnityGain);
|
||
|
double Bessel(double x);
|
||
|
double Sinc(double x);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
// This algorithm is a bit faster than the one in the cpp file.
|
||
|
// For some reason, it is faster to calculate the next twiddle factor with recursion
|
||
|
// than it is to access the Twiddle arrays. It is also faster to use the Sum and Twid
|
||
|
// variables in the inner loop rather than the Output and Twiddle arrays.
|
||
|
// 256 pts in 540 ms
|
||
|
void RealSigDFT(double *Samples, double *OutputR, double *OutputI, int N)
|
||
|
{
|
||
|
int j, k;
|
||
|
double Arg, Temp, zReal, zImag, TwidR, TwidI; // z, as in e^(j*omega)
|
||
|
double SumReal, SumImag;
|
||
|
static double *TwiddleReal, *TwiddleImag;
|
||
|
static int M = -1;
|
||
|
|
||
|
// This calculates the twiddle factors on the 1st call or when N changes.
|
||
|
if(M != N)
|
||
|
{
|
||
|
if(M != -1) // M = -1 on the 1st call.
|
||
|
{
|
||
|
delete[] TwiddleReal;
|
||
|
delete[] TwiddleImag;
|
||
|
}
|
||
|
|
||
|
M = N;
|
||
|
TwiddleReal = new(std::nothrow) double[N];
|
||
|
TwiddleImag = new(std::nothrow) double[N];
|
||
|
if(TwiddleReal == NULL || TwiddleImag == NULL)
|
||
|
{
|
||
|
ShowMessage("Failed to allocate memory in FIRFreqResponse");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for(j=0; j<N; j++)
|
||
|
{
|
||
|
Arg = M_2PI * (double)j / (double)N;
|
||
|
TwiddleReal[j] = cos(Arg);
|
||
|
TwiddleImag[j] = -sin(Arg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// We have a real input, so only do the pos frequencies. i.e. j<N/2
|
||
|
for(j=0; j<N/2; j++)
|
||
|
{
|
||
|
zReal = 1.0;
|
||
|
zImag = 0.0;
|
||
|
SumReal = 0.0;
|
||
|
SumImag = 0.0;
|
||
|
TwidR = TwiddleReal[j];
|
||
|
TwidI = TwiddleImag[j];
|
||
|
|
||
|
for(k=0; k<N; k++)
|
||
|
{
|
||
|
SumReal += Samples[k] * zReal;
|
||
|
SumImag += Samples[k] * zImag;
|
||
|
|
||
|
// Calc the next twiddle factor recursively.
|
||
|
Temp = zReal * TwidR - zImag * TwidI;
|
||
|
zImag = zReal * TwidI + zImag * TwidR;
|
||
|
zReal = Temp;
|
||
|
}
|
||
|
|
||
|
OutputR[j] = SumReal / (double)N;
|
||
|
OutputI[j] = SumImag / (double)N;
|
||
|
}
|
||
|
|
||
|
// The neg freq components are the conj of the pos components because the input signal is real.
|
||
|
for(j=1; j<N/2; j++)
|
||
|
{
|
||
|
OutputR[N-j] = OutputR[j];
|
||
|
OutputI[N-j] = -OutputI[j];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
*/
|