/* Bilinear Transform IIR Filter Design Example. Generates a low pass filter and transforms the frequency */ #include #include #include #include "GraphFunctions.h" /* Define constants */ #define PRINT_RESULTS 0 /* Set to 1 to print results as well as plot them */ /* Select which transforms to perform */ #define TRANSFORM_L_L 1 /* Low pass to low pass transformation */ #define TRANSFORM_L_H 1 /* Low pass to high pass transformation */ #define TRANSFORM_L_P 1 /* Low pass to band pass transformation */ #define TRANSFORM_L_S 1 /* Low pass to band stop transformation */ #define SAMPLE_RATE SIGLIB_ONE /* Normalized to 1.0 Hz for convenience */ #define PREWARP_MATCH_FREQUENCY ((SLData_t)0.2) /* Low pass filter cut-off frequency */ #define NUMBER_OF_ZEROS 5L #define NUMBER_OF_POLES 5L #define NUMBER_OF_FILTER_COEFFS (SIGLIB_IIR_COEFFS_PER_BIQUAD*NUMBER_OF_ZEROS) #define FILTER_STAGES NUMBER_OF_ZEROS /* Number of 2nd-order filter stages */ #define LPF_TO_LPF_NEW_FC ((SLData_t)0.3) #define LPF_TO_BPF_NEW_FC1 ((SLData_t)0.1) #define LPF_TO_BPF_NEW_FC2 ((SLData_t)0.3) #define LPF_TO_BSF_NEW_FC1 ((SLData_t)0.1) #define LPF_TO_BSF_NEW_FC2 ((SLData_t)0.3) #define LPF_TO_HPF_NEW_FC ((SLData_t)0.3) #define IMPULSE_RESPONSE_LENGTH ((SLArrayIndex_t)1024) #define FFT_SIZE IMPULSE_RESPONSE_LENGTH #define LOG_FFT_SIZE ((SLArrayIndex_t)10) #define PLOT_LENGTH (IMPULSE_RESPONSE_LENGTH/2L) /* Declare global variables */ SLComplexRect_s SPlaneZeros [NUMBER_OF_ZEROS]; SLComplexRect_s SPlanePoles [NUMBER_OF_POLES]; SLComplexRect_s ZPlaneZeros [NUMBER_OF_ZEROS]; SLComplexRect_s ZPlanePoles [NUMBER_OF_POLES]; SLComplexRect_s TransformedZPlaneZeros [2*NUMBER_OF_ZEROS]; /* Need twice number of poles and zeros for BPFs and BSFs */ SLComplexRect_s TransformedZPlanePoles [2*NUMBER_OF_POLES]; SLData_t *pFilterState, *pIIRCoeffs; SLData_t *pSrc, *pRealData, *pImagData, *pResults, *pFFTCoeffs; void main (void) { GraphObject *h2DGraph; /* Declare graph objects */ GraphObject *hPZGraph; /* Allocate memory */ /* Need twice number of poles and zeros for BPFs and BSFs */ pIIRCoeffs = SUF_IirCoefficientAllocate (2 * FILTER_STAGES); pFilterState = SUF_IirStateArrayAllocate (2 * FILTER_STAGES); pRealData = SUF_VectorArrayAllocate (FFT_SIZE); pImagData = SUF_VectorArrayAllocate (FFT_SIZE); pResults = SUF_VectorArrayAllocate (PLOT_LENGTH); pSrc = SUF_VectorArrayAllocate (IMPULSE_RESPONSE_LENGTH); pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_SIZE); if ((pIIRCoeffs == NULL) || (pRealData == NULL) || (pImagData == NULL) || (pResults == NULL) || (pSrc == NULL) || (pFFTCoeffs == NULL)) { printf ("\n\nMemory allocation failed\n\n"); exit (0); } /* Initialise s-plane zero and pole positions */ /* Create rectangular numbers from real and imaginary components */ SPlaneZeros[0] = SCV_Rectangular (((SLData_t)0.0), ((SLData_t)3.0)); SPlaneZeros[1] = SCV_Rectangular (((SLData_t)0.0), ((SLData_t)3.0)); SPlaneZeros[2] = SCV_Rectangular (((SLData_t)0.0), ((SLData_t)3.0)); SPlaneZeros[3] = SCV_Rectangular (((SLData_t)0.0), ((SLData_t)3.0)); SPlaneZeros[4] = SCV_Rectangular (((SLData_t)0.0), ((SLData_t)3.0)); SPlanePoles[0] = SCV_Rectangular (((SLData_t)-0.1), ((SLData_t)0.9)); SPlanePoles[1] = SCV_Rectangular (((SLData_t)-0.3), ((SLData_t)0.8)); SPlanePoles[2] = SCV_Rectangular (((SLData_t)-0.6), ((SLData_t)0.7)); SPlanePoles[3] = SCV_Rectangular (((SLData_t)-0.8), ((SLData_t)0.6)); SPlanePoles[4] = SCV_Rectangular (((SLData_t)-0.9), ((SLData_t)0.3)); #if PRINT_RESULTS printf ("\nComplex s-plane zeros\n"); /* Print s-plane poles and zeros */ for (i = 0; i < NUMBER_OF_ZEROS; i++) print_rectangular (SPlaneZeros[i]); printf ("\nComplex s-plane poles\n"); for (i = 0; i < NUMBER_OF_POLES; i++) print_rectangular (SPlanePoles[i]); #endif /* Convert z-plane poles and zeros to s-plane */ /* using the bilinear transform */ SDA_BilinearTransform (SPlaneZeros, /* S-plane zeros */ SPlanePoles, /* S-plane poles */ ZPlaneZeros, /* Z-plane zeros */ ZPlanePoles, /* Z-plane poles */ SAMPLE_RATE, /* Sample rate */ PREWARP_MATCH_FREQUENCY, /* Pre-warp frequency */ SIGLIB_ON, /* Pre-warp switch */ NUMBER_OF_ZEROS, /* Number of zeros */ NUMBER_OF_POLES); /* Number of poles */ #if PRINT_RESULTS printf ("\nComplex z-plane zeros\n"); /* Print z-plane poles and zeros */ for (i = 0; i < NUMBER_OF_ZEROS; i++) print_rectangular (ZPlaneZeros[i]); printf ("\nComplex z-plane poles\n"); for (i = 0; i < NUMBER_OF_POLES; i++) print_rectangular (ZPlanePoles[i]); printf ("Hit any key to see pole-zero plot . . ."); getchar(); #endif hPZGraph = /* Initialize graph */ CreatePoleZeroGraph("Pole-Zero Plot", /* Graph title */ "Real", /* X-Axis label */ "Imaginary", /* Y-Axis label */ SV_COMPLEX_ZERO, /* PZ Data type */ "localhost"); /* Graph server */ if (hPZGraph == NULL) /* Graph creation failed - e.g is server running ? */ { printf ("\nGraph creation failure. Please check that the server is running\n"); exit (1); } DisplayPZPlot(hPZGraph, /* Graph object */ "Poles", /* Title of dataset (for use on legends) */ (Complex_s *)ZPlanePoles, /* Array of complex values */ NUMBER_OF_POLES, /* Items of data */ SV_BLUE, /* Colour */ SV_GRAPH_NEW, /* Add / new mode */ SV_CONJUGATE_POLE); /* Pole-zero mode */ DisplayPZPlot(hPZGraph, /* Graph object */ "Zeros", /* Title of dataset (for use on legends) */ (Complex_s *)ZPlaneZeros, /* Array of complex values */ NUMBER_OF_ZEROS, /* Items of data */ SV_RED, /* Colour */ SV_GRAPH_ADD, /* Add / new mode */ SV_CONJUGATE_ZERO); /* Pole-zero mode */ printf ("Pole-zero Plot\nHit any key to continue . . ."); getchar (); /* Convert poles and zeros to coefficients */ SDA_IirZplaneToCoeffs (ZPlaneZeros, /* Z-plane zeros */ ZPlanePoles, /* Z-plane zeros */ pIIRCoeffs, /* IIR filter coefficients */ NUMBER_OF_ZEROS, /* Number of zeros */ NUMBER_OF_POLES); /* Number of poles */ #if PRINT_RESULTS printf ("\nIIR filter coefficients\n"); /* Print filter coefficients */ printf ("\nb(0), b(1), b(2), a(1), a(2)\n"); for (i = 0; i < NUMBER_OF_ZEROS; i++) { printf ("%le, %le, %le, %le, %le\n", *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+1), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+2), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+3), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+4)); } printf ("Hit any key to see impulse and frequency response . . ."); getchar(); #endif /* Generate impulse response */ h2DGraph = /* Initialize graph */ Create2DGraph ("Bilinear Transform IIR Filter Design", /* Graph title */ "Time", /* 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); } SIF_Iir (pFilterState, /* Pointer to filter state array */ FILTER_STAGES); /* Number of second order stages */ /* 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 */ /* Generate test impulse */ SDA_SignalGenerate (pSrc, /* Pointer to destination array */ SIGLIB_IMPULSE, /* Signal type - Impulse function */ SIGLIB_ONE, /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ SIGLIB_ZERO, /* Signal frequency - Unused */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ IMPULSE_RESPONSE_LENGTH); /* Output array length */ /* Apply iir filter and store filtered data */ SDA_Iir (pSrc, /* Input array to be filtered */ pRealData, /* Filtered output array */ pFilterState, /* Pointer to filter state array */ pIIRCoeffs, /* Pointer to filter coefficients array */ FILTER_STAGES, /* Number of stages */ IMPULSE_RESPONSE_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Impulse Response", /* Title of the dataset */ pRealData, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nImpulse Response\nPlease hit to continue . . ."); getchar (); /* Generate frequency response */ SDA_Rfft (pRealData, /* Pointer to real array */ pImagData, /* 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 */ /* Calculate real power from complex */ SDA_LogMagnitude (pRealData, /* Pointer to real source array */ pImagData, /* Pointer to imaginary source array */ pResults, /* Pointer to log magnitude destination array */ PLOT_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Frequency Response", /* Title of the dataset */ pResults, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nFrequency Response\nPlease hit to continue . . ."); getchar (); #if TRANSFORM_L_L /* Low pass to low pass transformation */ /* Transform the filter response and re-display */ SDA_IirZplaneLpfToLpf (ZPlaneZeros, /* Source Z-plane zeros */ ZPlanePoles, /* Source Z-plane poles */ TransformedZPlaneZeros, /* Destination Z-plane zeros */ TransformedZPlanePoles, /* Destination Z-plane poles */ PREWARP_MATCH_FREQUENCY, /* Source cut-off frequency */ LPF_TO_LPF_NEW_FC, /* Destination cut-off frequency */ SAMPLE_RATE, /* System sample rate */ NUMBER_OF_ZEROS, /* Number of zeros in input and output */ NUMBER_OF_POLES); /* Number of poles in input and output */ #if PRINT_RESULTS printf ("\nTransformed complex z-plane zeros\n"); /* Print z-plane poles and zeros */ for (i = 0; i < NUMBER_OF_ZEROS; i++) print_rectangular (TransformedZPlaneZeros[i]); printf ("\nTransformed complex z-plane poles\n"); for (i = 0; i < NUMBER_OF_POLES; i++) print_rectangular (TransformedZPlanePoles[i]); printf ("Hit any key to see pole-zero plot . . ."); getchar(); #endif DisplayPZPlot(hPZGraph, /* Graph object */ "Poles", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlanePoles, /* Array of complex values */ NUMBER_OF_POLES, /* Items of data */ SV_BLUE, /* Colour */ SV_GRAPH_NEW, /* Add / new mode */ SV_CONJUGATE_POLE); /* Pole-zero mode */ DisplayPZPlot(hPZGraph, /* Graph object */ "Zeros", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlaneZeros, /* Array of complex values */ NUMBER_OF_ZEROS, /* Items of data */ SV_RED, /* Colour */ SV_GRAPH_ADD, /* Add / new mode */ SV_CONJUGATE_ZERO); /* Pole-zero mode */ printf ("\nPole-zero Plot\nHit any key to continue . . ."); getchar (); /* Convert poles and zeros to coefficients */ SDA_IirZplaneToCoeffs (TransformedZPlaneZeros, /* Z-plane zeros */ TransformedZPlanePoles, /* Z-plane zeros */ pIIRCoeffs, /* IIR filter coefficients */ NUMBER_OF_ZEROS, /* Number of zeros */ NUMBER_OF_POLES); /* Number of poles */ #if PRINT_RESULTS printf ("\nIIR filter coefficients\n"); /* Print filter coefficients */ printf ("\nb(0), b(1), b(2), a(1), a(2)\n"); for (i = 0; i < NUMBER_OF_ZEROS; i++) { printf ("%le, %le, %le, %le, %le\n", *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+1), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+2), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+3), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+4)); } printf ("\nHit any key to see transformed impulse and frequency response . . ."); getchar(); #endif /* Re-initialise filter state array */ SIF_Iir (pFilterState, /* Pointer to filter state array */ FILTER_STAGES); /* Number of second order stages */ /* Generate test impulse */ SDA_SignalGenerate (pSrc, /* Pointer to destination array */ SIGLIB_IMPULSE, /* Signal type - Impulse function */ SIGLIB_ONE, /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ SIGLIB_ZERO, /* Signal frequency - Unused */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ IMPULSE_RESPONSE_LENGTH); /* Output array length */ /* Apply iir filter and store filtered data */ SDA_Iir (pSrc, /* Input array to be filtered */ pRealData, /* Filtered output array */ pFilterState, /* Pointer to filter state array */ pIIRCoeffs, /* Pointer to filter coefficients array */ FILTER_STAGES, /* Number of stages */ IMPULSE_RESPONSE_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Transformed Impulse Response", /* Title of the dataset */ pRealData, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nTransformed Impulse Response\nPlease hit to continue . . ."); getchar (); /* Save the old frequency response */ SDA_Copy (pResults, /* Pointer to source array */ pSrc, /* Pointer to destination array */ FFT_SIZE); /* Array length */ /* Generate frequency response */ /* Perform real FFT */ SDA_Rfft (pRealData, /* Pointer to real array */ pImagData, /* 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 */ /* Calculate real power from complex */ SDA_LogMagnitude (pRealData, /* Pointer to real source array */ pImagData, /* Pointer to imaginary source array */ pResults, /* Pointer to log magnitude destination array */ PLOT_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Original Frequency Response", /* Title of the dataset */ pSrc, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ Display2DGraph (h2DGraph, /* Graph handle */ "Transformed Frequency Response", /* Title of the dataset */ pResults, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_RED, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_ADD); /* New graph */ printf ("\nTransformed impulse response\nPlease hit to continue . . ."); getchar (); #endif #if TRANSFORM_L_H /* Low pass to high pass transformation */ /* Transform the filter response and re-display */ SDA_IirZplaneLpfToHpf (ZPlaneZeros, /* Source Z-plane zeros */ ZPlanePoles, /* Source Z-plane poles */ TransformedZPlaneZeros, /* Destination Z-plane zeros */ TransformedZPlanePoles, /* Destination Z-plane poles */ PREWARP_MATCH_FREQUENCY, /* Source cut-off frequency */ LPF_TO_LPF_NEW_FC, /* Destination cut-off frequency */ SAMPLE_RATE, /* System sample rate */ NUMBER_OF_ZEROS, /* Number of zeros in input and output */ NUMBER_OF_POLES); /* Number of poles in input and output */ #if PRINT_RESULTS printf ("\nTransformed complex z-plane zeros\n"); /* Print z-plane poles and zeros */ for (i = 0; i < NUMBER_OF_ZEROS; i++) print_rectangular (TransformedZPlaneZeros[i]); printf ("\nTransformed complex z-plane poles\n"); for (i = 0; i < NUMBER_OF_POLES; i++) print_rectangular (TransformedZPlanePoles[i]); printf ("Hit any key to see pole-zero plot . . ."); getchar(); #endif DisplayPZPlot(hPZGraph, /* Graph object */ "Poles", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlanePoles, /* Array of complex values */ NUMBER_OF_POLES, /* Items of data */ SV_BLUE, /* Colour */ SV_GRAPH_NEW, /* Add / new mode */ SV_CONJUGATE_POLE); /* Pole-zero mode */ DisplayPZPlot(hPZGraph, /* Graph object */ "Zeros", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlaneZeros, /* Array of complex values */ NUMBER_OF_ZEROS, /* Items of data */ SV_RED, /* Colour */ SV_GRAPH_ADD, /* Add / new mode */ SV_CONJUGATE_ZERO); /* Pole-zero mode */ printf ("Pole-zero Plot\nHit any key to continue . . ."); getchar (); /* Convert poles and zeros to coefficients */ SDA_IirZplaneToCoeffs (TransformedZPlaneZeros, /* Z-plane zeros */ TransformedZPlanePoles, /* Z-plane zeros */ pIIRCoeffs, /* IIR filter coefficients */ NUMBER_OF_ZEROS, /* Number of zeros */ NUMBER_OF_POLES); /* Number of poles */ #if PRINT_RESULTS printf ("\nIIR filter coefficients\n"); /* Print filter coefficients */ printf ("\nb(0), b(1), b(2), a(1), a(2)\n"); for (i = 0; i < NUMBER_OF_ZEROS; i++) { printf ("%le, %le, %le, %le, %le\n", *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+1), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+2), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+3), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+4)); } printf ("Hit any key to see transformed impulse and frequency response . . ."); getchar(); #endif /* Re-initialise filter state array */ SIF_Iir (pFilterState, /* Pointer to filter state array */ FILTER_STAGES); /* Number of second order stages */ /* Generate test impulse */ SDA_SignalGenerate (pSrc, /* Pointer to destination array */ SIGLIB_IMPULSE, /* Signal type - Impulse function */ SIGLIB_ONE, /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ SIGLIB_ZERO, /* Signal frequency - Unused */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ IMPULSE_RESPONSE_LENGTH); /* Output array length */ /* Apply iir filter and store filtered data */ SDA_Iir (pSrc, /* Input array to be filtered */ pRealData, /* Filtered output array */ pFilterState, /* Pointer to filter state array */ pIIRCoeffs, /* Pointer to filter coefficients array */ FILTER_STAGES, /* Number of stages */ IMPULSE_RESPONSE_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Transformed Impulse Response", /* Title of the dataset */ pRealData, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nTransformed Impulse Response\nPlease hit to continue . . ."); getchar (); /* Generate frequency response */ /* Perform real FFT */ SDA_Rfft (pRealData, /* Pointer to real array */ pImagData, /* 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 */ /* Calculate real power from complex */ SDA_LogMagnitude (pRealData, /* Pointer to real source array */ pImagData, /* Pointer to imaginary source array */ pResults, /* Pointer to log magnitude destination array */ PLOT_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Original Frequency Response", /* Title of the dataset */ pResults, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nTransformed Impulse Response\nPlease hit to continue . . ."); getchar (); #endif #if TRANSFORM_L_P /* Low pass to band pass transformation */ /* Transform the filter response and re-display */ SDA_IirZplaneLpfToBpf (ZPlaneZeros, /* Source Z-plane zeros */ ZPlanePoles, /* Source Z-plane poles */ TransformedZPlaneZeros, /* Destination Z-plane zeros */ TransformedZPlanePoles, /* Destination Z-plane poles */ PREWARP_MATCH_FREQUENCY, /* Source cut-off frequency */ LPF_TO_BPF_NEW_FC1, /* Destination lower cut-off frequency */ LPF_TO_BPF_NEW_FC2, /* Destination upper cut-off frequency */ SAMPLE_RATE, /* System sample rate */ NUMBER_OF_ZEROS, /* Number of zeros in input and output */ NUMBER_OF_POLES); /* Number of poles in input and output */ #if PRINT_RESULTS printf ("\nTransformed complex z-plane zeros\n"); /* Print z-plane poles and zeros */ for (i = 0; i < 2*NUMBER_OF_ZEROS; i++) print_rectangular (TransformedZPlaneZeros[i]); printf ("\nTransformed complex z-plane poles\n"); for (i = 0; i < 2*NUMBER_OF_POLES; i++) print_rectangular (TransformedZPlanePoles[i]); printf ("Hit any key to see pole-zero plot . . ."); getchar(); #endif DisplayPZPlot(hPZGraph, /* Graph object */ "Poles", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlanePoles, /* Array of complex values */ NUMBER_OF_POLES, /* Items of data */ SV_BLUE, /* Colour */ SV_GRAPH_NEW, /* Add / new mode */ SV_CONJUGATE_POLE); /* Pole-zero mode */ DisplayPZPlot(hPZGraph, /* Graph object */ "Zeros", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlaneZeros, /* Array of complex values */ NUMBER_OF_ZEROS, /* Items of data */ SV_RED, /* Colour */ SV_GRAPH_ADD, /* Add / new mode */ SV_CONJUGATE_ZERO); /* Pole-zero mode */ printf ("Pole-zero Plot\nHit any key to continue . . ."); getchar (); /* Convert poles and zeros to coefficients */ SDA_IirZplaneToCoeffs (TransformedZPlaneZeros, /* Z-plane zeros */ TransformedZPlanePoles, /* Z-plane zeros */ pIIRCoeffs, /* IIR filter coefficients */ 2*NUMBER_OF_ZEROS, /* Number of zeros */ 2*NUMBER_OF_POLES); /* Number of poles */ #if PRINT_RESULTS printf ("\nIIR filter coefficients\n"); /* Print filter coefficients */ printf ("\nb(0), b(1), b(2), a(1), a(2)\n"); for (i = 0; i < 2*NUMBER_OF_ZEROS; i++) { printf ("%le, %le, %le, %le, %le\n", *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+1), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+2), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+3), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+4)); } printf ("\nHit any key to see transformed impulse and frequency response . . ."); getchar(); #endif /* Re-initialise filter state array */ SIF_Iir (pFilterState, /* Pointer to filter state array */ 2L*FILTER_STAGES); /* Number of second order stages */ /* Generate test impulse */ SDA_SignalGenerate (pSrc, /* Pointer to destination array */ SIGLIB_IMPULSE, /* Signal type - Impulse function */ SIGLIB_ONE, /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ SIGLIB_ZERO, /* Signal frequency - Unused */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ IMPULSE_RESPONSE_LENGTH); /* Output array length */ /* Apply iir filter and store filtered data */ SDA_Iir (pSrc, /* Input array to be filtered */ pRealData, /* Filtered output array */ pFilterState, /* Pointer to filter state array */ pIIRCoeffs, /* Pointer to filter coefficients array */ 2L*FILTER_STAGES, /* Number of stages */ IMPULSE_RESPONSE_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Transformed Impulse Response", /* Title of the dataset */ pRealData, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nTransformed Impulse Response\nPlease hit to continue . . ."); getchar (); /* Generate frequency response */ /* Perform real FFT */ SDA_Rfft (pRealData, /* Pointer to real array */ pImagData, /* 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 */ /* Calculate real power from complex */ SDA_LogMagnitude (pRealData, /* Pointer to real source array */ pImagData, /* Pointer to imaginary source array */ pResults, /* Pointer to log magnitude destination array */ PLOT_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Original Frequency Response", /* Title of the dataset */ pResults, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nTransformed Impulse Response\nPlease hit to continue . . ."); getchar (); #endif #if TRANSFORM_L_S /* Low pass to band stop transformation */ /* Transform the filter response and re-display */ SDA_IirZplaneLpfToBsf (ZPlaneZeros, /* Source Z-plane zeros */ ZPlanePoles, /* Source Z-plane poles */ TransformedZPlaneZeros, /* Destination Z-plane zeros */ TransformedZPlanePoles, /* Destination Z-plane poles */ PREWARP_MATCH_FREQUENCY, /* Source cut-off frequency */ LPF_TO_BPF_NEW_FC1, /* Destination lower cut-off frequency */ LPF_TO_BPF_NEW_FC2, /* Destination upper cut-off frequency */ SAMPLE_RATE, /* System sample rate */ NUMBER_OF_ZEROS, /* Number of zeros in input and output */ NUMBER_OF_POLES); /* Number of poles in input and output */ #if PRINT_RESULTS printf ("\nTransformed complex z-plane zeros\n"); /* Print z-plane poles and zeros */ for (i = 0; i < 2*NUMBER_OF_ZEROS; i++) print_rectangular (TransformedZPlaneZeros[i]); printf ("\nTransformed complex z-plane poles\n"); for (i = 0; i < 2*NUMBER_OF_POLES; i++) print_rectangular (TransformedZPlanePoles[i]); printf ("Hit any key to see pole-zero plot . . ."); getchar(); #endif DisplayPZPlot(hPZGraph, /* Graph object */ "Poles", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlanePoles, /* Array of complex values */ NUMBER_OF_POLES, /* Items of data */ SV_BLUE, /* Colour */ SV_GRAPH_NEW, /* Add / new mode */ SV_CONJUGATE_POLE); /* Pole-zero mode */ DisplayPZPlot(hPZGraph, /* Graph object */ "Zeros", /* Title of dataset (for use on legends) */ (Complex_s *)TransformedZPlaneZeros, /* Array of complex values */ NUMBER_OF_ZEROS, /* Items of data */ SV_RED, /* Colour */ SV_GRAPH_ADD, /* Add / new mode */ SV_CONJUGATE_ZERO); /* Pole-zero mode */ printf ("Pole-zero Plot\nHit any key to continue . . ."); getchar (); /* Convert poles and zeros to coefficients */ SDA_IirZplaneToCoeffs (TransformedZPlaneZeros, /* Z-plane zeros */ TransformedZPlanePoles, /* Z-plane zeros */ pIIRCoeffs, /* IIR filter coefficients */ 2*NUMBER_OF_ZEROS, /* Number of zeros */ 2*NUMBER_OF_POLES); /* Number of poles */ #if PRINT_RESULTS printf ("\nIIR filter coefficients\n"); /* Print filter coefficients */ printf ("\nb(0), b(1), b(2), a(1), a(2)\n"); for (i = 0; i < 2*NUMBER_OF_ZEROS; i++) { printf ("%le, %le, %le, %le, %le\n", *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+1), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+2), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+3), *(pIIRCoeffs+(i*IIR_COEFFS_PER_BIQUAD)+4)); } printf ("\nHit any key to see transformed impulse and frequency response . . ."); getchar(); #endif /* Re-initialise filter state array */ SIF_Iir (pFilterState, /* Pointer to filter state array */ 2L*FILTER_STAGES); /* Number of second order stages */ /* Generate test impulse */ SDA_SignalGenerate (pSrc, /* Pointer to destination array */ SIGLIB_IMPULSE, /* Signal type - Impulse function */ SIGLIB_ONE, /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ SIGLIB_ZERO, /* Signal frequency - Unused */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ SIGLIB_NULL_DATA_PTR, /* Unused */ IMPULSE_RESPONSE_LENGTH); /* Output array length */ /* Apply iir filter and store filtered data */ SDA_Iir (pSrc, /* Input array to be filtered */ pRealData, /* Filtered output array */ pFilterState, /* Pointer to filter state array */ pIIRCoeffs, /* Pointer to filter coefficients array */ 2L*FILTER_STAGES, /* Number of stages */ IMPULSE_RESPONSE_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Transformed Impulse Response", /* Title of the dataset */ pRealData, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nTransformed Impulse Response\nPlease hit to continue . . ."); getchar (); /* Generate frequency response */ /* Perform real FFT */ SDA_Rfft (pRealData, /* Pointer to real array */ pImagData, /* 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 */ /* Calculate real power from complex */ SDA_LogMagnitude (pRealData, /* Pointer to real source array */ pImagData, /* Pointer to imaginary source array */ pResults, /* Pointer to log magnitude destination array */ PLOT_LENGTH); /* Array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Transformed Frequency Response", /* Title of the dataset */ pResults, /* Array of Double dataset */ PLOT_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ printf ("\nTransformed Impulse Response\n"); #endif SUF_MemoryFree (pSrc); /* Free memory */ SUF_MemoryFree (pIIRCoeffs); SUF_MemoryFree (pFilterState); SUF_MemoryFree (pRealData); SUF_MemoryFree (pImagData); SUF_MemoryFree (pResults); SUF_MemoryFree (pFFTCoeffs); }