Revision d15bed21 gnuradiocore/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc
gnuradiocore/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