Statistics
| Branch: | Tag: | Revision:

root / gr-filter / lib / fir_filter.cc @ 1b93bb39

History | View | Annotate | Download (6.8 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2004,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
#include <filter/fir_filter.h>
24
#include <fft/fft.h>
25
#include <volk/volk.h>
26
#include <cstdio>
27
#include <float_dotprod_x86.h>
28
29
namespace gr {
30
  namespace filter {
31
    namespace kernel {
32
    
33
      fir_filter_fff::fir_filter_fff(int decimation,
34
                                     const std::vector<float> &taps)
35
      {
36
        d_taps = NULL;
37
        set_taps(taps);
38
39
        // Make sure the output sample is always aligned, too.
40
        d_output = fft::malloc_float(1);
41
      }
42
      
43
      fir_filter_fff::~fir_filter_fff()
44
      {
45
        // Free taps
46
        if(d_taps != NULL) {
47
          fft::free(d_taps);
48
          d_taps = NULL;
49
        }
50
51
        // Free all aligned taps
52
        for(int i = 0; i < 4; i++) {
53
          fft::free(d_aligned_taps[i]);
54
        }
55
        fft::free(d_aligned_taps);
56
57
        // Free output sample
58
        fft::free(d_output);
59
      }
60
      
61
      void
62
      fir_filter_fff::set_taps(const std::vector<float> &taps)
63
      {
64
        // Free the taps if already allocated
65
        if(d_taps != NULL) {
66
          fft::free(d_taps);
67
          d_taps = NULL;
68
69
          for(int i = 0; i < 4; i++) {
70
            fft::free(d_aligned_taps[i]);
71
          }
72
          fft::free(d_aligned_taps);
73
        }
74
        
75
        d_ntaps = (int)taps.size();
76
        d_taps = fft::malloc_float(d_ntaps);
77
        for(unsigned int i = 0; i < d_ntaps; i++) {
78
          d_taps[d_ntaps-i-1] = taps[i];
79
        }
80
81
        // Make a set of taps at all possible arch alignments
82
        d_aligned_taps = (float**)malloc(4*sizeof(float**));
83
        for(int i = 0; i < 4; i++) {
84
          d_aligned_taps[i] = fft::malloc_float(d_ntaps+3);
85
          memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+3));
86
          memcpy(&d_aligned_taps[i][i], d_taps, sizeof(float)*(d_ntaps));
87
        }
88
      }
89
      
90
      std::vector<float>
91
      fir_filter_fff::taps() const
92
      {
93
        std::vector<float> t;
94
        for(unsigned int i = 0; i < d_ntaps; i++)
95
          t.push_back(d_taps[d_ntaps-i-1]);
96
        return t;
97
      }
98
99
      unsigned int
100
      fir_filter_fff::ntaps() const
101
      {
102
        return d_ntaps;
103
      }
104
105
      float
106
      fir_filter_fff::filter(const float input[])
107
      {
108
        const float *ar = (float *)((unsigned long) input & ~15);
109
        unsigned al = input - ar;
110
111
        volk_32f_x2_dot_prod_32f_a(d_output, ar,
112
                                   d_aligned_taps[al],
113
                                   (d_ntaps + al - 1) / 4 + 1);
114
        return *d_output;
115
      }
116
      
117
      void
118
      fir_filter_fff::filterN(float output[],
119
                              const float input[],
120
                              unsigned long n)
121
      {
122
        for(unsigned long i = 0; i < n; i++) {
123
          output[i] = filter(&input[i]);
124
        }
125
      }
126
      
127
      void
128
      fir_filter_fff::filterNdec(float output[],
129
                                 const float input[],
130
                                 unsigned long n,
131
                                 unsigned int decimate)
132
      {
133
        unsigned long j = 0;
134
        for(unsigned long i = 0; i < n; i++) {
135
          output[i] = filter(&input[j]);
136
          j += decimate;
137
        }
138
      }
139
      
140
      /**************************************************************/
141
142
      fir_filter_ccf::fir_filter_ccf(int decimation,
143
                                     const std::vector<float> &taps)
144
      {
145
        d_taps = NULL;
146
        set_taps(taps);
147
      }
148
      
149
      fir_filter_ccf::~fir_filter_ccf()
150
      {
151
        if(d_taps != NULL) {
152
          fft::free(d_taps);
153
          d_taps = NULL;
154
        }
155
    }
156
      
157
      void
158
      fir_filter_ccf::set_taps(const std::vector<float> &taps)
159
      {
160
        // Free the taps if already allocated
161
        if(d_taps != NULL) {
162
          fft::free(d_taps);
163
          d_taps = NULL;
164
        }
165
        
166
        d_ntaps = (int)taps.size();
167
        d_taps = fft::malloc_complex(d_ntaps);
168
        for(unsigned int i = 0; i < d_ntaps; i++) {
169
          d_taps[d_ntaps-i-1] = gr_complex(taps[i],0);
170
        }
171
      }
172
      
173
      std::vector<float>
174
      fir_filter_ccf::taps() const
175
      {
176
        std::vector<float> t;
177
        for(unsigned int i = 0; i < d_ntaps; i++)
178
          t.push_back(d_taps[d_ntaps-i-1].real());
179
        return t;
180
      }
181
182
      unsigned int
183
      fir_filter_ccf::ntaps() const
184
      {
185
        return d_ntaps;
186
      }
187
      
188
      gr_complex
189
      fir_filter_ccf::filter(const gr_complex input[])
190
      {
191
        gr_complex output;
192
        volk_32fc_x2_dot_prod_32fc_u(&output, input, d_taps, d_ntaps);
193
        return output;
194
      }
195
      
196
      void
197
      fir_filter_ccf::filterN(gr_complex output[],
198
                              const gr_complex input[],
199
                              unsigned long n)
200
      {
201
        for(unsigned long i = 0; i < n; i++)
202
          output[i] = filter(&input[i]);
203
      }
204
      
205
      
206
      void
207
      fir_filter_ccf::filterNdec(gr_complex output[],
208
                                 const gr_complex input[],
209
                                 unsigned long n,
210
                                 unsigned int decimate)
211
      {
212
        unsigned long j = 0;
213
        for(unsigned long i = 0; i < n; i++){
214
          output[i] = filter(&input[j]);
215
          j += decimate;
216
        }
217
      }
218
      
219
      /**************************************************************/
220
221
      fir_filter_ccc::fir_filter_ccc(int decimation,
222
                                     const std::vector<gr_complex> &taps)
223
      {
224
        d_taps = NULL;
225
        set_taps(taps);
226
      }
227
      
228
      fir_filter_ccc::~fir_filter_ccc()
229
      {
230
        if(d_taps != NULL) {
231
          fft::free(d_taps);
232
          d_taps = NULL;
233
        }
234
    }
235
      
236
      void
237
      fir_filter_ccc::set_taps(const std::vector<gr_complex> &taps)
238
      {
239
        // Free the taps if already allocated
240
        if(d_taps != NULL) {
241
          fft::free(d_taps);
242
          d_taps = NULL;
243
        }
244
        
245
        d_ntaps = (int)taps.size();
246
        d_taps = fft::malloc_complex(d_ntaps);
247
        for(unsigned int i = 0; i < d_ntaps; i++) {
248
          d_taps[d_ntaps-i-1] = taps[i];
249
        }
250
      }
251
      
252
      std::vector<gr_complex>
253
      fir_filter_ccc::taps() const
254
      {
255
        std::vector<gr_complex> t;
256
        for(unsigned int i = 0; i < d_ntaps; i++)
257
          t.push_back(d_taps[d_ntaps-i-1]);
258
        return t;
259
      }
260
261
      unsigned int
262
      fir_filter_ccc::ntaps() const
263
      {
264
        return d_ntaps;
265
      }
266
      
267
      gr_complex
268
      fir_filter_ccc::filter(const gr_complex input[])
269
      {
270
        gr_complex output;
271
        volk_32fc_x2_dot_prod_32fc_u(&output, input, d_taps, d_ntaps);
272
        return output;
273
      }
274
      
275
      void
276
      fir_filter_ccc::filterN(gr_complex output[],
277
                              const gr_complex input[],
278
                              unsigned long n)
279
      {
280
        for(unsigned long i = 0; i < n; i++)
281
          output[i] = filter(&input[i]);
282
      }
283
      
284
      
285
      void
286
      fir_filter_ccc::filterNdec(gr_complex output[],
287
                                 const gr_complex input[],
288
                                 unsigned long n,
289
                                 unsigned int decimate)
290
      {
291
        unsigned long j = 0;
292
        for(unsigned long i = 0; i < n; i++){
293
          output[i] = filter(&input[j]);
294
          j += decimate;
295
        }
296
      }
297
      
298
    } /* namespace kernel */
299
  } /* namespace filter */
300
} /* namespace gr */