Chris@184
|
1 /*
|
Chris@184
|
2 Copyright (c) 2003-2004, Mark Borgerding
|
Chris@184
|
3
|
Chris@184
|
4 All rights reserved.
|
Chris@184
|
5
|
Chris@184
|
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Chris@184
|
7
|
Chris@184
|
8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
Chris@184
|
9 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
Chris@184
|
10 * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
Chris@184
|
11
|
Chris@184
|
12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
Chris@184
|
13 */
|
Chris@184
|
14
|
Chris@184
|
15 #include "_kiss_fft_guts.h"
|
Chris@184
|
16
|
Chris@184
|
17
|
Chris@184
|
18 /*
|
Chris@184
|
19 Some definitions that allow real or complex filtering
|
Chris@184
|
20 */
|
Chris@184
|
21 #ifdef REAL_FASTFIR
|
Chris@184
|
22 #define MIN_FFT_LEN 2048
|
Chris@184
|
23 #include "kiss_fftr.h"
|
Chris@184
|
24 typedef kiss_fft_scalar kffsamp_t;
|
Chris@184
|
25 typedef kiss_fftr_cfg kfcfg_t;
|
Chris@184
|
26 #define FFT_ALLOC kiss_fftr_alloc
|
Chris@184
|
27 #define FFTFWD kiss_fftr
|
Chris@184
|
28 #define FFTINV kiss_fftri
|
Chris@184
|
29 #else
|
Chris@184
|
30 #define MIN_FFT_LEN 1024
|
Chris@184
|
31 typedef kiss_fft_cpx kffsamp_t;
|
Chris@184
|
32 typedef kiss_fft_cfg kfcfg_t;
|
Chris@184
|
33 #define FFT_ALLOC kiss_fft_alloc
|
Chris@184
|
34 #define FFTFWD kiss_fft
|
Chris@184
|
35 #define FFTINV kiss_fft
|
Chris@184
|
36 #endif
|
Chris@184
|
37
|
Chris@184
|
38 typedef struct kiss_fastfir_state *kiss_fastfir_cfg;
|
Chris@184
|
39
|
Chris@184
|
40
|
Chris@184
|
41
|
Chris@184
|
42 kiss_fastfir_cfg kiss_fastfir_alloc(const kffsamp_t * imp_resp,size_t n_imp_resp,
|
Chris@184
|
43 size_t * nfft,void * mem,size_t*lenmem);
|
Chris@184
|
44
|
Chris@184
|
45 /* see do_file_filter for usage */
|
Chris@184
|
46 size_t kiss_fastfir( kiss_fastfir_cfg cfg, kffsamp_t * inbuf, kffsamp_t * outbuf, size_t n, size_t *offset);
|
Chris@184
|
47
|
Chris@184
|
48
|
Chris@184
|
49
|
Chris@184
|
50 static int verbose=0;
|
Chris@184
|
51
|
Chris@184
|
52
|
Chris@184
|
53 struct kiss_fastfir_state{
|
Chris@184
|
54 size_t nfft;
|
Chris@184
|
55 size_t ngood;
|
Chris@184
|
56 kfcfg_t fftcfg;
|
Chris@184
|
57 kfcfg_t ifftcfg;
|
Chris@184
|
58 kiss_fft_cpx * fir_freq_resp;
|
Chris@184
|
59 kiss_fft_cpx * freqbuf;
|
Chris@184
|
60 size_t n_freq_bins;
|
Chris@184
|
61 kffsamp_t * tmpbuf;
|
Chris@184
|
62 };
|
Chris@184
|
63
|
Chris@184
|
64
|
Chris@184
|
65 kiss_fastfir_cfg kiss_fastfir_alloc(
|
Chris@184
|
66 const kffsamp_t * imp_resp,size_t n_imp_resp,
|
Chris@184
|
67 size_t *pnfft, /* if <= 0, an appropriate size will be chosen */
|
Chris@184
|
68 void * mem,size_t*lenmem)
|
Chris@184
|
69 {
|
Chris@184
|
70 kiss_fastfir_cfg st = NULL;
|
Chris@184
|
71 size_t len_fftcfg,len_ifftcfg;
|
Chris@184
|
72 size_t memneeded = sizeof(struct kiss_fastfir_state);
|
Chris@184
|
73 char * ptr;
|
Chris@184
|
74 size_t i;
|
Chris@184
|
75 size_t nfft=0;
|
Chris@184
|
76 float scale;
|
Chris@184
|
77 int n_freq_bins;
|
Chris@184
|
78 if (pnfft)
|
Chris@184
|
79 nfft=*pnfft;
|
Chris@184
|
80
|
Chris@184
|
81 if (nfft<=0) {
|
Chris@184
|
82 /* determine fft size as next power of two at least 2x
|
Chris@184
|
83 the impulse response length*/
|
Chris@184
|
84 i=n_imp_resp-1;
|
Chris@184
|
85 nfft=2;
|
Chris@184
|
86 do{
|
Chris@184
|
87 nfft<<=1;
|
Chris@184
|
88 }while (i>>=1);
|
Chris@184
|
89 #ifdef MIN_FFT_LEN
|
Chris@184
|
90 if ( nfft < MIN_FFT_LEN )
|
Chris@184
|
91 nfft=MIN_FFT_LEN;
|
Chris@184
|
92 #endif
|
Chris@184
|
93 }
|
Chris@184
|
94 if (pnfft)
|
Chris@184
|
95 *pnfft = nfft;
|
Chris@184
|
96
|
Chris@184
|
97 #ifdef REAL_FASTFIR
|
Chris@184
|
98 n_freq_bins = nfft/2 + 1;
|
Chris@184
|
99 #else
|
Chris@184
|
100 n_freq_bins = nfft;
|
Chris@184
|
101 #endif
|
Chris@184
|
102 /*fftcfg*/
|
Chris@184
|
103 FFT_ALLOC (nfft, 0, NULL, &len_fftcfg);
|
Chris@184
|
104 memneeded += len_fftcfg;
|
Chris@184
|
105 /*ifftcfg*/
|
Chris@184
|
106 FFT_ALLOC (nfft, 1, NULL, &len_ifftcfg);
|
Chris@184
|
107 memneeded += len_ifftcfg;
|
Chris@184
|
108 /* tmpbuf */
|
Chris@184
|
109 memneeded += sizeof(kffsamp_t) * nfft;
|
Chris@184
|
110 /* fir_freq_resp */
|
Chris@184
|
111 memneeded += sizeof(kiss_fft_cpx) * n_freq_bins;
|
Chris@184
|
112 /* freqbuf */
|
Chris@184
|
113 memneeded += sizeof(kiss_fft_cpx) * n_freq_bins;
|
Chris@184
|
114
|
Chris@184
|
115 if (lenmem == NULL) {
|
Chris@184
|
116 st = (kiss_fastfir_cfg) malloc (memneeded);
|
Chris@184
|
117 } else {
|
Chris@184
|
118 if (*lenmem >= memneeded)
|
Chris@184
|
119 st = (kiss_fastfir_cfg) mem;
|
Chris@184
|
120 *lenmem = memneeded;
|
Chris@184
|
121 }
|
Chris@184
|
122 if (!st)
|
Chris@184
|
123 return NULL;
|
Chris@184
|
124
|
Chris@184
|
125 st->nfft = nfft;
|
Chris@184
|
126 st->ngood = nfft - n_imp_resp + 1;
|
Chris@184
|
127 st->n_freq_bins = n_freq_bins;
|
Chris@184
|
128 ptr=(char*)(st+1);
|
Chris@184
|
129
|
Chris@184
|
130 st->fftcfg = (kfcfg_t)ptr;
|
Chris@184
|
131 ptr += len_fftcfg;
|
Chris@184
|
132
|
Chris@184
|
133 st->ifftcfg = (kfcfg_t)ptr;
|
Chris@184
|
134 ptr += len_ifftcfg;
|
Chris@184
|
135
|
Chris@184
|
136 st->tmpbuf = (kffsamp_t*)ptr;
|
Chris@184
|
137 ptr += sizeof(kffsamp_t) * nfft;
|
Chris@184
|
138
|
Chris@184
|
139 st->freqbuf = (kiss_fft_cpx*)ptr;
|
Chris@184
|
140 ptr += sizeof(kiss_fft_cpx) * n_freq_bins;
|
Chris@184
|
141
|
Chris@184
|
142 st->fir_freq_resp = (kiss_fft_cpx*)ptr;
|
Chris@184
|
143 ptr += sizeof(kiss_fft_cpx) * n_freq_bins;
|
Chris@184
|
144
|
Chris@184
|
145 FFT_ALLOC (nfft,0,st->fftcfg , &len_fftcfg);
|
Chris@184
|
146 FFT_ALLOC (nfft,1,st->ifftcfg , &len_ifftcfg);
|
Chris@184
|
147
|
Chris@184
|
148 memset(st->tmpbuf,0,sizeof(kffsamp_t)*nfft);
|
Chris@184
|
149 /*zero pad in the middle to left-rotate the impulse response
|
Chris@184
|
150 This puts the scrap samples at the end of the inverse fft'd buffer */
|
Chris@184
|
151 st->tmpbuf[0] = imp_resp[ n_imp_resp - 1 ];
|
Chris@184
|
152 for (i=0;i<n_imp_resp - 1; ++i) {
|
Chris@184
|
153 st->tmpbuf[ nfft - n_imp_resp + 1 + i ] = imp_resp[ i ];
|
Chris@184
|
154 }
|
Chris@184
|
155
|
Chris@184
|
156 FFTFWD(st->fftcfg,st->tmpbuf,st->fir_freq_resp);
|
Chris@184
|
157
|
Chris@184
|
158 /* TODO: this won't work for fixed point */
|
Chris@184
|
159 scale = 1.0 / st->nfft;
|
Chris@184
|
160
|
Chris@184
|
161 for ( i=0; i < st->n_freq_bins; ++i ) {
|
Chris@184
|
162 #ifdef USE_SIMD
|
Chris@184
|
163 st->fir_freq_resp[i].r *= _mm_set1_ps(scale);
|
Chris@184
|
164 st->fir_freq_resp[i].i *= _mm_set1_ps(scale);
|
Chris@184
|
165 #else
|
Chris@184
|
166 st->fir_freq_resp[i].r *= scale;
|
Chris@184
|
167 st->fir_freq_resp[i].i *= scale;
|
Chris@184
|
168 #endif
|
Chris@184
|
169 }
|
Chris@184
|
170 return st;
|
Chris@184
|
171 }
|
Chris@184
|
172
|
Chris@184
|
173 static void fastconv1buf(const kiss_fastfir_cfg st,const kffsamp_t * in,kffsamp_t * out)
|
Chris@184
|
174 {
|
Chris@184
|
175 size_t i;
|
Chris@184
|
176 /* multiply the frequency response of the input signal by
|
Chris@184
|
177 that of the fir filter*/
|
Chris@184
|
178 FFTFWD( st->fftcfg, in , st->freqbuf );
|
Chris@184
|
179 for ( i=0; i<st->n_freq_bins; ++i ) {
|
Chris@184
|
180 kiss_fft_cpx tmpsamp;
|
Chris@184
|
181 C_MUL(tmpsamp,st->freqbuf[i],st->fir_freq_resp[i]);
|
Chris@184
|
182 st->freqbuf[i] = tmpsamp;
|
Chris@184
|
183 }
|
Chris@184
|
184
|
Chris@184
|
185 /* perform the inverse fft*/
|
Chris@184
|
186 FFTINV(st->ifftcfg,st->freqbuf,out);
|
Chris@184
|
187 }
|
Chris@184
|
188
|
Chris@184
|
189 /* n : the size of inbuf and outbuf in samples
|
Chris@184
|
190 return value: the number of samples completely processed
|
Chris@184
|
191 n-retval samples should be copied to the front of the next input buffer */
|
Chris@184
|
192 static size_t kff_nocopy(
|
Chris@184
|
193 kiss_fastfir_cfg st,
|
Chris@184
|
194 const kffsamp_t * inbuf,
|
Chris@184
|
195 kffsamp_t * outbuf,
|
Chris@184
|
196 size_t n)
|
Chris@184
|
197 {
|
Chris@184
|
198 size_t norig=n;
|
Chris@184
|
199 while (n >= st->nfft ) {
|
Chris@184
|
200 fastconv1buf(st,inbuf,outbuf);
|
Chris@184
|
201 inbuf += st->ngood;
|
Chris@184
|
202 outbuf += st->ngood;
|
Chris@184
|
203 n -= st->ngood;
|
Chris@184
|
204 }
|
Chris@184
|
205 return norig - n;
|
Chris@184
|
206 }
|
Chris@184
|
207
|
Chris@184
|
208 static
|
Chris@184
|
209 size_t kff_flush(kiss_fastfir_cfg st,const kffsamp_t * inbuf,kffsamp_t * outbuf,size_t n)
|
Chris@184
|
210 {
|
Chris@184
|
211 size_t zpad=0,ntmp;
|
Chris@184
|
212
|
Chris@184
|
213 ntmp = kff_nocopy(st,inbuf,outbuf,n);
|
Chris@184
|
214 n -= ntmp;
|
Chris@184
|
215 inbuf += ntmp;
|
Chris@184
|
216 outbuf += ntmp;
|
Chris@184
|
217
|
Chris@184
|
218 zpad = st->nfft - n;
|
Chris@184
|
219 memset(st->tmpbuf,0,sizeof(kffsamp_t)*st->nfft );
|
Chris@184
|
220 memcpy(st->tmpbuf,inbuf,sizeof(kffsamp_t)*n );
|
Chris@184
|
221
|
Chris@184
|
222 fastconv1buf(st,st->tmpbuf,st->tmpbuf);
|
Chris@184
|
223
|
Chris@184
|
224 memcpy(outbuf,st->tmpbuf,sizeof(kffsamp_t)*( st->ngood - zpad ));
|
Chris@184
|
225 return ntmp + st->ngood - zpad;
|
Chris@184
|
226 }
|
Chris@184
|
227
|
Chris@184
|
228 size_t kiss_fastfir(
|
Chris@184
|
229 kiss_fastfir_cfg vst,
|
Chris@184
|
230 kffsamp_t * inbuf,
|
Chris@184
|
231 kffsamp_t * outbuf,
|
Chris@184
|
232 size_t n_new,
|
Chris@184
|
233 size_t *offset)
|
Chris@184
|
234 {
|
Chris@184
|
235 size_t ntot = n_new + *offset;
|
Chris@184
|
236 if (n_new==0) {
|
Chris@184
|
237 return kff_flush(vst,inbuf,outbuf,ntot);
|
Chris@184
|
238 }else{
|
Chris@184
|
239 size_t nwritten = kff_nocopy(vst,inbuf,outbuf,ntot);
|
Chris@184
|
240 *offset = ntot - nwritten;
|
Chris@184
|
241 /*save the unused or underused samples at the front of the input buffer */
|
Chris@184
|
242 memcpy( inbuf , inbuf+nwritten , *offset * sizeof(kffsamp_t) );
|
Chris@184
|
243 return nwritten;
|
Chris@184
|
244 }
|
Chris@184
|
245 }
|
Chris@184
|
246
|
Chris@184
|
247 #ifdef FAST_FILT_UTIL
|
Chris@184
|
248 #include <unistd.h>
|
Chris@184
|
249 #include <sys/types.h>
|
Chris@184
|
250 #include <sys/mman.h>
|
Chris@184
|
251 #include <assert.h>
|
Chris@184
|
252
|
Chris@184
|
253 static
|
Chris@184
|
254 void direct_file_filter(
|
Chris@184
|
255 FILE * fin,
|
Chris@184
|
256 FILE * fout,
|
Chris@184
|
257 const kffsamp_t * imp_resp,
|
Chris@184
|
258 size_t n_imp_resp)
|
Chris@184
|
259 {
|
Chris@184
|
260 size_t nlag = n_imp_resp - 1;
|
Chris@184
|
261
|
Chris@184
|
262 const kffsamp_t *tmph;
|
Chris@184
|
263 kffsamp_t *buf, *circbuf;
|
Chris@184
|
264 kffsamp_t outval;
|
Chris@184
|
265 size_t nread;
|
Chris@184
|
266 size_t nbuf;
|
Chris@184
|
267 size_t oldestlag = 0;
|
Chris@184
|
268 size_t k, tap;
|
Chris@184
|
269 #ifndef REAL_FASTFIR
|
Chris@184
|
270 kffsamp_t tmp;
|
Chris@184
|
271 #endif
|
Chris@184
|
272
|
Chris@184
|
273 nbuf = 4096;
|
Chris@184
|
274 buf = (kffsamp_t *) malloc ( sizeof (kffsamp_t) * nbuf);
|
Chris@184
|
275 circbuf = (kffsamp_t *) malloc (sizeof (kffsamp_t) * nlag);
|
Chris@184
|
276 if (!circbuf || !buf) {
|
Chris@184
|
277 perror("circbuf allocation");
|
Chris@184
|
278 exit(1);
|
Chris@184
|
279 }
|
Chris@184
|
280
|
Chris@184
|
281 if ( fread (circbuf, sizeof (kffsamp_t), nlag, fin) != nlag ) {
|
Chris@184
|
282 perror ("insufficient data to overcome transient");
|
Chris@184
|
283 exit (1);
|
Chris@184
|
284 }
|
Chris@184
|
285
|
Chris@184
|
286 do {
|
Chris@184
|
287 nread = fread (buf, sizeof (kffsamp_t), nbuf, fin);
|
Chris@184
|
288 if (nread <= 0)
|
Chris@184
|
289 break;
|
Chris@184
|
290
|
Chris@184
|
291 for (k = 0; k < nread; ++k) {
|
Chris@184
|
292 tmph = imp_resp+nlag;
|
Chris@184
|
293 #ifdef REAL_FASTFIR
|
Chris@184
|
294 # ifdef USE_SIMD
|
Chris@184
|
295 outval = _mm_set1_ps(0);
|
Chris@184
|
296 #else
|
Chris@184
|
297 outval = 0;
|
Chris@184
|
298 #endif
|
Chris@184
|
299 for (tap = oldestlag; tap < nlag; ++tap)
|
Chris@184
|
300 outval += circbuf[tap] * *tmph--;
|
Chris@184
|
301 for (tap = 0; tap < oldestlag; ++tap)
|
Chris@184
|
302 outval += circbuf[tap] * *tmph--;
|
Chris@184
|
303 outval += buf[k] * *tmph;
|
Chris@184
|
304 #else
|
Chris@184
|
305 # ifdef USE_SIMD
|
Chris@184
|
306 outval.r = outval.i = _mm_set1_ps(0);
|
Chris@184
|
307 #else
|
Chris@184
|
308 outval.r = outval.i = 0;
|
Chris@184
|
309 #endif
|
Chris@184
|
310 for (tap = oldestlag; tap < nlag; ++tap){
|
Chris@184
|
311 C_MUL(tmp,circbuf[tap],*tmph);
|
Chris@184
|
312 --tmph;
|
Chris@184
|
313 C_ADDTO(outval,tmp);
|
Chris@184
|
314 }
|
Chris@184
|
315
|
Chris@184
|
316 for (tap = 0; tap < oldestlag; ++tap) {
|
Chris@184
|
317 C_MUL(tmp,circbuf[tap],*tmph);
|
Chris@184
|
318 --tmph;
|
Chris@184
|
319 C_ADDTO(outval,tmp);
|
Chris@184
|
320 }
|
Chris@184
|
321 C_MUL(tmp,buf[k],*tmph);
|
Chris@184
|
322 C_ADDTO(outval,tmp);
|
Chris@184
|
323 #endif
|
Chris@184
|
324
|
Chris@184
|
325 circbuf[oldestlag++] = buf[k];
|
Chris@184
|
326 buf[k] = outval;
|
Chris@184
|
327
|
Chris@184
|
328 if (oldestlag == nlag)
|
Chris@184
|
329 oldestlag = 0;
|
Chris@184
|
330 }
|
Chris@184
|
331
|
Chris@184
|
332 if (fwrite (buf, sizeof (buf[0]), nread, fout) != nread) {
|
Chris@184
|
333 perror ("short write");
|
Chris@184
|
334 exit (1);
|
Chris@184
|
335 }
|
Chris@184
|
336 } while (nread);
|
Chris@184
|
337 free (buf);
|
Chris@184
|
338 free (circbuf);
|
Chris@184
|
339 }
|
Chris@184
|
340
|
Chris@184
|
341 static
|
Chris@184
|
342 void do_file_filter(
|
Chris@184
|
343 FILE * fin,
|
Chris@184
|
344 FILE * fout,
|
Chris@184
|
345 const kffsamp_t * imp_resp,
|
Chris@184
|
346 size_t n_imp_resp,
|
Chris@184
|
347 size_t nfft )
|
Chris@184
|
348 {
|
Chris@184
|
349 int fdout;
|
Chris@184
|
350 size_t n_samps_buf;
|
Chris@184
|
351
|
Chris@184
|
352 kiss_fastfir_cfg cfg;
|
Chris@184
|
353 kffsamp_t *inbuf,*outbuf;
|
Chris@184
|
354 int nread,nwrite;
|
Chris@184
|
355 size_t idx_inbuf;
|
Chris@184
|
356
|
Chris@184
|
357 fdout = fileno(fout);
|
Chris@184
|
358
|
Chris@184
|
359 cfg=kiss_fastfir_alloc(imp_resp,n_imp_resp,&nfft,0,0);
|
Chris@184
|
360
|
Chris@184
|
361 /* use length to minimize buffer shift*/
|
Chris@184
|
362 n_samps_buf = 8*4096/sizeof(kffsamp_t);
|
Chris@184
|
363 n_samps_buf = nfft + 4*(nfft-n_imp_resp+1);
|
Chris@184
|
364
|
Chris@184
|
365 if (verbose) fprintf(stderr,"bufsize=%d\n",(int)(sizeof(kffsamp_t)*n_samps_buf) );
|
Chris@184
|
366
|
Chris@184
|
367
|
Chris@184
|
368 /*allocate space and initialize pointers */
|
Chris@184
|
369 inbuf = (kffsamp_t*)malloc(sizeof(kffsamp_t)*n_samps_buf);
|
Chris@184
|
370 outbuf = (kffsamp_t*)malloc(sizeof(kffsamp_t)*n_samps_buf);
|
Chris@184
|
371
|
Chris@184
|
372 idx_inbuf=0;
|
Chris@184
|
373 do{
|
Chris@184
|
374 /* start reading at inbuf[idx_inbuf] */
|
Chris@184
|
375 nread = fread( inbuf + idx_inbuf, sizeof(kffsamp_t), n_samps_buf - idx_inbuf,fin );
|
Chris@184
|
376
|
Chris@184
|
377 /* If nread==0, then this is a flush.
|
Chris@184
|
378 The total number of samples in input is idx_inbuf + nread . */
|
Chris@184
|
379 nwrite = kiss_fastfir(cfg, inbuf, outbuf,nread,&idx_inbuf) * sizeof(kffsamp_t);
|
Chris@184
|
380 /* kiss_fastfir moved any unused samples to the front of inbuf and updated idx_inbuf */
|
Chris@184
|
381
|
Chris@184
|
382 if ( write(fdout, outbuf, nwrite) != nwrite ) {
|
Chris@184
|
383 perror("short write");
|
Chris@184
|
384 exit(1);
|
Chris@184
|
385 }
|
Chris@184
|
386 }while ( nread );
|
Chris@184
|
387 free(cfg);
|
Chris@184
|
388 free(inbuf);
|
Chris@184
|
389 free(outbuf);
|
Chris@184
|
390 }
|
Chris@184
|
391
|
Chris@184
|
392 int main(int argc,char**argv)
|
Chris@184
|
393 {
|
Chris@184
|
394 kffsamp_t * h;
|
Chris@184
|
395 int use_direct=0;
|
Chris@184
|
396 size_t nh,nfft=0;
|
Chris@184
|
397 FILE *fin=stdin;
|
Chris@184
|
398 FILE *fout=stdout;
|
Chris@184
|
399 FILE *filtfile=NULL;
|
Chris@184
|
400 while (1) {
|
Chris@184
|
401 int c=getopt(argc,argv,"n:h:i:o:vd");
|
Chris@184
|
402 if (c==-1) break;
|
Chris@184
|
403 switch (c) {
|
Chris@184
|
404 case 'v':
|
Chris@184
|
405 verbose=1;
|
Chris@184
|
406 break;
|
Chris@184
|
407 case 'n':
|
Chris@184
|
408 nfft=atoi(optarg);
|
Chris@184
|
409 break;
|
Chris@184
|
410 case 'i':
|
Chris@184
|
411 fin = fopen(optarg,"rb");
|
Chris@184
|
412 if (fin==NULL) {
|
Chris@184
|
413 perror(optarg);
|
Chris@184
|
414 exit(1);
|
Chris@184
|
415 }
|
Chris@184
|
416 break;
|
Chris@184
|
417 case 'o':
|
Chris@184
|
418 fout = fopen(optarg,"w+b");
|
Chris@184
|
419 if (fout==NULL) {
|
Chris@184
|
420 perror(optarg);
|
Chris@184
|
421 exit(1);
|
Chris@184
|
422 }
|
Chris@184
|
423 break;
|
Chris@184
|
424 case 'h':
|
Chris@184
|
425 filtfile = fopen(optarg,"rb");
|
Chris@184
|
426 if (filtfile==NULL) {
|
Chris@184
|
427 perror(optarg);
|
Chris@184
|
428 exit(1);
|
Chris@184
|
429 }
|
Chris@184
|
430 break;
|
Chris@184
|
431 case 'd':
|
Chris@184
|
432 use_direct=1;
|
Chris@184
|
433 break;
|
Chris@184
|
434 case '?':
|
Chris@184
|
435 fprintf(stderr,"usage options:\n"
|
Chris@184
|
436 "\t-n nfft: fft size to use\n"
|
Chris@184
|
437 "\t-d : use direct FIR filtering, not fast convolution\n"
|
Chris@184
|
438 "\t-i filename: input file\n"
|
Chris@184
|
439 "\t-o filename: output(filtered) file\n"
|
Chris@184
|
440 "\t-n nfft: fft size to use\n"
|
Chris@184
|
441 "\t-h filename: impulse response\n");
|
Chris@184
|
442 exit (1);
|
Chris@184
|
443 default:fprintf(stderr,"bad %c\n",c);break;
|
Chris@184
|
444 }
|
Chris@184
|
445 }
|
Chris@184
|
446 if (filtfile==NULL) {
|
Chris@184
|
447 fprintf(stderr,"You must supply the FIR coeffs via -h\n");
|
Chris@184
|
448 exit(1);
|
Chris@184
|
449 }
|
Chris@184
|
450 fseek(filtfile,0,SEEK_END);
|
Chris@184
|
451 nh = ftell(filtfile) / sizeof(kffsamp_t);
|
Chris@184
|
452 if (verbose) fprintf(stderr,"%d samples in FIR filter\n",(int)nh);
|
Chris@184
|
453 h = (kffsamp_t*)malloc(sizeof(kffsamp_t)*nh);
|
Chris@184
|
454 fseek(filtfile,0,SEEK_SET);
|
Chris@184
|
455 if (fread(h,sizeof(kffsamp_t),nh,filtfile) != nh)
|
Chris@184
|
456 fprintf(stderr,"short read on filter file\n");
|
Chris@184
|
457
|
Chris@184
|
458 fclose(filtfile);
|
Chris@184
|
459
|
Chris@184
|
460 if (use_direct)
|
Chris@184
|
461 direct_file_filter( fin, fout, h,nh);
|
Chris@184
|
462 else
|
Chris@184
|
463 do_file_filter( fin, fout, h,nh,nfft);
|
Chris@184
|
464
|
Chris@184
|
465 if (fout!=stdout) fclose(fout);
|
Chris@184
|
466 if (fin!=stdin) fclose(fin);
|
Chris@184
|
467
|
Chris@184
|
468 return 0;
|
Chris@184
|
469 }
|
Chris@184
|
470 #endif
|