35 #include <boost/format.hpp> 37 static void bindump(
char * fn, std::complex<float> * buf,
unsigned int num_elts,
int append = 0) __attribute__ ((unused));
38 static
void bindump(
char * fn,
std::complex<
float> * buf,
unsigned int num_elts,
int append)
48 for(i = 0; i < num_elts; i++) {
49 fprintf(of,
"%d %g %g\n", i + (append * num_elts), buf[i].real(), buf[i].imag());
54 static void bindump_2(
char * fn, std::complex<float> * buf,
unsigned int num_elts,
unsigned int num_cols) __attribute__ ((unused));
55 static void bindump_2(
char * fn, std::complex<float> * buf,
unsigned int num_elts,
unsigned int num_cols)
60 for(i = 0; i < num_elts; i++) {
61 fprintf(of,
"%d ", i);
62 for(j = 0; j < num_cols; j++) {
63 fprintf(of,
"%g %g ", buf[i * num_cols + j].real(), buf[i * num_cols + j].imag());
70 static unsigned int ipow(
unsigned int a,
unsigned int b)
75 for(i = 0; i < b; i++) {
83 unsigned int decimate_ratio,
85 unsigned int _filter_len)
89 iM = interpolate_ratio;
100 unsigned int N_guess, N_best, E_best;
104 for(i = 1; i <= 0xff; i++) {
105 unsigned int a = i & 0xf;
106 unsigned int b = (i >> 4) & 0x3;
107 unsigned int c = (i >> 6) & 0x3;
109 if(N_guess >= (
M +
Q - 1)) {
110 unsigned slop = N_guess - (
M +
Q - 1);
129 inbuf = (std::complex<float> *) fftwf_alloc_complex(
N);
131 in_fft = (std::complex<float> *) fftwf_alloc_complex(
N);
134 for(i = 0; i < N; i++) inbuf[i] = std::complex<float>(0.0,0.0);
139 c_filt =
new std::complex<float>*[
iM];
140 for(i = 0; i <
iM; i++) {
141 c_filt[i] = (std::complex<float> *) fftwf_alloc_complex(
N);
145 filt_fft = (std::complex<float> *) fftwf_alloc_complex(iM*
N);
147 interp_res = (std::complex<float> *) fftwf_alloc_complex(iM*N);
151 (fftwf_complex *) inbuf,
153 FFTW_FORWARD, FFTW_ESTIMATE);
160 (fftwf_complex *)
filt_fft, NULL, iM, 1,
162 FFTW_BACKWARD, FFTW_ESTIMATE);
175 if((fN & 1) == 0) fN--;
177 unsigned int i, j, k;
183 float cutdown = ((float) ((
iM >
dN) ?
iM :
dN));
184 beta = 1.0 / (2.2 * cutdown);
188 float f1 = (1.0 - alpha) * beta;
189 float f2 = (1.0 + alpha) * beta;
190 float tau = 0.5 / alpha;
193 std::complex<float> * filt_FD = (std::complex<float>*) fftwf_alloc_complex(
N);
194 std::complex<float> * filt_td = (std::complex<float>*) fftwf_alloc_complex(
N);
195 std::complex<float> * filt_td2 = (std::complex<float>*) fftwf_alloc_complex(
N);
198 float f_incr = 1.0 / ((float) (
N));
199 unsigned int hlim = (
N);
200 float gain_corr = 1.0 / ((float) hlim);
202 for(i = 0, f = 0.0; i <= hlim / 2; i++, f += f_incr) {
204 filt_FD[i] = std::complex<float>(1.0, 0.0);
207 float h = 0.5 * (1.0 + cos(M_PI * tau * (f - f1) / beta));
208 filt_FD[i] = std::complex<float>(h, 0.0);
211 filt_FD[i] = std::complex<float>(0.0, 0.0);
214 filt_FD[i] *= tau * gain_corr;
216 if(i != 0) filt_FD[hlim - i] = filt_FD[i];
220 fftwf_plan filt_ifft_plan = fftwf_plan_dft_1d(hlim,
221 (fftwf_complex *) filt_FD,
222 (fftwf_complex *) filt_td,
223 FFTW_BACKWARD, FFTW_ESTIMATE);
224 fftwf_execute(filt_ifft_plan);
227 for(i = 0; i < hlim; i++) sum += filt_td[i].real();
229 float sgain = 1.0 / sum;
230 for(i = 0; i < hlim; i++) filt_td[i] *= sgain;
232 fftwf_destroy_plan(filt_ifft_plan);
236 for(i = 0; i <
N; i++) {
237 filt_td2[i] = std::complex<float>(0.0,0.0);
241 for(i = 0, j = N - (filter_len/2); j <
N; i++, j++) {
242 filt_td2[i] = filt_td[j];
244 for(j = 0; j < filter_len / 2; j++, i++) {
245 filt_td2[i] = filt_td[j];
251 for(i = 0; i <
iM; i++) {
255 filt_td[k] = filt_td2[j];
257 for(; k < N; k++) filt_td[k] = std::complex<float>(0.0,0.0);
258 fftwf_plan filt_fft_plan = fftwf_plan_dft_1d(N,
259 (fftwf_complex *) filt_td,
260 (fftwf_complex *)
c_filt[i],
261 FFTW_FORWARD, FFTW_ESTIMATE);
262 fftwf_execute(filt_fft_plan);
263 fftwf_destroy_plan(filt_fft_plan);
267 fftwf_free(filt_td2);
273 std::complex<float> * out,
278 memcpy(&(
inbuf[
Q-1]), in,
sizeof(std::complex<float>) *
M);
284 for(i = 0; i <
N; i++) {
285 for(j = 0; j <
iM; j++) {
302 unsigned int mctr = 0;
303 unsigned int out_lim = (M *
iM) /
dN;
304 std::complex<float> * ir_clean = &(
interp_res[(
Q-1)]);
307 for(j = 0; j < out_lim; j++) {
328 for(i = 0; i <
M; i++) {
329 inbuf[i+(
Q-1)] = std::complex<float>(in[i], 0.0);
336 for(i = 0; i <
N; i++) {
337 for(j = 0; j <
iM; j++) {
348 for(i = 0; i < (
Q-1); i++) {
356 unsigned int mctr = 0;
357 unsigned int out_lim = (M *
iM) /
dN;
358 std::complex<float> * ir_clean = &(
interp_res[(
Q-1)]);
359 for(j = 0; j < out_lim; j++) {
std::complex< float > * inbuf
the fft input buffer
std::complex< float > ** c_filt
filter bank for interp/deci filter
static void bindump_2(char *fn, std::complex< float > *buf, unsigned int num_elts, unsigned int num_cols) __attribute__((unused))
void CreateFilter(unsigned int filter_len)
create a filter bank for a polyphase resampler.
std::complex< float > * in_fft
the result of the first fft stage
int filter_len
the length of the polyphase filter that we're using.
static unsigned int ipow(unsigned int a, unsigned int b)
ReSampler(unsigned int interp_ratio, unsigned int decim_ratio, unsigned int _inlen, unsigned int filter_len)
Constructor.
std::complex< float > * filt_fft
the filtered image of the input stream
std::complex< float > * interp_res
the interpolation result
static void bindump(char *fn, std::complex< float > *buf, unsigned int num_elts, int append=0) __attribute__((unused))
unsigned int apply(std::complex< float > *in, std::complex< float > *out, float gain=1.0)
apply the resampler to a buffer of IQ samples.