Statistics
| Branch: | Tag: | Revision:

root / gr-filter / lib / fir_filter_with_buffer.cc @ 6b2dbab5

History | View | Annotate | Download (11.1 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2010,2012 Free Software Foundation, Inc.
4
 *
5
 * This file is part of GNU Radio
6
 *
7
 * GNU Radio 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 3, or (at your option)
10
 * any later version.
11
 *
12
 * GNU Radio 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.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with GNU Radio; see the file COPYING.  If not, write to
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
20
 * Boston, MA 02110-1301, USA.
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include <config.h>
25
#endif
26
27
#include <filter/fir_filter_with_buffer.h>
28
#include <fft/fft.h>
29
#include <volk/volk.h>
30
#include <algorithm>
31
#include <cstdio>
32
33
namespace gr {
34
  namespace filter {
35
    namespace kernel {
36
37
      fir_filter_with_buffer_fff::fir_filter_with_buffer_fff(const std::vector<float> &taps)
38
      {
39
        d_align = volk_get_alignment();
40
        d_naligned = d_align / sizeof(float);
41
42
        d_buffer = NULL;
43
        d_aligned_taps = NULL;
44
        set_taps(taps);
45
46
        // Make sure the output sample is always aligned, too.
47
        d_output = fft::malloc_float(1);
48
      }
49
50
      fir_filter_with_buffer_fff::~fir_filter_with_buffer_fff()
51
      {
52
        if(d_buffer != NULL) {
53
          fft::free(d_buffer);
54
          d_buffer = NULL;
55
        }
56
        
57
        // Free aligned taps
58
        if(d_aligned_taps != NULL) {
59
          for(int i = 0; i < d_naligned; i++) {
60
            fft::free(d_aligned_taps[i]);
61
          }
62
          fft::free(d_aligned_taps);
63
          d_aligned_taps = NULL;
64
        }
65
66
        // Free output sample
67
        fft::free(d_output);
68
      }
69
70
      void
71
      fir_filter_with_buffer_fff::set_taps(const std::vector<float> &taps)
72
      {
73
        if(d_buffer != NULL) {
74
          fft::free(d_buffer);
75
          d_buffer = NULL;
76
        }
77
78
        // Free the taps if already allocated
79
        if(d_aligned_taps != NULL) {
80
          for(int i = 0; i < d_naligned; i++) {
81
            fft::free(d_aligned_taps[i]);
82
          }
83
          fft::free(d_aligned_taps);
84
          d_aligned_taps = NULL;
85
        }
86
87
        d_ntaps = (int)taps.size();
88
        d_taps = taps;
89
        std::reverse(d_taps.begin(), d_taps.end());
90
91
        d_buffer = fft::malloc_float(2*d_ntaps);
92
        memset(d_buffer, 0, 2*d_ntaps*sizeof(float));
93
94
        // Allocate aligned taps
95
        d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**));
96
        for(int i = 0; i < d_naligned; i++) {
97
          d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1);
98
          memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1));
99
          for(unsigned int j = 0; j < d_ntaps; j++)
100
            d_aligned_taps[i][i+j] = d_taps[j];
101
        }
102
103
        d_idx = 0;
104
      }
105
106
      std::vector<float>
107
      fir_filter_with_buffer_fff::taps() const
108
      {
109
        std::vector<float> t = d_taps;
110
        std::reverse(t.begin(), t.end());
111
        return t;
112
      }
113
114
      float
115
      fir_filter_with_buffer_fff::filter(float input)
116
      {
117
        d_buffer[d_idx] = input;
118
        d_buffer[d_idx+ntaps()] = input;
119
120
        d_idx++;
121
        if(d_idx >= ntaps())
122
          d_idx = 0;
123
124
        const float *ar = (float*)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
125
        unsigned al = (&d_buffer[d_idx]) - ar;
126
127
        volk_32f_x2_dot_prod_32f_a(d_output, ar,
128
                                   d_aligned_taps[al],
129
                                   ntaps()+al);
130
        return *d_output;
131
      }
132
133
      float
134
      fir_filter_with_buffer_fff::filter(const float input[],
135
                                         unsigned long dec)
136
      {
137
        unsigned int i;
138
139
        for(i = 0; i < dec; i++) {
140
          d_buffer[d_idx] = input[i];
141
          d_buffer[d_idx+ntaps()] = input[i];
142
          d_idx++;
143
          if(d_idx >= ntaps())
144
            d_idx = 0;
145
        }
146
147
        const float *ar = (float*)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
148
        unsigned al = (&d_buffer[d_idx]) - ar;
149
150
        volk_32f_x2_dot_prod_32f_a(d_output, ar,
151
                                   d_aligned_taps[al],
152
                                   ntaps()+al);
153
        return *d_output;
154
      }
155
156
      void
157
      fir_filter_with_buffer_fff::filterN(float output[],
158
                                          const float input[],
159
                                          unsigned long n)
160
      {
161
        for(unsigned long i = 0; i < n; i++) {
162
          output[i] = filter(input[i]);
163
        }
164
      }
