~ubuntu-branches/ubuntu/trusty/gnuradio/trusty-updates

« back to all changes in this revision

Viewing changes to gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc

  • Committer: Package Import Robot
  • Author(s): A. Maitland Bottoms
  • Date: 2012-02-26 21:26:16 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20120226212616-vsfkbi1158xshdql
Tags: 3.5.1-1
* new upstream version, re-packaged from scratch with modern tools
    closes: #642716, #645332, #394849, #616832, #590048, #642580,
    #647018, #557050, #559640, #631863
* CMake build

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}