polyphaseResample.cpp 1.87 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
#include "polyphaseResample.h"
#include <iostream>
#include <stdio.h>
using namespace std;

// table_len should be decied by the length of the filter output
// but a default value of 50000 is adequate for our app
void buildPolyphaseCache(const int P, const int Q, int *&branch_table, int *&offset_table, const int table_len) {
	branch_table = new int[table_len];
	offset_table = new int[table_len];
	for (int i = 0; i < table_len; ++i) {
		branch_table[i] = (i * Q) % P;
		offset_table[i] = (i * Q - branch_table[i]) / P;
	}
}

void polyphaseResample(short *in_data, unsigned int in_sample_count,
		short *out_data, unsigned int out_sample_count,
		short *filter_coeff, unsigned int filter_len,
		const int P, const int Q, const unsigned int fix_shift,
		int *branch_table, int *offset_table) {
	buildPolyphaseCache( P, Q, branch_table, offset_table, 50000);
	// calculate the sample count of output
	out_sample_count = (int)(in_sample_count * (float)P / (float)Q);

	short *output_ptr = out_data;
	unsigned int output_ix = 0;
	short const *input_end = in_data + in_sample_count * 2;
	short const *output_end = out_data + out_sample_count * 2;
	short const *filter_end = filter_coeff + filter_len;
	while (output_ptr < output_end) 
	{
		int output_branch = branch_table[output_ix];
		int input_offset = offset_table[output_ix];

		short *input_ptr = in_data + 2 * input_offset;
		short *filter_ptr = filter_coeff + output_branch;

		while (input_ptr >= input_end) {
			input_ptr -= 2;
			filter_ptr += P;
		}

		int sum_real = 0, sum_imag = 0;
		while ((input_ptr >= in_data) && (filter_ptr < filter_end)) {
			sum_real += (int)(*input_ptr) * (int)(*filter_ptr);
			sum_imag += (int)(*(input_ptr + 1)) * (int)(*filter_ptr);
			input_ptr -= 2;
			filter_ptr += P;
		}

		*output_ptr = (short)(sum_real >> fix_shift);
		*(output_ptr + 1) = (short)(sum_imag >> fix_shift);

		output_ptr += 2;
		output_ix++;
	}
}