/* SigLib Chirp z-Transform Example The chirp z-transform algorithm is shown in the following diagram : _____ vL | | VL -------------| FFT |------- |_____| | _____ | ______ xN yN->yL | | YL | GL | | gL->gM xM ----O--------| FFT |------O-----| IFFT |---------O------ | |_____| |______| | | | | AWNr, AWNi | wM The input vector length is 150 samples, the output vector length is 100 samples and the FFTs are 256 points, which must be >> (input + output lengths - 1). The input data files have been sampled at 10 KHz. In some applications a pre-window can assist the analysis e.g. Hanning. This program individually initialises all the vectors for the sake of demonstration. A neater way of coding this is to use the czt_init() function. */ /* Include files */ #include #include #include #include #include "GraphFunctions.h" /* Define constants */ #define DEBUG 0 /* Set to 0 for no debug */ #define SAMPLE_RATE 10000.0 /* 10 KHz */ #define INPUT_LENGTH ((SLArrayIndex_t)150) /* Input array length */ #define OUTPUT_LENGTH ((SLArrayIndex_t)100) #define WINDOW_SIZE INPUT_LENGTH #define FFT_SIZE 256L #define LOG_FFT_SIZE ((SLArrayIndex_t)8) /* Declare global variables */ SLFixData_t waveform; SLData_t Radius, Decay, StartFreq, EndFreq; SLComplexPolar_s ContourStart; SLComplexRect_s temp; SLData_t deltaomega, deltasigma; /* Variables used to calculate W */ SLData_t phinc, w1inc, w2inc; SLComplexRect_s A_1, W1, W_1, W12, W_12; /* Complex contour coeffs */ SLData_t *pInput, *pResults; SLData_t *pRealData, *pImagData, *pWindowCoeffs, *pFFTCoeffs; SLData_t *pAWNr, *pAWNi, *pvLr, *pvLi, *pWMr, *pWMi; SLData_t *pCZTRealWork, *pCZTImagWork; void main(void); void main(void) { GraphObject *h2DGraph; /* Declare graph object */ pInput = SUF_VectorArrayAllocate (INPUT_LENGTH); pRealData = SUF_VectorArrayAllocate (FFT_SIZE); pImagData = SUF_VectorArrayAllocate (FFT_SIZE); pWindowCoeffs = SUF_VectorArrayAllocate (WINDOW_SIZE); pAWNr = SUF_VectorArrayAllocate (INPUT_LENGTH); pAWNi = SUF_VectorArrayAllocate (INPUT_LENGTH); pvLr = SUF_VectorArrayAllocate (FFT_SIZE); pvLi = SUF_VectorArrayAllocate (FFT_SIZE); pCZTRealWork = SUF_VectorArrayAllocate (FFT_SIZE); pCZTImagWork = SUF_VectorArrayAllocate (FFT_SIZE); pWMr = SUF_VectorArrayAllocate (OUTPUT_LENGTH); pWMi = SUF_VectorArrayAllocate (OUTPUT_LENGTH); pResults = SUF_VectorArrayAllocate (OUTPUT_LENGTH); pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_SIZE); if ((pInput == NULL) || (pRealData == NULL) || (pImagData == NULL) || (pWindowCoeffs == NULL) || (pAWNr == NULL) || (pAWNi == NULL) || (pvLr == NULL) || (pvLi == NULL) || (pWMr == NULL) || (pWMi == NULL) || (pResults == NULL) || (pFFTCoeffs == NULL)) { printf ("\n\nMalloc failed\n\n"); exit (0); } system ("cls"); printf ("\n\n\n"); printf ("Choose a waveform file\n\n"); printf ("(Sample rate = 10 KHz)\n\n"); printf ("AA.SIG ... (1)\n"); printf ("EE.SIG ... (2)\n"); printf ("ER.SIG ... (3)\n"); printf ("I.SIG ... (4)\n"); printf ("OO.SIG ... (5)\n\n"); printf (">"); scanf ("%d", &waveform); switch (waveform) { case 1 : printf ("Opening AA.SIG\n\n"); read_buffer (pInput, "aa.sig", INPUT_LENGTH); /* Read data from disk */ break; case 2 : printf ("Opening EE.SIG\n\n"); read_buffer (pInput, "ee.sig", INPUT_LENGTH); /* Read data from disk */ break; case 3 : printf ("Opening ER.SIG\n\n"); read_buffer (pInput, "er.sig", INPUT_LENGTH); /* Read data from disk */ break; case 4 : printf ("Opening I.SIG\n\n"); read_buffer (pInput, "i.sig", INPUT_LENGTH); /* Read data from disk */ break; case 5 : printf ("Opening OO.SIG\n\n"); read_buffer (pInput, "oo.sig", INPUT_LENGTH); /* Read data from disk */ break; default : printf ("\nInvalid result\n\n"); exit (0); break; } printf ("\n\nEnter radius (r>0.9) >"); scanf ("%lf", &Radius); printf ("\n\nEnter decay (Delta sigma / 2 * SIGLIB_PI) >"); scanf ("%lf", &Decay); printf ("\n\nEnter start_freq >"); scanf ("%lf", &StartFreq); printf ("\n\nEnter end_freq >"); scanf ("%lf", &EndFreq); getchar (); /* Clear the CR in the pipeline */ /* Calculate A0 values */ ContourStart = SCV_Polar (Radius, (StartFreq / SAMPLE_RATE) * SIGLIB_TWO_PI); temp = SCV_PolarToRectangular (ContourStart); A_1 = SCV_Inverse (temp); /* Calculate W0 values - W^(N^2/2) */ deltaomega = (EndFreq - StartFreq) / ((SLData_t)OUTPUT_LENGTH - SIGLIB_ONE); deltasigma = Decay; phinc = SIGLIB_TWO * (-SIGLIB_PI) * deltaomega / SAMPLE_RATE; w1inc = SDS_Exp (SIGLIB_TWO * SIGLIB_PI * deltasigma / SAMPLE_RATE); w2inc = SDS_Sqrt (w1inc); W1.real = w1inc * SDS_Cos (phinc); /* W */ W1.imag = w1inc * sin (phinc); W12.real = w2inc * SDS_Cos (phinc / SIGLIB_TWO); /* W^(1/2) */ W12.imag = w2inc * SDS_Sin (phinc / SIGLIB_TWO); W_1.real = (SIGLIB_ONE / w1inc) * SDS_Cos (-phinc); /* W^(-1) */ W_1.imag = (SIGLIB_ONE / w1inc) * SDS_Sin (-phinc); W_12.real = (SIGLIB_ONE / w2inc) * SDS_Cos (-phinc / SIGLIB_TWO); /* W^(-1/2) */ W_12.imag = (SIGLIB_ONE / w2inc) * SDS_Sin (-phinc / SIGLIB_TWO); #if DEBUG printf ("phinc = %lf\n", phinc); printf ("w1inc = %lf\n", w1inc); printf ("w2inc = %lf\n\n", w2inc); printf ("A_1.real = %lf\n", A_1.real); printf ("A_1.imag = %lf\n\n", A_1.imag); printf ("W1.real = %lf\n", W1.real); printf ("W1.imag = %lf\n", W1.imag); printf ("W12.real = %lf\n", W12.real); printf ("W12.imag = %lf\n\n", W12.imag); printf ("W_1.real = %lf\n", W_1.real); printf ("W_1.imag = %lf\n", W_1.imag); printf ("W_12.real = %lf\n", W_12.real); printf ("W_12.imag = %lf\n\n", W_12.imag); getchar (); #endif h2DGraph = /* Initialize graph */ Create2DGraph ("Chirp z-Transform", /* Graph title */ "Time / Frequency", /* X-Axis label */ "Magnitude", /* Y-Axis label */ SV_AUTO_SCALE, /* Scaling mode */ SV_SIGNED, /* Sign mode */ SV_GRAPH_LINE, /* Graph type */ "localhost"); /* Graph server */ if (h2DGraph == NULL) /* Graph creation failed - e.g is server running ? */ { printf ("\nGraph creation failure. Please check that the server is running\n"); exit (1); } /* Initialise FFT */ SIF_Fft (pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_SIZE); /* FFT Size */ /* Gen. complex window coeffs */ SIF_Awn (pAWNr, /* Real coefficient pointer */ pAWNi, /* Imaginary coefficient pointer */ A_1, /* A ^ (-1) */ W1, /* W */ W12, /* W^(1/2) */ INPUT_LENGTH); /* Array length */ /* Gen. contour definition coeffs */ SIF_Vl (pvLr, /* Real coefficient pointer */ pvLi, /* Imaginary coefficient pointer */ W_1, /* W^(-1) */ W_12, /* W^(-1/2) */ INPUT_LENGTH, /* Input array length */ OUTPUT_LENGTH, /* Output array length */ FFT_SIZE); /* FFT array length */ /* Gen. weighting coeffs */ SIF_Wm (pWMr, /* Real coefficient pointer */ pWMi, /* Imaginary coefficient pointer */ W1, /* W */ W12, /* W^(1/2) */ OUTPUT_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Source Signal", /* Title of the dataset */ pInput, /* Array of Double dataset */ INPUT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_BLUE, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nSource Signal\nPlease hit to continue . . ."); getchar (); /* Ensure zero padded samples */ SDA_Clear (pCZTRealWork, /* Pointer to destination array */ FFT_SIZE); /* Array length */ SDA_Clear (pCZTImagWork, /* Pointer to destination array */ FFT_SIZE); /* Array length */ /* Complex window = complex mpy with real data */ SDA_ComplexWindow (pInput, /* Pointer to real source array */ pInput, /* Pointer to imaginary source array */ pCZTRealWork, /* Pointer to real destination array */ pCZTImagWork, /* Pointer to imaginary destination array */ pAWNr, /* Real window array pointer */ pAWNi, /* Imaginary window array pointer */ INPUT_LENGTH); /* Window size */ /* Frequency domain convolution */ SDA_Cfft (pCZTRealWork, /* Pointer to real array */ pCZTImagWork, /* Pointer to imaginary array */ pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_SIZE, /* FFT size */ LOG_FFT_SIZE); /* log2 FFT size */ SDA_ComplexMultiply2 (pCZTRealWork, /* Pointer to real source array 1 */ pCZTImagWork, /* Pointer to imaginary source array 1 */ pvLr, /* Pointer to real source array 2 */ pvLi, /* Pointer to imaginary source array 2 */ pCZTRealWork, /* Pointer to real destination array */ pCZTImagWork, /* Pointer to imaginary destination array */ FFT_SIZE); /* Array lengths */ /* IFFT */ SDA_Cifft (pCZTRealWork, /* Pointer to real array */ pCZTImagWork, /* Pointer to imaginary array */ pFFTCoeffs, /* Pointer to FFT coefficients */ SIGLIB_NULL_ARRAY_INDEX_PTR, /* Pointer to bit reverse address table - NOT USED */ FFT_SIZE, /* FFT size */ LOG_FFT_SIZE); /* log2 FFT size */ /* Complex multiply */ SDA_ComplexMultiply2 (pWMr, /* Pointer to real source array 1 */ pWMi, /* Pointer to imaginary source array 1 */ pCZTRealWork, /* Pointer to real source array 2 */ pCZTImagWork, /* Pointer to imaginary source array 2 */ pRealData, /* Pointer to real destination array */ pImagData, /* Pointer to imaginary destination array */ OUTPUT_LENGTH); /* Array lengths */ /* Scale chirp z-transform results */ SDA_ComplexScalarDivide (pRealData, /* Pointer to real source array */ pImagData, /* Pointer to imaginary source array */ ((SLData_t)INPUT_LENGTH) * ((SLData_t)FFT_SIZE), /* Divisor */ pRealData, /* Pointer to real destination array */ pImagData, /* Pointer to imaginary destination array */ OUTPUT_LENGTH); /* Array lengths */ /* Calculate real magnitude from complex */ SDA_Magnitude (pRealData, /* Pointer to real source array */ pImagData, /* Pointer to imaginary source array */ pResults, /* Pointer to magnitude destination array */ OUTPUT_LENGTH); /* Array length */ /* Scale results so peaks equal 100.0 */ SDA_Scale (pResults, /* Pointer to source array */ pResults, /* Pointer to destination array */ ((SLData_t)100.0), /* Peak level */ OUTPUT_LENGTH); /* Array length */ /* dB scaling */ SDA_20Log10 (pResults, /* Pointer to source array */ pResults, /* Pointer to destination array */ OUTPUT_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "chirp z-Transform", /* Title of the dataset */ pResults, /* Array of Double dataset */ OUTPUT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_BLUE, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nchirp z-Transform\n"); SUF_MemoryFree (pInput); /* Free memory */ SUF_MemoryFree (pRealData); SUF_MemoryFree (pImagData); SUF_MemoryFree (pWindowCoeffs); SUF_MemoryFree (pAWNr); SUF_MemoryFree (pAWNi); SUF_MemoryFree (pvLr); SUF_MemoryFree (pvLi); SUF_MemoryFree (pCZTRealWork); SUF_MemoryFree (pCZTImagWork); SUF_MemoryFree (pWMr); SUF_MemoryFree (pWMi); SUF_MemoryFree (pResults); SUF_MemoryFree (pFFTCoeffs); }