2 This file is part of a program that implements a Software-Defined Radio.
4 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 The authors can be reached by email at
28 The DTTS Microwave Society
35 static REAL onepi = 3.141592653589793;
40 newFIR_REAL(int size, char *tag) {
41 RealFIR p = (RealFIRDesc *) safealloc(1, sizeof(RealFIRDesc), tag);
42 FIRcoef(p) = (REAL *) safealloc(size, sizeof(REAL), tag);
44 FIRtype(p) = FIR_Undef;
45 FIRiscomplex(p) = FALSE;
46 FIRfqlo(p) = FIRfqhi(p) = -1.0;
51 newFIR_COMPLEX(int size, char *tag) {
52 ComplexFIR p = (ComplexFIRDesc *) safealloc(1, sizeof(ComplexFIRDesc), tag);
53 FIRcoef(p) = (COMPLEX *) safealloc(size, sizeof(COMPLEX), tag);
55 FIRtype(p) = FIR_Undef;
56 FIRiscomplex(p) = TRUE;
57 FIRfqlo(p) = FIRfqhi(p) = -1.0;
62 delFIR_REAL(RealFIR p) {
64 delvec_REAL(FIRcoef(p));
70 delFIR_COMPLEX(ComplexFIR p) {
72 delvec_COMPLEX(FIRcoef(p));
78 newFIR_Lowpass_REAL(REAL cutoff, REAL sr, int size) {
79 if ((cutoff < 0.0) || (cutoff > (sr / 2.0))) return 0;
80 else if (size < 1) return 0;
83 REAL *h, *w, fc = cutoff / sr;
86 if (!(size & 01)) size++;
87 midpoint = (size >> 01) | 01;
88 p = newFIR_REAL(size, "newFIR_Lowpass_REAL");
90 w = newvec_REAL(size, "newFIR_Lowpass_REAL window");
91 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
93 for (i = 1; i <= size; i++) {
96 h[j] = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
98 h[midpoint - 1] = 2.0 * fc;
102 FIRtype(p) = FIR_Lowpass;
108 newFIR_Lowpass_COMPLEX(REAL cutoff, REAL sr, int size) {
109 if ((cutoff < 0.0) || (cutoff > (sr / 2.0))) return 0;
110 else if (size < 1) return 0;
114 REAL *w, fc = cutoff / sr;
117 if (!(size & 01)) size++;
118 midpoint = (size >> 01) | 01;
119 p = newFIR_COMPLEX(size, "newFIR_Lowpass_COMPLEX");
121 w = newvec_REAL(size, "newFIR_Lowpass_REAL window");
122 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
124 for (i = 1; i <= size; i++) {
127 h[j].re = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
129 h[midpoint - 1].re = 2.0 * fc;
133 FIRtype(p) = FIR_Lowpass;
139 newFIR_Bandpass_REAL(REAL lo, REAL hi, REAL sr, int size) {
140 if ((lo < 0.0) || (hi > (sr / 2.0)) || (hi <= lo)) return 0;
141 else if (size < 1) return 0;
147 if (!(size & 01)) size++;
148 midpoint = (size >> 01) | 01;
149 p = newFIR_REAL(size, "newFIR_Bandpass_REAL");
151 w = newvec_REAL(size, "newFIR_Bandpass_REAL window");
152 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
155 fc = (hi - lo) / 2.0;
156 ff = (lo + hi) * onepi;
158 for (i = 1; i <= size; i++) {
161 h[j] = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
163 h[midpoint - 1] = 2.0 * fc;
164 h[j] *= 2.0 * cos(ff * (i - midpoint));
168 FIRtype(p) = FIR_Bandpass;
174 newFIR_Bandpass_COMPLEX(REAL lo, REAL hi, REAL sr, int size) {
175 if ((lo < -(sr/2.0)) || (hi > (sr / 2.0)) || (hi <= lo)) return 0;
176 else if (size < 1) return 0;
183 if (!(size & 01)) size++;
184 midpoint = (size >> 01) | 01;
185 p = newFIR_COMPLEX(size, "newFIR_Bandpass_COMPLEX");
187 w = newvec_REAL(size, "newFIR_Bandpass_COMPLEX window");
188 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
191 fc = (hi - lo) / 2.0;
192 ff = (lo + hi) * onepi;
194 for (i = 1; i <= size; i++) {
195 int j = i - 1, k = i - midpoint;
196 REAL tmp, phs = ff * k;
198 tmp = (sin(twopi * k * fc) / (onepi * k)) * w[j];
202 h[j].re = tmp * cos(phs);
203 h[j].im = tmp * sin(phs);
207 FIRtype(p) = FIR_Bandpass;
213 newFIR_Highpass_REAL(REAL cutoff, REAL sr, int size) {
214 if ((cutoff < 0.0) || (cutoff > (sr / 2.0))) return 0;
215 else if (size < 1) return 0;
218 REAL *h, *w, fc = cutoff / sr;
221 if (!(size & 01)) size++;
222 midpoint = (size >> 01) | 01;
223 p = newFIR_REAL(size, "newFIR_Highpass_REAL");
225 w = newvec_REAL(size, "newFIR_Highpass_REAL window");
226 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
228 for (i = 1; i <= size; i++) {
231 h[j] = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
233 h[midpoint - 1] = 2.0 * fc;
236 for (i = 1; i <= size; i++) {
238 if (i != midpoint) h[j] = -h[j];
239 else h[midpoint - 1] = 1.0 - h[midpoint - 1];
243 FIRtype(p) = FIR_Highpass;
249 newFIR_Highpass_COMPLEX(REAL cutoff, REAL sr, int size) {
250 if ((cutoff < 0.0) || (cutoff > (sr / 2.0))) return 0;
251 else if (size < 1) return 0;
255 REAL *w, fc = cutoff / sr;
258 if (!(size & 01)) size++;
259 midpoint = (size >> 01) | 01;
260 p = newFIR_COMPLEX(size, "newFIR_Highpass_REAL");
262 w = newvec_REAL(size, "newFIR_Highpass_REAL window");
263 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
265 for (i = 1; i <= size; i++) {
268 h[j].re = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
270 h[midpoint - 1].re = 2.0 * fc;
273 for (i = 1; i <= size; i++) {
275 if (i != midpoint) h[j].re = -h[j].re;
276 else h[midpoint - 1].re = 1.0 - h[midpoint - 1].re;
280 FIRtype(p) = FIR_Highpass;
286 newFIR_Hilbert_REAL(REAL lo, REAL hi, REAL sr, int size) {
287 if ((lo < 0.0) || (hi > (sr / 2.0)) || (hi <= lo)) return 0;
288 else if (size < 1) return 0;
294 if (!(size & 01)) size++;
295 midpoint = (size >> 01) | 01;
296 p = newFIR_REAL(size, "newFIR_Hilbert_REAL");
298 w = newvec_REAL(size, "newFIR_Hilbert_REAL window");
299 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
302 fc = (hi - lo) / 2.0;
303 ff = (lo + hi) * onepi;
305 for (i = 1; i <= size; i++) {
308 h[j] = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
310 h[midpoint - 1] = 2.0 * fc;
311 h[j] *= 2.0 * sin(ff * (i - midpoint));
315 FIRtype(p) = FIR_Hilbert;
321 newFIR_Hilbert_COMPLEX(REAL lo, REAL hi, REAL sr, int size) {
322 if ((lo < 0.0) || (hi > (sr / 2.0)) || (hi <= lo)) return 0;
323 else if (size < 1) return 0;
330 if (!(size & 01)) size++;
331 midpoint = (size >> 01) | 01;
332 p = newFIR_COMPLEX(size, "newFIR_Hilbert_COMPLEX");
334 w = newvec_REAL(size, "newFIR_Hilbert_COMPLEX window");
335 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
338 fc = (hi - lo) / 2.0;
339 ff = (lo + hi) * onepi;
341 for (i = 1; i <= size; i++) {
343 REAL tmp, phs = ff * (i - midpoint);
345 tmp = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
349 /* h[j].re *= tmp * cos(phs); */
350 h[j].im *= tmp * sin(phs);
354 FIRtype(p) = FIR_Hilbert;
360 newFIR_Bandstop_REAL(REAL lo, REAL hi, REAL sr, int size) {
361 if ((lo < 0.0) || (hi > (sr / 2.0)) || (hi <= lo)) return 0;
362 else if (size < 1) return 0;
368 if (!(size & 01)) size++;
369 midpoint = (size >> 01) | 01;
370 p = newFIR_REAL(size, "newFIR_Bandstop_REAL");
372 w = newvec_REAL(size, "newFIR_Bandstop_REAL window");
373 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
376 fc = (hi - lo) / 2.0;
377 ff = (lo + hi) * onepi;
379 for (i = 1; i <= size; i++) {
382 h[j] = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
384 h[midpoint - 1] = 2.0 * fc;
385 h[j] *= 2.0 * cos(ff * (i - midpoint));
388 for (i = 1; i <= size; i++) {
390 if (i != midpoint) h[j] = -h[j];
391 else h[midpoint - 1] = 1.0 - h[midpoint - 1];
395 FIRtype(p) = FIR_Bandstop;
401 newFIR_Bandstop_COMPLEX(REAL lo, REAL hi, REAL sr, int size) {
402 if ((lo < 0.0) || (hi > (sr / 2.0)) || (hi <= lo)) return 0;
403 else if (size < 1) return 0;
410 if (!(size & 01)) size++;
411 midpoint = (size >> 01) | 01;
412 p = newFIR_COMPLEX(size, "newFIR_Bandstop_REAL");
414 w = newvec_REAL(size, "newFIR_Bandstop_REAL window");
415 (void) makewindow(BLACKMANHARRIS_WINDOW, size, w);
418 fc = (hi - lo) / 2.0;
419 ff = (lo + hi) * onepi;
421 for (i = 1; i <= size; i++) {
423 REAL tmp, phs = ff * (i - midpoint);
425 tmp = (sin(twopi * (i - midpoint) * fc) / (onepi * (i - midpoint))) * w[j];
429 h[j].re *= tmp * cos(phs);
430 h[j].im *= tmp * sin(phs);
433 for (i = 1; i <= size; i++) {
435 if (i != midpoint) h[j] = Cmul(h[j], cxminusone);
436 else h[midpoint - 1] = Csub(cxone, h[midpoint - 1]);
440 FIRtype(p) = FIR_Bandstop;
447 main(int argc, char **argv) {
451 filt = newFIR_Lowpass_REAL(1000.0, 48000.0, size);
452 for (i = 0; i < FIRsize(filt); i++)
453 printf("%d %f\n", i, FIRtap(filt, i));
458 filt = newFIR_Bandstop_REAL(1000.0, 2000.0, 48000.0, size);
459 for (i = 0; i < FIRsize(filt); i++)
460 printf("%d %f\n", i, FIRtap(filt, i));
464 filt = newFIR_Bandpass_REAL(1000.0, 2000.0, 48000.0, size);
465 for (i = 0; i < FIRsize(filt); i++)
466 printf("%d %f\n", i, FIRtap(filt, i));
470 filt = newFIR_Highpass_REAL(1000.0, 48000.0, size);
471 for (i = 0; i < FIRsize(filt); i++)
472 printf("%d %f\n", i, FIRtap(filt, i));
477 filt = newFIR_Hilbert_REAL(1000.0, 2000.0, 48000.0, size);
478 for (i = 0; i < FIRsize(filt); i++)
479 printf("%d %f\n", i, FIRtap(filt, i));
488 fftlen = nblock2(size) * 2;
489 z = newvec_COMPLEX(fftlen, "z");
490 ttbl = newvec_REAL(fftlen, "ttbl");
491 cfftm(FFT_INIT, fftlen, (float *) z, (float *) z, ttbl);
492 for (i = 0; i < FIRsize(filt); i++)
493 z[i].re = FIRtap(filt, i);
494 cfftm(FFT_FORWARD, fftlen, (float *) z, (float *) z, ttbl);
495 for (i = 0; i < size; i++) {
496 printf("%d %f\n", i, Cabs(z[i]));