165
166
      void
167
      fir_filter_with_buffer_fff::filterNdec(float output[],
168
                                             const float input[],
169
                                             unsigned long n,
170
                                             unsigned long decimate)
171
      {
172
        unsigned long j = 0;
173
        for(unsigned long i = 0; i < n; i++) {
174
          output[i] = filter(&input[j], decimate);
175
          j += decimate;
176
        }
177
      }
178
179
      
180
      /**************************************************************/
181
182
183
      fir_filter_with_buffer_ccc::fir_filter_with_buffer_ccc(const std::vector<gr_complex> &taps)
184
      {
185
        d_align = volk_get_alignment();
186
        d_naligned = d_align / sizeof(gr_complex);
187
188
        d_buffer = NULL;
189
        d_aligned_taps = NULL;
190
        set_taps(taps);
191
192
        // Make sure the output sample is always aligned, too.
193
        d_output = fft::malloc_complex(1);
194
      }
195
196
      fir_filter_with_buffer_ccc::~fir_filter_with_buffer_ccc()
197
      {
198
        if(d_buffer != NULL) {
199
          fft::free(d_buffer);
200
          d_buffer = NULL;
201
        }
202
        
203
        // Free aligned taps
204
        if(d_aligned_taps != NULL) {
205
          for(int i = 0; i < d_naligned; i++) {
206
            fft::free(d_aligned_taps[i]);
207
          }
208
          fft::free(d_aligned_taps);
209
          d_aligned_taps = NULL;
210
        }
211
212
        // Free output sample
213
        fft::free(d_output);
214
      }
215
216
      void
217
      fir_filter_with_buffer_ccc::set_taps(const std::vector<gr_complex> &taps)
218
      {
219
        if(d_buffer != NULL) {
220
          fft::free(d_buffer);
221
          d_buffer = NULL;
222
        }
223
224
        // Free the taps if already allocated
225
        if(d_aligned_taps != NULL) {
226
          for(int i = 0; i < d_naligned; i++) {
227
            fft::free(d_aligned_taps[i]);
228
          }
229
          fft::free(d_aligned_taps);
230
          d_aligned_taps = NULL;
231
        }
232
233
        d_ntaps = (int)taps.size();
234
        d_taps = taps;
235
        std::reverse(d_taps.begin(), d_taps.end());
236
237
        d_buffer = fft::malloc_complex(2*d_ntaps);
238
        memset(d_buffer, 0, 2*d_ntaps*sizeof(gr_complex));
239
240
        // Allocate aligned taps
241
        d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**));
242
        for(int i = 0; i < d_naligned; i++) {
243
          d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1);
244
          memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1));
245
          for(unsigned int j = 0; j < d_ntaps; j++)
246
            d_aligned_taps[i][i+j] = d_taps[j];
247
        }
248
249
        d_idx = 0;
250
      }
251
252
      std::vector<gr_complex>
253
      fir_filter_with_buffer_ccc::taps() const
254
      {
255
        std::vector<gr_complex> t = d_taps;
256
        std::reverse(t.begin(), t.end());
257
        return t;
258
      }
259
260
      gr_complex
261
      fir_filter_with_buffer_ccc::filter(gr_complex input)
262
      {
263
        d_buffer[d_idx] = input;
264
        d_buffer[d_idx+ntaps()] = input;
265
266
        d_idx++;
267
        if(d_idx >= ntaps())
268
          d_idx = 0;
269
270
        const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
271
        unsigned al = (&d_buffer[d_idx]) - ar;
272
273
        volk_32fc_x2_dot_prod_32fc_a(d_output, ar,
274
                                     d_aligned_taps[al],
275
                                     (ntaps()+al)*sizeof(gr_complex));
276
        return *d_output;
277
      }
278
279
      gr_complex
280
      fir_filter_with_buffer_ccc::filter(const gr_complex input[],
281
                                         unsigned long dec)
282
      {
283
        unsigned int i;
284
285
        for(i = 0; i < dec; i++) {
286
          d_buffer[d_idx] = input[i];
287
          d_buffer[d_idx+ntaps()] = input[i];
288
          d_idx++;
289
          if(d_idx >= ntaps())
290
            d_idx = 0;
291
        }
292
293
        const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
294
        unsigned al = (&d_buffer[d_idx]) - ar;
295
296
        volk_32fc_x2_dot_prod_32fc_a(d_output, ar,
297
                                     d_aligned_taps[al],
298
                                     (ntaps()+al)*sizeof(gr_complex));
299
        return *d_output;
300
      }
301
302
      void
303
      fir_filter_with_buffer_ccc::filterN(gr_complex output[],
304
                                          const gr_complex input[],
305
                                          unsigned long n)
306
      {
307
        for(unsigned long i = 0; i < n; i++) {
308
          output[i] = filter(input[i]);
309
        }
310
      }
311
312
      void
313
      fir_filter_with_buffer_ccc::filterNdec(gr_complex output[],
314
                                             const gr_complex input[],
315
                                             unsigned long n,
316
                                             unsigned long decimate)
