summaryrefslogtreecommitdiff
path: root/gr-filter
diff options
context:
space:
mode:
authorTom Rondeau2013-02-14 09:50:52 -0500
committerTom Rondeau2013-02-14 12:45:09 -0500
commit5f90465feed9949d00bc8c639fa4e911162449bd (patch)
tree01e81b81a7d28c3c0bcbb5b6d9791d29f1371add /gr-filter
parentdc4bb4a2dcab344c5e397686fd43c5e98b85ba72 (diff)
downloadgnuradio-5f90465feed9949d00bc8c639fa4e911162449bd.tar.gz
gnuradio-5f90465feed9949d00bc8c639fa4e911162449bd.tar.bz2
gnuradio-5f90465feed9949d00bc8c639fa4e911162449bd.zip
filter: fixing synthesis filter output rate when using 2x oversampling.
Diffstat (limited to 'gr-filter')
-rw-r--r--gr-filter/lib/pfb_synthesizer_ccf_impl.cc52
1 files changed, 27 insertions, 25 deletions
diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
index 9dd519d57..f89b48b12 100644
--- a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
+++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc
@@ -47,8 +47,8 @@ namespace gr {
: gr_sync_interpolator("pfb_synthesizer_ccf",
gr_make_io_signature(1, numchans, sizeof(gr_complex)),
gr_make_io_signature(1, 1, sizeof(gr_complex)),
- numchans),
- d_updated (false), d_numchans(numchans), d_state(0)
+ (twox ? numchans/2 : numchans)),
+ d_updated(false), d_numchans(numchans), d_state(0)
{
// set up 2x multiplier; if twox==True, set to 2, otherwise to 1
d_twox = (twox ? 2 : 1);
@@ -56,12 +56,12 @@ namespace gr {
throw std::invalid_argument("pfb_synthesizer_ccf: number of channels must be even for 2x oversampling.\n");
}
- d_filters = std::vector<kernel::fir_filter_with_buffer_ccf*>(d_twox*d_numchans);
- d_channel_map.resize(d_twox*d_numchans);
+ d_filters = std::vector<kernel::fir_filter_with_buffer_ccf*>(d_numchans);
+ d_channel_map.resize(d_numchans);
// Create a FIR filter for each channel and zero out the taps
- std::vector<float> vtaps(0, d_twox*d_numchans);
- for(unsigned int i = 0; i < d_twox*d_numchans; i++) {
+ std::vector<float> vtaps(0, d_numchans);
+ for(unsigned int i = 0; i < d_numchans; i++) {
d_filters[i] = new kernel::fir_filter_with_buffer_ccf(vtaps);
d_channel_map[i] = i;
}
@@ -70,15 +70,15 @@ namespace gr {
set_taps(taps);
// Create the IFFT to handle the input channel rotations
- d_fft = new fft::fft_complex(d_twox*d_numchans, false);
- memset(d_fft->get_inbuf(), 0, d_twox*d_numchans*sizeof(gr_complex));
+ d_fft = new fft::fft_complex(d_numchans, false);
+ memset(d_fft->get_inbuf(), 0, d_numchans*sizeof(gr_complex));
set_output_multiple(d_numchans);
}
pfb_synthesizer_ccf_impl::~pfb_synthesizer_ccf_impl()
{
- for(unsigned int i = 0; i < d_twox*d_numchans; i++) {
+ for(unsigned int i = 0; i < d_numchans; i++) {
delete d_filters[i];
}
}
@@ -137,11 +137,11 @@ namespace gr {
unsigned int i,j;
int state = 0;
- unsigned int ntaps = taps.size();
+ unsigned int ntaps = 2*taps.size();
d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans);
// Create d_numchan vectors to store each channel's taps
- d_taps.resize(d_twox*d_numchans);
+ d_taps.resize(d_numchans);
// Make a vector of the taps plus fill it out with 0's to fill
// each polyphase filter with exactly d_taps_per_filter
@@ -152,29 +152,30 @@ namespace gr {
}
// Partition the filter
- for(i = 0; i < d_numchans; i++) {
+ unsigned int halfchans = d_numchans/2;
+ for(i = 0; i < halfchans; i++) {
// Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
d_taps[i] = std::vector<float>(d_taps_per_filter, 0);
- d_taps[d_numchans+i] = std::vector<float>(d_taps_per_filter, 0);
+ d_taps[halfchans+i] = std::vector<float>(d_taps_per_filter, 0);
state = 0;
for(j = 0; j < d_taps_per_filter; j++) {
// add taps to channels in reverse order
// Zero out every other tap
if(state == 0) {
- d_taps[i][j] = tmp_taps[i + j*d_numchans];
- d_taps[d_numchans + i][j] = 0;
+ d_taps[i][j] = tmp_taps[i + j*halfchans];
+ d_taps[halfchans + i][j] = 0;
state = 1;
}
else {
d_taps[i][j] = 0;
- d_taps[d_numchans + i][j] = tmp_taps[i + j*d_numchans];
+ d_taps[halfchans + i][j] = tmp_taps[i + j*halfchans];
state = 0;
}
}
// Build a filter for each channel and add it's taps to it
d_filters[i]->set_taps(d_taps[i]);
- d_filters[d_numchans + i]->set_taps(d_taps[d_numchans + i]);
+ d_filters[halfchans + i]->set_taps(d_taps[halfchans + i]);
}
}
@@ -182,7 +183,7 @@ namespace gr {
pfb_synthesizer_ccf_impl::print_taps()
{
unsigned int i, j;
- for(i = 0; i < d_twox*d_numchans; i++) {
+ for(i = 0; i < d_numchans; i++) {
printf("filter[%d]: [", i);
for(j = 0; j < d_taps_per_filter; j++) {
printf(" %.4e", d_taps[i][j]);
@@ -204,13 +205,13 @@ namespace gr {
if(map.size() > 0) {
unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end());
- if(max >= d_twox*d_numchans) {
+ if(max >= d_numchans) {
throw std::invalid_argument("gr_pfb_synthesizer_ccf::set_channel_map: map range out of bounds.\n");
}
d_channel_map = map;
// Zero out fft buffer so that unused channels are always 0
- memset(d_fft->get_inbuf(), 0,d_twox*d_numchans*sizeof(gr_complex));
+ memset(d_fft->get_inbuf(), 0, d_numchans*sizeof(gr_complex));
}
}
@@ -258,7 +259,8 @@ namespace gr {
// Algorithm for oversampling by 2x
else {
- for(n = 0; n < noutput_items/d_numchans; n++) {
+ unsigned int halfchans = d_numchans/2;
+ for(n = 0; n < noutput_items/halfchans; n++) {
for(i = 0; i < ninputs; i++) {
in = (gr_complex*)input_items[i];
d_fft->get_inbuf()[d_channel_map[i]] = in[n];
@@ -270,13 +272,13 @@ namespace gr {
// Output is sum of two filters, but the input buffer to the filters must be circularly
// shifted by numchans every time through, done by using d_state to determine which IFFT
// buffer position to pull from.
- for(i = 0; i < d_numchans; i++) {
- out[i] = d_filters[i]->filter(d_fft->get_outbuf()[d_state*d_numchans+i]);
- out[i] += d_filters[d_numchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*d_numchans+i]);
+ for(i = 0; i < halfchans; i++) {
+ out[i] = d_filters[i]->filter(d_fft->get_outbuf()[d_state*halfchans+i]);
+ out[i] += d_filters[halfchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*halfchans+i]);
}
d_state ^= 1;
- out += d_numchans;
+ out += halfchans;
}
}