1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
//
// iirfilt_cccf_example.c
//
// Complex infinite impulse response filter example. Demonstrates the
// functionality of iirfilt with complex coefficients by designing a
// filter with specified parameters and then filters noise.
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <complex.h>
#include <getopt.h>
#include "liquid.h"
#define OUTPUT_FILENAME "iirfilt_cccf_example.m"
// print usage/help message
void usage()
{
printf("iirfilt_cccf_example -- infinite impulse response filter example\n");
printf("options (default values in []):\n");
printf(" h : print help\n");
printf(" t : filter type: [butter], cheby1, cheby2, ellip, bessel\n");
printf(" b : filter transformation: [LP], HP, BP, BS\n");
printf(" n : filter order, n > 0 [5]\n");
printf(" r : passband ripple in dB (cheby1, ellip), r > 0 [1.0]\n");
printf(" s : stopband attenuation in dB (cheby2, ellip), s > 0 [40.0]\n");
printf(" f : passband cut-off, 0 < f < 0.5 [0.2]\n");
printf(" c : center frequency (BP, BS cases), 0 < c < 0.5 [0.25]\n");
printf(" o : format [sos], tf\n");
printf(" sos : second-order sections form\n");
printf(" tf : regular transfer function form (potentially\n");
printf(" unstable for large orders\n");
}
int main(int argc, char*argv[])
{
// options
unsigned int order=4; // filter order
float fc=0.1f; // cutoff frequency
float f0=0.0f; // center frequency
float Ap=1.0f; // pass-band ripple
float As=40.0f; // stop-band attenuation
unsigned int n=128; // number of samples
liquid_iirdes_filtertype ftype = LIQUID_IIRDES_ELLIP;
liquid_iirdes_bandtype btype = LIQUID_IIRDES_LOWPASS;
liquid_iirdes_format format = LIQUID_IIRDES_SOS;
int dopt;
while ((dopt = getopt(argc,argv,"ht:b:n:r:s:f:c:o:")) != EOF) {
switch (dopt) {
case 'h': usage(); return 0;
case 't':
if (strcmp(optarg,"butter")==0) ftype = LIQUID_IIRDES_BUTTER;
else if (strcmp(optarg,"cheby1")==0) ftype = LIQUID_IIRDES_CHEBY1;
else if (strcmp(optarg,"cheby2")==0) ftype = LIQUID_IIRDES_CHEBY2;
else if (strcmp(optarg,"ellip") ==0) ftype = LIQUID_IIRDES_ELLIP;
else if (strcmp(optarg,"bessel")==0) ftype = LIQUID_IIRDES_BESSEL;
else {
fprintf(stderr,"error: iirdes_example, unknown filter type '%s'\n", optarg);
exit(1);
}
break;
case 'b':
if (strcmp(optarg,"LP")==0) btype = LIQUID_IIRDES_LOWPASS;
else if (strcmp(optarg,"HP")==0) btype = LIQUID_IIRDES_HIGHPASS;
else if (strcmp(optarg,"BP")==0) btype = LIQUID_IIRDES_BANDPASS;
else if (strcmp(optarg,"BS")==0) btype = LIQUID_IIRDES_BANDSTOP;
else {
fprintf(stderr,"error: iirdes_example, unknown band type '%s'\n", optarg);
exit(1);
}
break;
case 'n': order = atoi(optarg); break;
case 'r': Ap = atof(optarg); break;
case 's': As = atof(optarg); break;
case 'f': fc = atof(optarg); break;
case 'c': f0 = atof(optarg); break;
case 'o':
if (strcmp(optarg,"sos")==0) format = LIQUID_IIRDES_SOS;
else if (strcmp(optarg,"tf") ==0) format = LIQUID_IIRDES_TF;
else {
fprintf(stderr,"error: iirdes_example, unknown output format '%s'\n", optarg);
exit(1);
}
break;
default:
exit(1);
}
}
// design filter from prototype
iirfilt_cccf q = iirfilt_cccf_create_prototype(ftype, btype, format, order, fc, f0, Ap, As);
iirfilt_cccf_print(q);
unsigned int i;
// allocate memory for data arrays
float complex x[n];
float complex y[n];
// generate input signal (noisy sine wave with decaying amplitude)
unsigned int wlen = (3*n)/4;
for (i=0; i<n; i++) {
// input signal (windowed noise)
x[i] = randnf() + _Complex_I*randnf();
x[i] *= i < wlen ? liquid_hamming(i,wlen) : 0.0f;
// run filter
iirfilt_cccf_execute(q, x[i], &y[i]);
}
// compute two-sided frequency response
unsigned int nfft=512;
float complex H[nfft];
for (i=0; i<nfft; i++) {
float freq = (float)i / (float)nfft - 0.5f;
iirfilt_cccf_freqresponse(q, freq, &H[i]);
}
// destroy filter object
iirfilt_cccf_destroy(q);
//
// plot results to output file
//
FILE * fid = fopen(OUTPUT_FILENAME,"w");
fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
fprintf(fid,"clear all;\n");
fprintf(fid,"close all;\n");
fprintf(fid,"\n");
fprintf(fid,"order=%u;\n", order);
// save input, output arrays
fprintf(fid,"n=%u;\n",n);
fprintf(fid,"x=zeros(1,n);\n");
fprintf(fid,"y=zeros(1,n);\n");
for (i=0; i<n; i++) {
fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));
fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));
}
// save frequency response
fprintf(fid,"nfft=%u;\n",nfft);
fprintf(fid,"H=zeros(1,nfft);\n");
for (i=0; i<nfft; i++)
fprintf(fid,"H(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(H[i]), cimagf(H[i]));
// plot time-domain output
fprintf(fid,"t=0:(n-1);\n");
fprintf(fid,"figure;\n");
fprintf(fid,"subplot(2,1,1);\n");
fprintf(fid," plot(t,real(x),'-','Color',[1 1 1]*0.5,'LineWidth',1,...\n");
fprintf(fid," t,real(y),'-','Color',[0 0.5 0.25],'LineWidth',2);\n");
fprintf(fid," xlabel('time');\n");
fprintf(fid," ylabel('real');\n");
fprintf(fid," legend('input','filtered output',1);\n");
fprintf(fid," grid on;\n");
fprintf(fid,"subplot(2,1,2);\n");
fprintf(fid," plot(t,imag(x),'-','Color',[1 1 1]*0.5,'LineWidth',1,...\n");
fprintf(fid," t,imag(y),'-','Color',[0 0.25 0.5],'LineWidth',2);\n");
fprintf(fid," xlabel('time');\n");
fprintf(fid," ylabel('imag');\n");
fprintf(fid," legend('input','filtered output',1);\n");
fprintf(fid," grid on;\n");
// plot spectral output
fprintf(fid,"X = 20*log10(abs(fftshift(fft(x))));\n");
fprintf(fid,"Y = 20*log10(abs(fftshift(fft(y))));\n");
fprintf(fid,"figure;\n");
fprintf(fid,"plot([0:(n-1)]/n-0.5, X, 'Color', [1 1 1]*0.5,\n");
fprintf(fid," [0:(n-1)]/n-0.5, Y, 'Color', [0 0.25 0.50]);\n");
fprintf(fid,"xlabel('Normalized Frequency');\n");
fprintf(fid,"ylabel('PSD [dB]');\n");
fprintf(fid,"legend('input','filtered output',1);\n");
fprintf(fid,"grid on;\n");
// plot ideal frequency response
fprintf(fid,"f=[0:(nfft-1)]/nfft - 0.5;\n");
fprintf(fid,"figure;\n");
fprintf(fid,"subplot(3,1,1);\n");
fprintf(fid," plot(f,20*log10(abs(H)));\n");
fprintf(fid," axis([-0.5 0.5 -3 0]);\n");
fprintf(fid," grid on;\n");
fprintf(fid," legend('Pass band (dB)',0);\n");
fprintf(fid,"subplot(3,1,2);\n");
fprintf(fid," plot(f,20*log10(abs(H)));\n");
fprintf(fid," axis([-0.5 0.5 -100 0]);\n");
fprintf(fid," grid on;\n");
fprintf(fid," legend('Stop band (dB)',0);\n");
fprintf(fid,"subplot(3,1,3);\n");
fprintf(fid," plot(f,180/pi*arg(H));\n");
fprintf(fid," axis([-0.5 0.5 -180 180]);\n");
fprintf(fid," grid on;\n");
fprintf(fid," legend('Phase (degrees)',0);\n");
fclose(fid);
printf("results written to %s.\n", OUTPUT_FILENAME);
printf("done.\n");
return 0;
}
|