317
      {
318
        unsigned long j = 0;
319
        for(unsigned long i = 0; i < n; i++) {
320
          output[i] = filter(&input[j], decimate);
321
          j += decimate;
322
        }
323
      }
324
325
      
326
      /**************************************************************/
327
328
329
      fir_filter_with_buffer_ccf::fir_filter_with_buffer_ccf(const std::vector<float> &taps)
330
      {
331
        d_align = volk_get_alignment();
332
        d_naligned = d_align / sizeof(gr_complex);
333
334
        d_buffer = NULL;
335
        d_aligned_taps = NULL;
336
        set_taps(taps);
337
338
        // Make sure the output sample is always aligned, too.
339
        d_output = fft::malloc_complex(1);
340
      }
341
342
      fir_filter_with_buffer_ccf::~fir_filter_with_buffer_ccf()
343
      {
344
        if(d_buffer != NULL) {
345
          fft::free(d_buffer);
346
          d_buffer = NULL;
347
        }
348
        
349
        // Free aligned taps
350
        if(d_aligned_taps != NULL) {
351
          for(int i = 0; i < d_naligned; i++) {
352
            fft::free(d_aligned_taps[i]);
353
          }
354
          fft::free(d_aligned_taps);
355
          d_aligned_taps = NULL;
356
        }
357
358
        // Free output sample
359
        fft::free(d_output);
360
      }
361
362
      void
363
      fir_filter_with_buffer_ccf::set_taps(const std::vector<float> &taps)
364
      {
365
        if(d_buffer != NULL) {
366
          fft::free(d_buffer);
367
          d_buffer = NULL;
368
        }
369
370
        // Free the taps if already allocated
371
        if(d_aligned_taps != NULL) {
372
          for(int i = 0; i < d_naligned; i++) {
373
            fft::free(d_aligned_taps[i]);
374
          }
375
          fft::free(d_aligned_taps);
376
          d_aligned_taps = NULL;
377
        }
378
379
        d_ntaps = (int)taps.size();
380
        d_taps = taps;
381
        std::reverse(d_taps.begin(), d_taps.end());
382
383
        d_buffer = fft::malloc_complex(2*d_ntaps);
384
        memset(d_buffer, 0, 2*d_ntaps*sizeof(gr_complex));
385
386
        // Allocate aligned taps
387
        d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**));
388
        for(int i = 0; i < d_naligned; i++) {
389
          d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1);
390
          memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1));
391
          for(unsigned int j = 0; j < d_ntaps; j++)
392
            d_aligned_taps[i][i+j] = d_taps[j];
393
        }
394
395
        d_idx = 0;
396
      }
397
398
      std::vector<float>
399
      fir_filter_with_buffer_ccf::taps() const
400
      {
401
        std::vector<float> t = d_taps;
402
        std::reverse(t.begin(), t.end());
403
        return t;
404
      }
405
406
      gr_complex
407
      fir_filter_with_buffer_ccf::filter(gr_complex input)
408
      {
409
        d_buffer[d_idx] = input;
410
        d_buffer[d_idx+ntaps()] = input;
411
412
        d_idx++;
413
        if(d_idx >= ntaps())
414
          d_idx = 0;
415
416
        const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
417
        unsigned al = (&d_buffer[d_idx]) - ar;
418
419
        volk_32fc_32f_dot_prod_32fc_a(d_output, ar,
420
                                      d_aligned_taps[al],
421
                                      ntaps()+al);
422
        return *d_output;
423
      }
424
425
      gr_complex
426
      fir_filter_with_buffer_ccf::filter(const gr_complex input[],
427
                                         unsigned long dec)
428
      {
429
        unsigned int i;
430
431
        for(i = 0; i < dec; i++) {
432
          d_buffer[d_idx] = input[i];
433
          d_buffer[d_idx+ntaps()] = input[i];
434
          d_idx++;
435
          if(d_idx >= ntaps())
436
            d_idx = 0;
437
        }
438
439
        const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1));
440
        unsigned al = (&d_buffer[d_idx]) - ar;
441
442
        volk_32fc_32f_dot_prod_32fc_a(d_output, ar,
443
                                      d_aligned_taps[al],
444
                                      ntaps()+al);
445
        return *d_output;
446
      }
447
448
      void
449
      fir_filter_with_buffer_ccf::filterN(gr_complex output[],
450
                                          const gr_complex input[],
451
                                          unsigned long n)
452
      {
453
        for(unsigned long i = 0; i < n; i++) {
454
          output[i] = filter(input[i]);
455
        }
456
      }
457
458
      void
459
      fir_filter_with_buffer_ccf::filterNdec(gr_complex output[],
460
                                             const gr_complex input[],
461
                                             unsigned long n,
462
                                             unsigned long decimate)
463
      {
464
        unsigned long j = 0;
465
        for(unsigned long i = 0; i < n; i++) {
466
          output[i] = filter(&input[j], decimate);
467
          j += decimate;
468
        }
469
      }
470
471
472
    } /* namespace kernel */
473
  } /* namespace filter */
474
} /* namespace gr */