Revision d15bed21 gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc

View differences:

gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc
31 31
#include <cstring>
32 32

33 33
gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf 
34
    (unsigned int numchans, const std::vector<float> &taps)
34
    (unsigned int numchans, const std::vector<float> &taps, bool twox)
35 35
{
36 36
  return gr_pfb_synthesis_filterbank_ccf_sptr 
37
    (new gr_pfb_synthesis_filterbank_ccf (numchans, taps));
37
    (new gr_pfb_synthesis_filterbank_ccf (numchans, taps, twox));
38 38
}
39 39

40 40

41 41
gr_pfb_synthesis_filterbank_ccf::gr_pfb_synthesis_filterbank_ccf
42
    (unsigned int numchans, const std::vector<float> &taps)
42
    (unsigned int numchans, const std::vector<float> &taps, bool twox)
43 43
  : gr_sync_interpolator ("pfb_synthesis_filterbank_ccf",
44 44
			  gr_make_io_signature (1, numchans, sizeof(gr_complex)),
45 45
			  gr_make_io_signature (1, 1, sizeof(gr_complex)),
46 46
			  numchans),
47 47
    d_updated (false), d_numchans(numchans), d_state(0)
48 48
{
49
  d_filters = std::vector<gri_fir_filter_with_buffer_ccf*>(2*d_numchans);
49
  // set up 2x multiplier; if twox==True, set to 2, otherwise to 1
50
  d_twox = (twox ? 2 : 1);
51
  if(d_numchans % d_twox != 0) {
52
    throw std::invalid_argument("gr_pfb_synthesis_filterbank_ccf: number of channels must be even for 2x oversampling.\n");
53
  }
54

55
  d_filters = std::vector<gri_fir_filter_with_buffer_ccf*>(d_twox*d_numchans);
56
  d_channel_map.resize(d_twox*d_numchans);
50 57

51 58
  // Create an FIR filter for each channel and zero out the taps
52
  std::vector<float> vtaps(0, 2*d_numchans);
53
  for(unsigned int i = 0; i < 2*d_numchans; i++) {
59
  std::vector<float> vtaps(0, d_twox*d_numchans);
60
  for(unsigned int i = 0; i < d_twox*d_numchans; i++) {
54 61
    d_filters[i] = new gri_fir_filter_with_buffer_ccf(vtaps);
62
    d_channel_map[i] = i;
55 63
  }
56 64

57 65
  // Now, actually set the filters' taps
58
  set_taps2(taps);
66
  set_taps(taps);
59 67

60 68
  // Create the IFFT to handle the input channel rotations
61
  d_fft = new gri_fft_complex (2*d_numchans, false);
62
  memset(d_fft->get_inbuf(), 0, 2*d_numchans*sizeof(gr_complex));
69
  d_fft = new gri_fft_complex (d_twox*d_numchans, false);
70
  memset(d_fft->get_inbuf(), 0, d_twox*d_numchans*sizeof(gr_complex));
63 71

64 72
  set_output_multiple(d_numchans);
65 73
}
66 74

67 75
gr_pfb_synthesis_filterbank_ccf::~gr_pfb_synthesis_filterbank_ccf ()
68 76
{
69
  for(unsigned int i = 0; i < d_numchans; i++) {
77
  for(unsigned int i = 0; i < d_twox*d_numchans; i++) {
70 78
    delete d_filters[i];
71 79
  }
72 80
}
73 81

74 82
void
75
gr_pfb_synthesis_filterbank_ccf::set_taps (const std::vector<float> &taps)
83
gr_pfb_synthesis_filterbank_ccf::set_taps(const std::vector<float> &taps)
84
{
85
  gruel::scoped_lock guard(d_mutex);
86
  if(d_twox == 1)
87
    set_taps1(taps);
88
  else
89
    set_taps2(taps);
90
}
91

92
void
93
gr_pfb_synthesis_filterbank_ccf::set_taps1(const std::vector<float> &taps)
76 94
{
77 95
  unsigned int i,j;
78 96

......
118 136
  d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans);
119 137

120 138
  // Create d_numchan vectors to store each channel's taps
121
  d_taps.resize(2*d_numchans);
139
  d_taps.resize(d_twox*d_numchans);
122 140

123 141
  // Make a vector of the taps plus fill it out with 0's to fill
124 142
  // each polyphase filter with exactly d_taps_per_filter
......
164 182
gr_pfb_synthesis_filterbank_ccf::print_taps()
165 183
{
166 184
  unsigned int i, j;
167
  for(i = 0; i < 2*d_numchans; i++) {
185
  for(i = 0; i < d_twox*d_numchans; i++) {
168 186
    printf("filter[%d]: [", i);
169 187
    for(j = 0; j < d_taps_per_filter; j++) {
170 188
      printf(" %.4e", d_taps[i][j]);
......
174 192
}
175 193

176 194

195
std::vector< std::vector<float> >
196
gr_pfb_synthesis_filterbank_ccf::taps() const
197
{
198
  return d_taps;
199
}
200

201
void
202
gr_pfb_synthesis_filterbank_ccf::set_channel_map(const std::vector<int> &map)
203
{
204
  gruel::scoped_lock guard(d_mutex);
205

206
  unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end());
207
  unsigned int min = (unsigned int)*std::min_element(map.begin(), map.end());
208
  if((max >= d_twox*d_numchans) || (min < 0)) {
209
    throw std::invalid_argument("gr_pfb_synthesis_filterbank_ccf::set_channel_map: map range out of bounds.\n");
210
  }
211
  d_channel_map = map;
212

213
  // Zero out fft buffer so that unused channels are always 0
214
  memset(d_fft->get_inbuf(), 0,d_twox*d_numchans*sizeof(gr_complex));
215
}
216

217
std::vector<int>
218
gr_pfb_synthesis_filterbank_ccf::channel_map() const
219
{
220
  return d_channel_map;
221
}
222

177 223
int
178 224
gr_pfb_synthesis_filterbank_ccf::work (int noutput_items,
179 225
				       gr_vector_const_void_star &input_items,
180 226
				       gr_vector_void_star &output_items)
181 227
{
228
  gruel::scoped_lock guard(d_mutex);
229

182 230
  gr_complex *in = (gr_complex*) input_items[0];
183 231
  gr_complex *out = (gr_complex *) output_items[0];
184 232

......
188 236
  }
189 237

190 238
  unsigned int n, i;
191
  for(n = 0; n < noutput_items/d_numchans; n++) {
192
    for(i = 0; i < d_numchans; i++) {
193
      in = (gr_complex*)input_items[i];
194
      d_fft->get_inbuf()[i] = in[n];
239
  size_t ninputs = input_items.size();
240

241
  // Algoritm for critically sampled channels
242
  if(d_twox == 1) {
243
    for(n = 0; n < noutput_items/d_numchans; n++) {
244
      for(i = 0; i < ninputs; i++) {
245
	in = (gr_complex*)input_items[i];
246
	d_fft->get_inbuf()[d_channel_map[i]] = in[n];
247
      }
248
      
249
      // spin through IFFT
250
      d_fft->execute();
251
      
252
      for(i = 0; i < d_numchans; i++) {
253
	out[i]  = d_filters[i]->filter(d_fft->get_outbuf()[i]);
254
      }
255
      out += d_numchans;
195 256
    }
196
    
197
    // spin through IFFT
198
    d_fft->execute();
199

200
    // Output is sum of two filters, but the input buffer to the filters must be circularly
201
    // shifted by numchans every time through, done by using d_state to determine which IFFT
202
    // buffer position to pull from.
203
    for(i = 0; i < d_numchans; i++) {
204
      out[i]  = d_filters[i]->filter(d_fft->get_outbuf()[d_state*d_numchans+i]);
205
      out[i] += d_filters[d_numchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*d_numchans+i]);
257
  }
258
  
259
  // Algorithm for oversampling by 2x
260
  else {
261
    for(n = 0; n < noutput_items/d_numchans; n++) {
262
      for(i = 0; i < ninputs; i++) {
263
	in = (gr_complex*)input_items[i];
264
	d_fft->get_inbuf()[d_channel_map[i]] = in[n];
265
      }
266
      
267
      // spin through IFFT
268
      d_fft->execute();
269
      
270
      // Output is sum of two filters, but the input buffer to the filters must be circularly
271
      // shifted by numchans every time through, done by using d_state to determine which IFFT
272
      // buffer position to pull from.
273
      for(i = 0; i < d_numchans; i++) {
274
	out[i]  = d_filters[i]->filter(d_fft->get_outbuf()[d_state*d_numchans+i]);
275
	out[i] += d_filters[d_numchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*d_numchans+i]);
276
      }
277
      d_state ^= 1;
278
      
279
      out += d_numchans;
206 280
    }
207
    d_state ^= 1;
208
    
209
    out += d_numchans;
210 281
  }
211 282

212 283
  return noutput_items;

Also available in: Unified diff