3 This file is part of a program that implements a Software-Defined Radio.
5 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 The authors can be reached by email at
29 The DTTS Microwave Society
36 /*------------------------------------------------------------*/
40 filter_OvSv(FiltOvSv pflt) {
45 COMPLEX *zfvec = pflt->zfvec,
49 REAL scl = pflt->scale;
52 fftw_one(pflt->pfwd, (fftw_complex *) zrvec, (fftw_complex *) zivec);
55 for (i = 0; i < m; i++) zivec[i] = Cmul(zivec[i], zfvec[i]);
57 /* z convolved sig -> time output sig */
58 fftw_one(pflt->pinv, (fftw_complex *) zivec, (fftw_complex *) zovec);
61 for (i = 0; i < n; i++) zovec[i].re *= scl, zovec[i].im *= scl;
63 /* prepare input sig vec for next fill */
64 for (i = 0, j = n; i < n; i++, j++) zrvec[i] = zrvec[j];
68 filter_OvSv_par(FiltOvSv pflt) {
73 COMPLEX *zfvec = pflt->zfvec,
77 REAL scl = pflt->scale;
80 fftw_one(pflt->pfwd,(fftw_complex *) zrvec, (fftw_complex *) zivec);
83 for (i = 0; i < m; i++) zivec[i] = Cmul(zivec[i], zfvec[i]);
85 /* z convolved sig -> time output sig */
86 fftw_one(pflt->pinv, (fftw_complex *) zivec, (fftw_complex *) zovec);
89 for (i = 0; i < n; i++) zovec[i].re *= scl, zovec[i].im *= scl;
91 /* prepare input sig vec for next fill */
92 for (i = 0, j = n; i < n; i++, j++) zrvec[i] = zrvec[j];
95 /*------------------------------------------------------------*/
97 /* NB strategy. This is the address we pass to newCXB as
98 the place to read samples into. It's the right half of
99 the true buffer. Old samples get slid from here to
100 left half after each go-around. */
102 FiltOvSv_initpoint(FiltOvSv pflt) { return &(pflt->zrvec[pflt->buflen]); }
104 /* how many to put there */
106 FiltOvSv_initsize(FiltOvSv pflt) { return (pflt->fftlen - pflt->buflen); }
108 /* where to put next batch of samples to filter */
110 FiltOvSv_fetchpoint(FiltOvSv pflt) { return &(pflt->zrvec[pflt->buflen]); }
112 /* how many samples to put there */
115 FiltOvSv_fetchsize(FiltOvSv pflt) { return (pflt->fftlen - pflt->buflen); }
117 /* where samples should be taken from after filtering */
120 FiltOvSv_storepoint(FiltOvSv plft) { return ((pflt->zovec) + buflen); }
123 FiltOvSv_storepoint(FiltOvSv pflt) { return ((pflt->zovec)); }
126 /* alternating parity fetch/store */
129 FiltOvSv_fetchpt_par(FiltOvSv pflt, int parity) {
131 return pflt->zovec + pflt->buflen;
137 FiltOvSv_storept_par(FiltOvSv pflt, int parity) {
141 return pflt->zovec + pflt->buflen;
144 /* how many samples to take */
145 /* NB strategy. This is the number of good samples in the
146 left half of the true buffer. Samples in right half
147 are circular artifacts and are ignored. */
149 FiltOvSv_storesize(FiltOvSv pflt) { return (pflt->fftlen - pflt->buflen); }
151 /*------------------------------------------------------------*/
152 /* create a new overlap/save filter from complex coefficients */
155 newFiltOvSv(COMPLEX *coefs, int ncoef, int pbits) {
159 COMPLEX *zrvec, *zfvec, *zivec, *zovec;
160 p = (FiltOvSv) safealloc(1, sizeof(filt_ov_sv), "new overlap/save filter");
161 buflen = nblock2(ncoef-1), fftlen = 2 * buflen;
162 zrvec = newvec_COMPLEX(fftlen, "raw signal vec in newFiltOvSv");
163 zfvec = newvec_COMPLEX(fftlen, "filter z vec in newFiltOvSv");
164 zivec = newvec_COMPLEX(fftlen, "signal in z vec in newFiltOvSv");
165 zovec = newvec_COMPLEX(fftlen, "signal out z vec in newFiltOvSv");
167 /* prepare frequency response from filter coefs */
173 zcvec = newvec_COMPLEX(fftlen, "temp filter z vec in newFiltOvSv");
174 ptmp = fftw_create_plan(fftlen, FFTW_FORWARD, pbits);
177 for (i = 0; i < ncoef; i++) zcvec[i] = coefs[i];
179 for (i = 0; i < ncoef; i++) zcvec[fftlen - ncoef - 1 + i] = coefs[i];
182 fftw_one(ptmp, (fftw_complex *) zcvec, (fftw_complex *) zfvec);
183 fftw_destroy_plan(ptmp);
184 delvec_COMPLEX(zcvec);
187 /* prepare transforms for signal */
188 pfwd = fftw_create_plan(fftlen, FFTW_FORWARD, pbits);
189 pinv = fftw_create_plan(fftlen, FFTW_BACKWARD, pbits);
199 p->scale = 1.0 / fftlen;
204 /* deep-six the filter */
206 delFiltOvSv(FiltOvSv p) {
208 delvec_COMPLEX(p->zfvec);
209 delvec_COMPLEX(p->zivec);
210 delvec_COMPLEX(p->zovec);
211 delvec_COMPLEX(p->zrvec);
212 fftw_destroy_plan(p->pfwd);
213 fftw_destroy_plan(p->pinv);
214 safefree((char *) p);
218 /*------------------------------------------------------------*/