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];
96 reset_OvSv(FiltOvSv pflt) {
97 memset((char *) pflt->zrvec, 0, pflt->fftlen * sizeof(COMPLEX));
100 /*------------------------------------------------------------*/
102 /* NB strategy. This is the address we pass to newCXB as
103 the place to read samples into. It's the right half of
104 the true buffer. Old samples get slid from here to
105 left half after each go-around. */
107 FiltOvSv_initpoint(FiltOvSv pflt) { return &(pflt->zrvec[pflt->buflen]); }
109 /* how many to put there */
111 FiltOvSv_initsize(FiltOvSv pflt) { return (pflt->fftlen - pflt->buflen); }
113 /* where to put next batch of samples to filter */
115 FiltOvSv_fetchpoint(FiltOvSv pflt) { return &(pflt->zrvec[pflt->buflen]); }
117 /* how many samples to put there */
120 FiltOvSv_fetchsize(FiltOvSv pflt) { return (pflt->fftlen - pflt->buflen); }
122 /* where samples should be taken from after filtering */
125 FiltOvSv_storepoint(FiltOvSv plft) { return ((pflt->zovec) + buflen); }
128 FiltOvSv_storepoint(FiltOvSv pflt) { return ((pflt->zovec)); }
131 /* alternating parity fetch/store */
134 FiltOvSv_fetchpt_par(FiltOvSv pflt, int parity) {
136 return pflt->zovec + pflt->buflen;
142 FiltOvSv_storept_par(FiltOvSv pflt, int parity) {
146 return pflt->zovec + pflt->buflen;
149 /* how many samples to take */
150 /* NB strategy. This is the number of good samples in the
151 left half of the true buffer. Samples in right half
152 are circular artifacts and are ignored. */
154 FiltOvSv_storesize(FiltOvSv pflt) { return (pflt->fftlen - pflt->buflen); }
156 /*------------------------------------------------------------*/
157 /* create a new overlap/save filter from complex coefficients */
160 newFiltOvSv(COMPLEX *coefs, int ncoef, int pbits) {
164 COMPLEX *zrvec, *zfvec, *zivec, *zovec;
165 p = (FiltOvSv) safealloc(1, sizeof(filt_ov_sv), "new overlap/save filter");
166 buflen = nblock2(ncoef-1), fftlen = 2 * buflen;
167 zrvec = newvec_COMPLEX(fftlen, "raw signal vec in newFiltOvSv");
168 zfvec = newvec_COMPLEX(fftlen, "filter z vec in newFiltOvSv");
169 zivec = newvec_COMPLEX(fftlen, "signal in z vec in newFiltOvSv");
170 zovec = newvec_COMPLEX(fftlen, "signal out z vec in newFiltOvSv");
172 /* prepare frequency response from filter coefs */
178 zcvec = newvec_COMPLEX(fftlen, "temp filter z vec in newFiltOvSv");
179 ptmp = fftw_create_plan(fftlen, FFTW_FORWARD, pbits);
182 for (i = 0; i < ncoef; i++) zcvec[i] = coefs[i];
184 for (i = 0; i < ncoef; i++) zcvec[fftlen - ncoef - 1 + i] = coefs[i];
187 fftw_one(ptmp, (fftw_complex *) zcvec, (fftw_complex *) zfvec);
188 fftw_destroy_plan(ptmp);
189 delvec_COMPLEX(zcvec);
192 /* prepare transforms for signal */
193 pfwd = fftw_create_plan(fftlen, FFTW_FORWARD, pbits);
194 pinv = fftw_create_plan(fftlen, FFTW_BACKWARD, pbits);
204 p->scale = 1.0 / fftlen;
209 /* deep-six the filter */
211 delFiltOvSv(FiltOvSv p) {
213 delvec_COMPLEX(p->zfvec);
214 delvec_COMPLEX(p->zivec);
215 delvec_COMPLEX(p->zovec);
216 delvec_COMPLEX(p->zrvec);
217 fftw_destroy_plan(p->pfwd);
218 fftw_destroy_plan(p->pinv);
219 safefree((char *) p);
223 /*------------------------------------------------------------*/