From 9bc1a4761171b27a2e3854967662039118ba5e6c Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Tue, 22 Jan 2013 17:18:14 +0100 Subject: [PATCH 1/1] Initial checkin for move to Git (no prior version history available). --- qmfsplit.cpp | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 qmfsplit.cpp diff --git a/qmfsplit.cpp b/qmfsplit.cpp new file mode 100644 index 0000000..7d94df2 --- /dev/null +++ b/qmfsplit.cpp @@ -0,0 +1,208 @@ +#include +#include + +FILE *in; + +//double coeffs[] = { 0.6830127, 1.1830127, 0.3169873, -0.1830127 }; +//double coeffs[] = { 0.47046721, 1.14111692, 0.650365, -0.19093442, -0.12083221, 0.0498175 }; +double coeffs[] = { 0.22641898, 0.85394354, 1.02432694, 0.19576696, -0.34265671, -0.04560113, 0.10970265, -0.00882680, -0.01779187, 4.71742793e-3 }; +//double coeffs[] = { 0.03771716, 0.26612218, 0.74557507, 0.97362811, 0.39763774, -0.35333620, -0.27710988, 0.18012745, 0.13160299, -0.10096657, -0.04165925, 0.04696981, 5.10043697e-3, -0.01517900, 1.97332536e-3, 2.81768659e-3, -9.69947840e-4, -1.64709006e-4, 1.32354367e-4, -1.875841e-5 }; + +#define NUM_COEFF (sizeof(coeffs)/sizeof(coeffs[0])) +#define FILTER_LAG (NUM_COEFF - 2) + +double read_sample() +{ + short x; + if (fread(&x, 2, 1, in) != 1) { + exit(0); + } + return x; +} + +short trunc_short(double x) +{ + if (x >= 32767.0) { + return 32767; + } else if (x <= -32768.0) { + return -32768; + } else { + return short(x); + } +} + +void write_sample(double x) +{ + short s = trunc_short(x * 0.5); + if (fwrite(&s, 2, 1, stdout) != 1) { + perror("fwrite"); + exit(1); + } +} + +double filter_lo(double *s) { + double acc = 0.0; + for (unsigned i = 0; i < NUM_COEFF; ++i) { + acc += s[i] * coeffs[i]; + } + return acc; +} + +double filter_hi(double *s) { + double acc = 0.0; + for (unsigned i = 0; i < NUM_COEFF; i += 2) { + acc += s[i] * coeffs[NUM_COEFF - i - 1]; + acc -= s[i + 1] * coeffs[NUM_COEFF - i - 2]; + } + return acc; +} + +void inv_filter(double *dst, double *src_lo, double *src_hi) +{ + // first sample + { + double c1 = 0.0, c2 = 0.0; + for (unsigned i = 0; i < NUM_COEFF/2; ++i) { + c1 += src_lo[i] * coeffs[NUM_COEFF - (i*2 + 1) - 1]; + c2 += src_hi[i] * coeffs[i*2 + 1]; + } + dst[0] = 0.5*(c1+c2); + } + + // second sample + { + double c1 = 0.0, c2 = 0.0; + for (unsigned i = 0; i < NUM_COEFF/2; ++i) { + c1 += src_lo[i] * coeffs[NUM_COEFF - i*2 - 1]; + c2 += src_hi[i] * coeffs[i*2]; + } + dst[1] = 0.5*(c1-c2); + } +} + +void filter_lo_series(double *dst, double *src, unsigned len) +{ + for (unsigned i = 0; i < FILTER_LAG; ++i) { + dst[i] = dst[len + i]; + } + for (unsigned i = 0; i < len; ++i) { + dst[i + FILTER_LAG] = filter_lo(src + i*2); + } +} + +void filter_hi_series(double *dst, double *src, unsigned len) +{ + for (unsigned i = 0; i < FILTER_LAG; ++i) { + dst[i] = dst[len + i]; + } + for (unsigned i = 0; i < len; ++i) { + dst[i + FILTER_LAG] = filter_hi(src + i*2); + } +} + +int main(int argc, char **argv) +{ + in = fopen(argv[1], "rb"); + + double s0[(1 << 4) + FILTER_LAG] = {0}; // 18 + double s1[2][(1 << 3) + FILTER_LAG] = {{0}}; // 10 + double s2[4][(1 << 2) + FILTER_LAG] = {{0}}; // 6 + double s3[8][(1 << 1) + FILTER_LAG] = {{0}}; // 4 + double s4[16][1 + FILTER_LAG/2] = {{0}}; // 2 + double u3[8][(1 << 1) + FILTER_LAG/2] = {{0}}; // 3 + double u2[4][(1 << 2) + FILTER_LAG/2] = {{0}}; // 5 + double u1[2][(1 << 3) + FILTER_LAG/2] = {{0}}; // 9 + double u0[1 << 4] = {0}; // 16 + + for ( ;; ) { + // Input (one band) + for (unsigned i = 0; i < FILTER_LAG; ++i) { + s0[i] = s0[(1 << 4) + i]; + } + for (unsigned i = 0; i < (1 << 4); ++i) { + s0[i + FILTER_LAG] = read_sample(); + } + + // First level (two bands) + filter_lo_series(s1[0], s0, (1 << 3)); + filter_hi_series(s1[1], s0, (1 << 3)); + + // Second level (four bands) + for (unsigned i = 0; i < 2; ++i) { + filter_lo_series(s2[i * 2], s1[i], (1 << 2)); + filter_hi_series(s2[i * 2 + 1], s1[i], (1 << 2)); + } + + // Third level (eight bands) + for (unsigned i = 0; i < 4; ++i) { + filter_lo_series(s3[i * 2], s2[i], (1 << 1)); + filter_hi_series(s3[i * 2 + 1], s2[i], (1 << 1)); + } + + // Fourth level (sixteen bands) + for (unsigned i = 0; i < 8; ++i) { + for (unsigned j = 0; j < FILTER_LAG/2; ++j) { + s4[i * 2][j] = s4[i * 2][j + 1]; + s4[i * 2 + 1][j] = s4[i * 2 + 1][j + 1]; + } + s4[i * 2][FILTER_LAG/2] = filter_lo(s3[i]); + s4[i * 2 + 1][FILTER_LAG/2] = filter_hi(s3[i]); + } + + // COMPRESS HERE (based on s4[0..15][FILTER_LAG/2]) + for (unsigned i = 0; i < 16; ++i) { + if (i != 0) + s4[i][FILTER_LAG/2] = 0.0f; + } + + // Third level (eight bands) + for (unsigned i = 0; i < 8; ++i) { + for (unsigned j = 0; j < FILTER_LAG/2; ++j) { + u3[i][j] = u3[i][j + 2]; + } + inv_filter(u3[i] + FILTER_LAG/2, s4[i * 2], s4[i * 2 + 1]); + } + + // Second level (four bands) + for (unsigned i = 0; i < 4; ++i) { + for (unsigned j = 0; j < FILTER_LAG/2; ++j) { + u2[i][j] = u2[i][j + 4]; + } + for (unsigned j = 0; j < 2; ++j) { + inv_filter(u2[i] + j*2 + FILTER_LAG/2, u3[i * 2] + j, u3[i * 2 + 1] + j); + } + } + + // First level (two bands) + for (unsigned i = 0; i < 2; ++i) { + for (unsigned j = 0; j < FILTER_LAG/2; ++j) { + u1[i][j] = u1[i][j + 8]; + } + for (unsigned j = 0; j < 4; ++j) { + inv_filter(u1[i] + j*2 + FILTER_LAG/2, u2[i * 2] + j, u2[i * 2 + 1] + j); + } + } + + // Output data + for (unsigned j = 0; j < 8; ++j) { + inv_filter(u0 + j*2, u1[0] + j, u1[1] + j); + } + + for (unsigned j = 0; j < 16; ++j) { + write_sample(u0[j]); + } + +#if 0 + // DEBUG + printf("IN: "); + for (unsigned j = 2; j < 18; ++j) { + printf("%f ", s0[j]); + } + printf("\nOUT: "); + for (unsigned j = 0; j < 16; ++j) { + printf("%f ", u0[j]); + } + printf("\n\n"); +#endif + } +} -- 2.39.2