Statistics
| Branch: | Tag: | Revision:

root / gnuradio-core / src / lib / filter / gr_pfb_arb_resampler_ccf.cc @ a151e3e1

History | View | Annotate | Download (6.6 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2009,2010 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 <gr_pfb_arb_resampler_ccf.h>
28
#include <gr_fir_ccf.h>
29
#include <gr_fir_util.h>
30
#include <gr_io_signature.h>
31
#include <cstdio>
32
33
gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, 
34
                                                             const std::vector<float> &taps,
35
                                                             unsigned int filter_size)
36
{
37
  return gnuradio::get_initial_sptr(new gr_pfb_arb_resampler_ccf (rate, taps,
38
                                                                  filter_size));
39
}
40
41
42
gr_pfb_arb_resampler_ccf::gr_pfb_arb_resampler_ccf (float rate, 
43
                                                    const std::vector<float> &taps,
44
                                                    unsigned int filter_size)
45
  : gr_block ("pfb_arb_resampler_ccf",
46
              gr_make_io_signature (1, 1, sizeof(gr_complex)),
47
              gr_make_io_signature (1, 1, sizeof(gr_complex))),
48
    d_updated (false)
49
{
50
  d_acc = 0; // start accumulator at 0
51
52
  /* The number of filters is specified by the user as the filter size;
53
     this is also the interpolation rate of the filter. We use it and the
54
     rate provided to determine the decimation rate. This acts as a
55
     rational resampler. The flt_rate is calculated as the residual
56
     between the integer decimation rate and the real decimation rate and
57
     will be used to determine to interpolation point of the resampling
58
     process.
59
  */
60
  d_int_rate = filter_size;
61
  set_rate(rate);
62
63
  // Store the last filter between calls to work
64
  d_last_filter = 0;
65
66
  d_start_index = 0;
67
  
68
  d_filters = std::vector<gr_fir_ccf*>(d_int_rate);
69
  d_diff_filters = std::vector<gr_fir_ccf*>(d_int_rate);
70
71
  // Create an FIR filter for each channel and zero out the taps
72
  std::vector<float> vtaps(0, d_int_rate);
73
  for(unsigned int i = 0; i < d_int_rate; i++) {
74
    d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
75
    d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
76
  }
77
78
  // Now, actually set the filters' taps
79
  std::vector<float> dtaps;
80
  create_diff_taps(taps, dtaps);
81
  create_taps(taps, d_taps, d_filters);
82
  create_taps(dtaps, d_dtaps, d_diff_filters);
83
}
84
85
gr_pfb_arb_resampler_ccf::~gr_pfb_arb_resampler_ccf ()
86
{
87
  for(unsigned int i = 0; i < d_int_rate; i++) {
88
    delete d_filters[i];
89
  }
90
}
91
92
void
93
gr_pfb_arb_resampler_ccf::create_taps (const std::vector<float> &newtaps,
94
                                       std::vector< std::vector<float> > &ourtaps,
95
                                       std::vector<gr_fir_ccf*> &ourfilter)
96
{
97
  unsigned int ntaps = newtaps.size();
98
  d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate);
99
100
  // Create d_numchan vectors to store each channel's taps
101
  ourtaps.resize(d_int_rate);
102
  
103
  // Make a vector of the taps plus fill it out with 0's to fill
104
  // each polyphase filter with exactly d_taps_per_filter
105
  std::vector<float> tmp_taps;
106
  tmp_taps = newtaps;
107
  while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) {
108
    tmp_taps.push_back(0.0);
109
  }
110
  
111
  // Partition the filter
112
  for(unsigned int i = 0; i < d_int_rate; i++) {
113
    // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
114
    ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0);
115
    for(unsigned int j = 0; j < d_taps_per_filter; j++) {
116
      ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate];
117
    }
118
    
119
    // Build a filter for each channel and add it's taps to it
120
    ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]);
121
  }
122
123
  // Set the history to ensure enough input items for each filter
124
  set_history (d_taps_per_filter + 1);
125
126
  d_updated = true;
127
}
128
129
void
130
gr_pfb_arb_resampler_ccf::create_diff_taps(const std::vector<float> &newtaps,
131
                                           std::vector<float> &difftaps)
132
{
133
  // Calculate the differential taps (derivative filter) by taking the difference
134
  // between two taps. Duplicate the last one to make both filters the same length.
135
  float tap;
136
  difftaps.clear();
137
  for(unsigned int i = 0; i < newtaps.size()-1; i++) {
138
    tap = newtaps[i+1] - newtaps[i];
139
    difftaps.push_back(tap);
140
  }
141
  difftaps.push_back(tap);
142
}
143
144
void
145
gr_pfb_arb_resampler_ccf::print_taps()
146
{
147
  unsigned int i, j;
148
  for(i = 0; i < d_int_rate; i++) {
149
    printf("filter[%d]: [", i);
150
    for(j = 0; j < d_taps_per_filter; j++) {
151
      printf(" %.4e", d_taps[i][j]);
152
    }
153
    printf("]\n");
154
  }
155
}
156
157
int
158
gr_pfb_arb_resampler_ccf::general_work (int noutput_items,
159
                                        gr_vector_int &ninput_items,
160
                                        gr_vector_const_void_star &input_items,
161
                                        gr_vector_void_star &output_items)
162
{
163
  gr_complex *in = (gr_complex *) input_items[0];
164
  gr_complex *out = (gr_complex *) output_items[0];
165
166
  if (d_updated) {
167
    d_updated = false;
168
    return 0;                     // history requirements may have changed.
169
  }
170
171
  int i = 0, count = d_start_index;
172
  unsigned int j;
173
  gr_complex o0, o1;
174
175
  // Restore the last filter position
176
  j = d_last_filter;
177
178
  // produce output as long as we can and there are enough input samples
179
  int max_input = ninput_items[0]-(int)d_taps_per_filter;
180
  while((i < noutput_items) && (count < max_input)) {
181
    // start j by wrapping around mod the number of channels
182
    while((j < d_int_rate) && (i < noutput_items)) {
183
      // Take the current filter and derivative filter output
184
      o0 = d_filters[j]->filter(&in[count]);
185
      o1 = d_diff_filters[j]->filter(&in[count]);
186
187
      out[i] = o0 + o1*d_acc;     // linearly interpolate between samples
188
      i++;
189
190
      // Adjust accumulator and index into filterbank
191
      d_acc += d_flt_rate;
192
      j += d_dec_rate + (int)floor(d_acc);
193
      d_acc = fmodf(d_acc, 1.0);
194
    }
195
    if(i < noutput_items) {              // keep state for next entry
196
      float ss = (int)(j / d_int_rate);  // number of items to skip ahead by
197
      count += ss;                       // we have fully consumed another input
198
      j = j % d_int_rate;                // roll filter around
199
    }
200
  }
201
202
  // Store the current filter position and start of next sample
203
  d_last_filter = j;
204
  d_start_index = std::max(0, count - ninput_items[0]);
205
206
  // consume all we've processed but no more than we can
207
  consume_each(std::min(count, ninput_items[0]));
208
  return i;
209
}