summaryrefslogtreecommitdiffstats
path: root/sys/tools/feeder_rate_mkfilter.awk
diff options
context:
space:
mode:
Diffstat (limited to 'sys/tools/feeder_rate_mkfilter.awk')
-rw-r--r--sys/tools/feeder_rate_mkfilter.awk767
1 files changed, 767 insertions, 0 deletions
diff --git a/sys/tools/feeder_rate_mkfilter.awk b/sys/tools/feeder_rate_mkfilter.awk
new file mode 100644
index 0000000..898c737
--- /dev/null
+++ b/sys/tools/feeder_rate_mkfilter.awk
@@ -0,0 +1,767 @@
+#!/usr/bin/awk -f
+#
+# Copyright (c) 2007-2009 Ariff Abdullah <ariff@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#
+# FIR filter design by windowing method. This might become one of the
+# funniest joke I've ever written due to too many tricks being applied to
+# ensure maximum precision (well, in fact this is already have the same
+# precision granularity compared to its C counterpart). Nevertheless, it's
+# working, precise, dynamically tunable based on "presets".
+#
+# XXX EXPECT TOTAL REWRITE! DON'T ARGUE!
+#
+# TODO: Using ultraspherical window might be a good idea.
+#
+# Based on:
+#
+# "Digital Audio Resampling" by Julius O. Smith III
+#
+# - http://ccrma.stanford.edu/~jos/resample/
+#
+
+#
+# Some basic Math functions.
+#
+function abs(x)
+{
+ return (((x < 0) ? -x : x) + 0);
+}
+
+function fabs(x)
+{
+ return (((x < 0.0) ? -x : x) + 0.0);
+}
+
+function ceil(x, r)
+{
+ r = int(x);
+ if (r < x)
+ r++;
+ return (r + 0);
+}
+
+function floor(x, r)
+{
+ r = int(x);
+ if (r > x)
+ r--;
+ return (r + 0);
+}
+
+function pow(x, y)
+{
+ return (exp(1.0 * y * log(1.0 * x)));
+}
+
+#
+# What the hell...
+#
+function shl(x, y)
+{
+ while (y > 0) {
+ x *= 2;
+ y--;
+ }
+ return (x);
+}
+
+function shr(x, y)
+{
+ while (y > 0 && x != 0) {
+ x = floor(x / 2);
+ y--;
+ }
+ return (x);
+}
+
+function fx_floor(v, o, r)
+{
+ if (fabs(v) < fabs(smallest))
+ smallest = v;
+ if (fabs(v) > fabs(largest))
+ largest = v;
+
+ r = floor((v * o) + 0.5);
+ if (r < INT32_MIN || r > INT32_MAX)
+ printf("\n#error overflow v=%f, please reduce %d\n", v, o);
+
+ return (r);
+}
+
+#
+# Kaiser linear piecewise functions.
+#
+function kaiserAttn2Beta(attn, beta)
+{
+ if (attn < 0.0)
+ return (Z_KAISER_BETA_DEFAULT);
+
+ if (attn > 50.0)
+ beta = 0.1102 * ((1.0 * attn) - 8.7);
+ else if (attn > 21.0)
+ beta = (0.5842 * pow((1.0 * attn) - 21.0, 0.4)) + \
+ (0.07886 * ((1.0 * attn) - 21.0));
+ else
+ beta = 0.0;
+
+ return (beta);
+}
+
+function kaiserBeta2Attn(beta, x, y, i, attn, xbeta)
+{
+ if (beta < Z_WINDOW_KAISER)
+ return (Z_KAISER_ATTN_DEFAULT);
+
+ if (beta > kaiserAttn2Beta(50.0))
+ attn = ((1.0 * beta) / 0.1102) + 8.7;
+ else {
+ x = 21.0;
+ y = 50.0;
+ attn = 0.5 * (x + y);
+ for (i = 0; i < 128; i++) {
+ xbeta = kaiserAttn2Beta(attn)
+ if (beta == xbeta || \
+ (i > 63 && \
+ fabs(beta - xbeta) < Z_KAISER_EPSILON))
+ break;
+ if (beta > xbeta)
+ x = attn;
+ else
+ y = attn;
+ attn = 0.5 * (x + y);
+ }
+ }
+
+ return (attn);
+}
+
+function kaiserRolloff(len, attn)
+{
+ return (1.0 - (((1.0 * attn) - 7.95) / (((1.0 * len) - 1.0) * 14.36)));
+}
+
+#
+# 0th order modified Bessel function of the first kind.
+#
+function I0(x, s, u, n, h, t)
+{
+ s = n = u = 1.0;
+ h = x * 0.5;
+
+ do {
+ t = h / n;
+ n += 1.0;
+ t *= t;
+ u *= t;
+ s += u;
+ } while (u >= (I0_EPSILON * s));
+
+ return (s);
+}
+
+function wname(beta)
+{
+ if (beta >= Z_WINDOW_KAISER)
+ return ("Kaiser");
+ else if (beta == Z_WINDOW_BLACKMAN_NUTTALL)
+ return ("Blackman - Nuttall");
+ else if (beta == Z_WINDOW_NUTTALL)
+ return ("Nuttall");
+ else if (beta == Z_WINDOW_BLACKMAN_HARRIS)
+ return ("Blackman - Harris");
+ else if (beta == Z_WINDOW_BLACKMAN)
+ return ("Blackman");
+ else if (beta == Z_WINDOW_HAMMING)
+ return ("Hamming");
+ else if (beta == Z_WINDOW_HANN)
+ return ("Hann");
+ else
+ return ("What The Hell !?!?");
+}
+
+function rolloff_round(x)
+{
+ if (x < 0.67)
+ x = 0.67;
+ else if (x > 1.0)
+ x = 1.0;
+
+ return (x);
+}
+
+function tap_round(x, y)
+{
+ y = floor(x + 3);
+ y -= y % 4;
+ return (y);
+}
+
+function lpf(imp, n, rolloff, beta, num, i, j, x, nm, ibeta, w)
+{
+ rolloff = rolloff_round(rolloff + (Z_NYQUIST_HOVER * (1.0 - rolloff)));
+ imp[0] = rolloff;
+
+ #
+ # Generate ideal sinc impulses, locate the last zero-crossing and pad
+ # the remaining with 0.
+ #
+ # Note that there are other (faster) ways of calculating this without
+ # the misery of traversing the entire sinc given the fact that the
+ # distance between each zero crossings is actually the bandwidth of
+ # the impulses, but it seems having 0.0001% chances of failure due to
+ # limited precision.
+ #
+ j = n;
+ for (i = 1; i < n; i++) {
+ x = (M_PI * i) / (1.0 * num);
+ imp[i] = sin(x * rolloff) / x;
+ if (i != 1 && (imp[i] * imp[i - 1]) <= 0.0)
+ j = i;
+ }
+
+ for (i = j; i < n; i++)
+ imp[i] = 0.0;
+
+ nm = 1.0 * (j - 1);
+
+ if (beta >= Z_WINDOW_KAISER)
+ ibeta = I0(beta);
+
+ for (i = 1; i < j; i++) {
+ if (beta >= Z_WINDOW_KAISER) {
+ # Kaiser window...
+ x = (1.0 * i) / nm;
+ w = I0(beta * sqrt(1.0 - (x * x))) / ibeta;
+ } else {
+ # Cosined windows...
+ x = (M_PI * i) / nm;
+ if (beta == Z_WINDOW_BLACKMAN_NUTTALL) {
+ # Blackman - Nuttall
+ w = 0.36335819 + (0.4891775 * cos(x)) + \
+ (0.1365995 * cos(2 * x)) + \
+ (0.0106411 * cos(3 * x));
+ } else if (beta == Z_WINDOW_NUTTALL) {
+ # Nuttall
+ w = 0.355768 + (0.487396 * cos(x)) + \
+ (0.144232 * cos(2 * x)) + \
+ (0.012604 * cos(3 * x));
+ } else if (beta == Z_WINDOW_BLACKMAN_HARRIS) {
+ # Blackman - Harris
+ w = 0.422323 + (0.49755 * cos(x)) + \
+ (0.07922 * cos(2 * x));
+ } else if (beta == Z_WINDOW_BLACKMAN) {
+ # Blackman
+ w = 0.42 + (0.50 * cos(x)) + \
+ (0.08 * cos(2 * x));
+ } else if (beta == Z_WINDOW_HAMMING) {
+ # Hamming
+ w = 0.54 + (0.46 * cos(x));
+ } else if (beta == Z_WINDOW_HANN) {
+ # Hann
+ w = 0.50 + (0.50 * cos(x));
+ } else {
+ # What The Hell !?!?
+ w = 0.0;
+ }
+ }
+ imp[i] *= w;
+ }
+
+ imp["impulse_length"] = j;
+ imp["rolloff"] = rolloff;
+}
+
+function mkfilter(imp, nmult, rolloff, beta, num, \
+ nwing, mwing, nrolloff, i, dcgain, v, quality)
+{
+ nwing = floor((nmult * num) / 2) + 1;
+
+ lpf(imp, nwing, rolloff, beta, num);
+
+ mwing = imp["impulse_length"];
+ nrolloff = imp["rolloff"];
+ quality = imp["quality"];
+
+ dcgain = 0.0;
+ for (i = num; i < mwing; i += num)
+ dcgain += imp[i];
+ dcgain *= 2.0;
+ dcgain += imp[0];
+
+ for (i = 0; i < nwing; i++)
+ imp[i] /= dcgain;
+
+ if (quality > 2)
+ printf("\n");
+ printf("/*\n");
+ printf(" * quality = %d\n", quality);
+ printf(" * window = %s\n", wname(beta));
+ if (beta >= Z_WINDOW_KAISER) {
+ printf(" * beta: %.2f\n", beta);
+ printf(" * stop: -%.2f dB\n", \
+ kaiserBeta2Attn(beta));
+ }
+ printf(" * length = %d\n", nmult);
+ printf(" * bandwidth = %.2f%%", rolloff * 100.0);
+ if (rolloff != nrolloff) {
+ printf(" + %.2f%% = %.2f%% (nyquist hover: %.2f%%)", \
+ (nrolloff - rolloff) * 100.0, nrolloff * 100.0, \
+ Z_NYQUIST_HOVER * 100.0);
+ }
+ printf("\n");
+ printf(" * drift = %d\n", num);
+ printf(" * width = %d\n", mwing);
+ printf(" */\n");
+ printf("static int32_t z_coeff_q%d[%d] = {", \
+ quality, nwing + (Z_COEFF_OFFSET * 2));
+ for (i = 0; i < (nwing + (Z_COEFF_OFFSET * 2)); i++) {
+ if ((i % 5) == 0)
+ printf("\n ");
+ if (i < Z_COEFF_OFFSET)
+ v = fx_floor(imp[Z_COEFF_OFFSET - i], Z_COEFF_ONE);
+ else if ((i - Z_COEFF_OFFSET) >= nwing)
+ v = fx_floor( \
+ imp[nwing + nwing - i + Z_COEFF_OFFSET - 1],\
+ Z_COEFF_ONE);
+ else
+ v = fx_floor(imp[i - Z_COEFF_OFFSET], Z_COEFF_ONE);
+ printf(" %s0x%08x,", (v < 0) ? "-" : " ", abs(v));
+ }
+ printf("\n};\n\n");
+ printf("/*\n");
+ printf(" * interpolated q%d differences.\n", quality);
+ printf(" */\n");
+ printf("static int32_t z_dcoeff_q%d[%d] = {", quality, nwing);
+ for (i = 1; i <= nwing; i++) {
+ if ((i % 5) == 1)
+ printf("\n ");
+ v = -imp[i - 1];
+ if (i != nwing)
+ v += imp[i];
+ v = fx_floor(v, Z_INTERP_COEFF_ONE);
+ if (abs(v) > abs(largest_interp))
+ largest_interp = v;
+ printf(" %s0x%08x,", (v < 0) ? "-" : " ", abs(v));
+ }
+ printf("\n};\n");
+
+ return (nwing);
+}
+
+function filter_parse(s, a, i, attn, alen)
+{
+ split(s, a, ":");
+ alen = length(a);
+
+ if (alen == 1 || alen == 2) {
+ if (a[1] == "nyquist_hover") {
+ i = 1.0 * a[2];
+ Z_NYQUIST_HOVER = (i > 0.0 && i < 1.0) ? i : 0.0;
+ return (-1);
+ }
+ i = 1;
+ if (alen == 1) {
+ attn = Z_KAISER_ATTN_DEFAULT;
+ Popts["beta"] = Z_KAISER_BETA_DEFAULT;
+ } else if (Z_WINDOWS[a[1]] < Z_WINDOW_KAISER) {
+ Popts["beta"] = Z_WINDOWS[a[1]];
+ i = tap_round(a[2]);
+ Popts["nmult"] = i;
+ if (i < 28)
+ i = 28;
+ i = 1.0 - (6.44 / i);
+ Popts["rolloff"] = rolloff_round(i);
+ return (0);
+ } else {
+ attn = 1.0 * a[i++];
+ Popts["beta"] = kaiserAttn2Beta(attn);
+ }
+ i = tap_round(a[i]);
+ Popts["nmult"] = i;
+ if (i > 7 && i < 28)
+ i = 27;
+ i = kaiserRolloff(i, attn);
+ Popts["rolloff"] = rolloff_round(i);
+
+ return (0);
+ }
+
+ if (!(alen == 3 || alen == 4))
+ return (-1);
+
+ i = 2;
+
+ if (a[1] == "kaiser") {
+ if (alen > 2)
+ Popts["beta"] = 1.0 * a[i++];
+ else
+ Popts["beta"] = Z_KAISER_BETA_DEFAULT;
+ } else if (Z_WINDOWS[a[1]] < Z_WINDOW_KAISER)
+ Popts["beta"] = Z_WINDOWS[a[1]];
+ else if (1.0 * a[1] < Z_WINDOW_KAISER)
+ return (-1);
+ else
+ Popts["beta"] = kaiserAttn2Beta(1.0 * a[1]);
+ Popts["nmult"] = tap_round(a[i++]);
+ if (a[1] == "kaiser" && alen == 3)
+ i = kaiserRolloff(Popts["nmult"], \
+ kaiserBeta2Attn(Popts["beta"]));
+ else
+ i = 1.0 * a[i];
+ Popts["rolloff"] = rolloff_round(i);
+
+ return (0);
+}
+
+function genscale(bit, s1, s2, scale)
+{
+ s1 = Z_COEFF_SHIFT - (32 - bit);
+ s2 = Z_SHIFT + (32 - bit);
+
+ if (s1 == 0)
+ scale = "v";
+ else if (s1 < 0)
+ scale = sprintf("(v) << %d", abs(s1));
+ else
+ scale = sprintf("(v) >> %d", s1);
+
+ scale = sprintf("(%s) * Z_SCALE_CAST(s)", scale);
+
+ if (s2 != 0)
+ scale = sprintf("(%s) >> %d", scale, s2);
+
+ printf("#define Z_SCALE_%d(v, s)\t%s(%s)\n", \
+ bit, (bit < 10) ? "\t" : "", scale);
+}
+
+function genlerp(bit, use64, lerp)
+{
+ if ((bit + Z_LINEAR_SHIFT) <= 32) {
+ lerp = sprintf("(((y) - (x)) * (z)) >> %d", Z_LINEAR_SHIFT);
+ } else if (use64 != 0) {
+ if ((bit + Z_LINEAR_SHIFT) <= 64) {
+ lerp = sprintf( \
+ "(((int64_t)(y) - (x)) * (z)) " \
+ ">> %d", \
+ Z_LINEAR_SHIFT);
+ } else {
+ lerp = sprintf( \
+ "((int64_t)((y) >> %d) - ((x) >> %d)) * ", \
+ "(z)" \
+ bit + Z_LINEAR_SHIFT - 64, \
+ bit + Z_LINEAR_SHIFT - 64);
+ if ((64 - bit) != 0)
+ lerp = sprintf("(%s) >> %d", lerp, 64 - bit);
+ }
+ } else {
+ lerp = sprintf( \
+ "(((y) >> %d) - ((x) >> %d)) * (z)", \
+ bit + Z_LINEAR_SHIFT - 32, \
+ bit + Z_LINEAR_SHIFT - 32);
+ if ((32 - bit) != 0)
+ lerp = sprintf("(%s) >> %d", lerp, 32 - bit);
+ }
+
+ printf("#define Z_LINEAR_INTERPOLATE_%d(z, x, y)" \
+ "\t\t\t\t%s\\\n\t((x) + (%s))\n", \
+ bit, (bit < 10) ? "\t" : "", lerp);
+}
+
+BEGIN {
+ I0_EPSILON = 1e-21;
+ M_PI = atan2(0.0, -1.0);
+
+ INT32_MAX = 1 + ((shl(1, 30) - 1) * 2);
+ INT32_MIN = -1 - INT32_MAX;
+
+ Z_COEFF_OFFSET = 5;
+
+ Z_FULL_SHIFT = 30;
+ Z_FULL_ONE = shl(1, Z_FULL_SHIFT);
+
+ Z_COEFF_SHIFT = 28;
+ Z_COEFF_ONE = shl(1, Z_COEFF_SHIFT);
+
+ Z_INTERP_COEFF_SHIFT = 24;
+ Z_INTERP_COEFF_ONE = shl(1, Z_INTERP_COEFF_SHIFT);
+
+ #
+ # Filter oversampling factor.
+ #
+ # 6, 7, or 8 depending on how much you can trade off between memory
+ # consumption (due to large tables) and precision / quality.
+ #
+ Z_DRIFT_SHIFT = 7;
+ Z_DRIFT_ONE = shl(1, Z_DRIFT_SHIFT);
+
+ Z_SHIFT = Z_FULL_SHIFT - Z_DRIFT_SHIFT;
+ Z_ONE = shl(1, Z_SHIFT);
+ Z_MASK = Z_ONE - 1;
+
+ Z_LINEAR_FULL_SHIFT = Z_FULL_SHIFT;
+ Z_LINEAR_FULL_ONE = shl(1, Z_LINEAR_FULL_SHIFT);
+ Z_LINEAR_SHIFT = 8;
+ Z_LINEAR_UNSHIFT = Z_LINEAR_FULL_SHIFT - Z_LINEAR_SHIFT;
+ Z_LINEAR_ONE = shl(1, Z_LINEAR_SHIFT)
+
+ # meehhhh... let it overflow...
+ #Z_SCALE_SHIFT = 31;
+ #Z_SCALE_ONE = shl(1, Z_SCALE_SHIFT);
+
+ Z_WINDOW_KAISER = 0.0;
+ Z_WINDOW_BLACKMAN_NUTTALL = -1.0;
+ Z_WINDOW_NUTTALL = -2.0;
+ Z_WINDOW_BLACKMAN_HARRIS = -3.0;
+ Z_WINDOW_BLACKMAN = -4.0;
+ Z_WINDOW_HAMMING = -5.0;
+ Z_WINDOW_HANN = -6.0;
+
+ Z_WINDOWS["blackman_nuttall"] = Z_WINDOW_BLACKMAN_NUTTALL;
+ Z_WINDOWS["nuttall"] = Z_WINDOW_NUTTALL;
+ Z_WINDOWS["blackman_harris"] = Z_WINDOW_BLACKMAN_HARRIS;
+ Z_WINDOWS["blackman"] = Z_WINDOW_BLACKMAN;
+ Z_WINDOWS["hamming"] = Z_WINDOW_HAMMING;
+ Z_WINDOWS["hann"] = Z_WINDOW_HANN;
+
+ Z_KAISER_2_BLACKMAN_BETA = 8.568611;
+ Z_KAISER_2_BLACKMAN_NUTTALL_BETA = 11.98;
+
+ Z_KAISER_ATTN_DEFAULT = 100;
+ Z_KAISER_BETA_DEFAULT = kaiserAttn2Beta(Z_KAISER_ATTN_DEFAULT);
+
+ Z_KAISER_EPSILON = 1e-21;
+
+ #
+ # This is practically a joke.
+ #
+ Z_NYQUIST_HOVER = 0.0;
+
+ smallest = 10.000000;
+ largest = 0.000010;
+ largest_interp = 0;
+
+ if (ARGC < 2) {
+ ARGC = 1;
+ ARGV[ARGC++] = "100:8:0.85";
+ ARGV[ARGC++] = "100:36:0.90";
+ ARGV[ARGC++] = "100:164:0.97";
+ #ARGV[ARGC++] = "100:8";
+ #ARGV[ARGC++] = "100:16";
+ #ARGV[ARGC++] = "100:32:0.7929";
+ #ARGV[ARGC++] = "100:64:0.8990";
+ #ARGV[ARGC++] = "100:128:0.9499";
+ }
+
+ printf("#ifndef _FEEDER_RATE_GEN_H_\n");
+ printf("#define _FEEDER_RATE_GEN_H_\n\n");
+ printf("/*\n");
+ printf(" * Generated using feeder_rate_mkfilter.awk, heaven, wind and awesome.\n");
+ printf(" *\n");
+ printf(" * DO NOT EDIT!\n");
+ printf(" */\n\n");
+ printf("#define FEEDER_RATE_PRESETS\t\"");
+ for (i = 1; i < ARGC; i++)
+ printf("%s%s", (i == 1) ? "" : " ", ARGV[i]);
+ printf("\"\n\n");
+ imp["quality"] = 2;
+ for (i = 1; i < ARGC; i++) {
+ if (filter_parse(ARGV[i]) == 0) {
+ beta = Popts["beta"];
+ nmult = Popts["nmult"];
+ rolloff = Popts["rolloff"];
+ ztab[imp["quality"] - 2] = \
+ mkfilter(imp, nmult, rolloff, beta, Z_DRIFT_ONE);
+ imp["quality"]++;
+ }
+ }
+
+ printf("\n");
+ #
+ # XXX
+ #
+ #if (length(ztab) > 0) {
+ # j = 0;
+ # for (i = 0; i < length(ztab); i++) {
+ # if (ztab[i] > j)
+ # j = ztab[i];
+ # }
+ # printf("static int32_t z_coeff_zero[%d] = {", j);
+ # for (i = 0; i < j; i++) {
+ # if ((i % 19) == 0)
+ # printf("\n");
+ # printf(" 0,");
+ # }
+ # printf("\n};\n\n");
+ #}
+ #
+ # XXX
+ #
+ printf("static const struct {\n");
+ printf("\tint32_t len;\n");
+ printf("\tint32_t *coeff;\n");
+ printf("\tint32_t *dcoeff;\n");
+ printf("} z_coeff_tab[] = {\n");
+ if (length(ztab) > 0) {
+ j = 0;
+ for (i = 0; i < length(ztab); i++) {
+ if (ztab[i] > j)
+ j = ztab[i];
+ }
+ j = length(sprintf("%d", j));
+ lfmt = sprintf("%%%dd", j);
+ j = length(sprintf("z_coeff_q%d", length(ztab) + 1));
+ zcfmt = sprintf("%%-%ds", j);
+ zdcfmt = sprintf("%%-%ds", j + 1);
+
+ for (i = 0; i < length(ztab); i++) {
+ l = sprintf(lfmt, ztab[i]);
+ zc = sprintf("z_coeff_q%d", i + 2);
+ zc = sprintf(zcfmt, zc);
+ zdc = sprintf("z_dcoeff_q%d", i + 2);
+ zdc = sprintf(zdcfmt, zdc);
+ printf("\t{ %s, %s, %s },\n", l, zc, zdc);
+ }
+ } else
+ printf("\t{ 0, NULL, NULL }\n");
+ printf("};\n\n");
+
+ #Z_UNSHIFT = 0;
+ #v = shr(Z_ONE - 1, Z_UNSHIFT) * abs(largest_interp);
+ #while (v < 0 || v > INT32_MAX) {
+ # Z_UNSHIFT += 1;
+ # v = shr(Z_ONE - 1, Z_UNSHIFT) * abs(largest_interp);
+ #}
+ v = ((Z_ONE - 1) * abs(largest_interp)) / INT32_MAX;
+ Z_UNSHIFT = ceil(log(v) / log(2.0));
+ Z_INTERP_SHIFT = Z_SHIFT - Z_UNSHIFT + Z_INTERP_COEFF_SHIFT;
+
+ Z_INTERP_UNSHIFT = (Z_SHIFT - Z_UNSHIFT) + Z_INTERP_COEFF_SHIFT \
+ - Z_COEFF_SHIFT;
+
+ printf("#define Z_COEFF_TAB_SIZE\t\t\t\t\t\t\\\n");
+ printf("\t((int32_t)(sizeof(z_coeff_tab) /");
+ printf(" sizeof(z_coeff_tab[0])))\n\n");
+ printf("#define Z_COEFF_OFFSET\t\t%d\n\n", Z_COEFF_OFFSET);
+ printf("#define Z_RSHIFT(x, y)\t\t(((x) + " \
+ "(1 << ((y) - 1))) >> (y))\n");
+ printf("#define Z_RSHIFT_L(x, y)\t(((x) + " \
+ "(1LL << ((y) - 1))) >> (y))\n\n");
+ printf("#define Z_FULL_SHIFT\t\t%d\n", Z_FULL_SHIFT);
+ printf("#define Z_FULL_ONE\t\t0x%08x%s\n", Z_FULL_ONE, \
+ (Z_FULL_ONE > INT32_MAX) ? "U" : "");
+ printf("\n");
+ printf("#define Z_DRIFT_SHIFT\t\t%d\n", Z_DRIFT_SHIFT);
+ #printf("#define Z_DRIFT_ONE\t\t0x%08x\n", Z_DRIFT_ONE);
+ printf("\n");
+ printf("#define Z_SHIFT\t\t\t%d\n", Z_SHIFT);
+ printf("#define Z_ONE\t\t\t0x%08x\n", Z_ONE);
+ printf("#define Z_MASK\t\t\t0x%08x\n", Z_MASK);
+ printf("\n");
+ printf("#define Z_COEFF_SHIFT\t\t%d\n", Z_COEFF_SHIFT);
+ zinterphp = "(z) * (d)";
+ zinterpunshift = Z_SHIFT + Z_INTERP_COEFF_SHIFT - Z_COEFF_SHIFT;
+ if (zinterpunshift > 0) {
+ v = (Z_ONE - 1) * abs(largest_interp);
+ if (v < INT32_MIN || v > INT32_MAX)
+ zinterphp = sprintf("(int64_t)%s", zinterphp);
+ zinterphp = sprintf("(%s) >> %d", zinterphp, zinterpunshift);
+ } else if (zinterpunshift < 0)
+ zinterphp = sprintf("(%s) << %d", zinterphp, \
+ abs(zinterpunshift));
+ if (Z_UNSHIFT == 0)
+ zinterp = "z";
+ else
+ zinterp = sprintf("(z) >> %d", Z_UNSHIFT);
+ zinterp = sprintf("(%s) * (d)", zinterp);
+ if (Z_INTERP_UNSHIFT < 0)
+ zinterp = sprintf("(%s) << %d", zinterp, \
+ abs(Z_INTERP_UNSHIFT));
+ else if (Z_INTERP_UNSHIFT > 0)
+ zinterp = sprintf("(%s) >> %d", zinterp, Z_INTERP_UNSHIFT);
+ if (zinterphp != zinterp) {
+ printf("\n#ifdef SND_FEEDER_RATE_HP\n");
+ printf("#define Z_COEFF_INTERPOLATE(z, c, d)" \
+ "\t\t\t\t\t\\\n\t((c) + (%s))\n", zinterphp);
+ printf("#else\n");
+ printf("#define Z_COEFF_INTERPOLATE(z, c, d)" \
+ "\t\t\t\t\t\\\n\t((c) + (%s))\n", zinterp);
+ printf("#endif\n");
+ } else
+ printf("#define Z_COEFF_INTERPOLATE(z, c, d)" \
+ "\t\t\t\t\t\\\n\t((c) + (%s))\n", zinterp);
+ #printf("\n");
+ #printf("#define Z_SCALE_SHIFT\t\t%d\n", Z_SCALE_SHIFT);
+ #printf("#define Z_SCALE_ONE\t\t0x%08x%s\n", Z_SCALE_ONE, \
+ # (Z_SCALE_ONE > INT32_MAX) ? "U" : "");
+ printf("\n");
+ printf("#define Z_SCALE_CAST(s)\t\t((uint32_t)(s))\n");
+ genscale(8);
+ genscale(16);
+ genscale(24);
+ genscale(32);
+ printf("\n");
+ printf("#define Z_LINEAR_FULL_ONE\t0x%08xU\n", Z_LINEAR_FULL_ONE);
+ printf("#define Z_LINEAR_SHIFT\t\t%d\n", Z_LINEAR_SHIFT);
+ printf("#define Z_LINEAR_UNSHIFT\t%d\n", Z_LINEAR_UNSHIFT);
+ printf("#define Z_LINEAR_ONE\t\t0x%08x\n", Z_LINEAR_ONE);
+ printf("\n");
+ printf("#ifdef SND_PCM_64\n");
+ genlerp(8, 1);
+ genlerp(16, 1);
+ genlerp(24, 1);
+ genlerp(32, 1);
+ printf("#else\t/* !SND_PCM_64 */\n");
+ genlerp(8, 0);
+ genlerp(16, 0);
+ genlerp(24, 0);
+ genlerp(32, 0);
+ printf("#endif\t/* SND_PCM_64 */\n");
+ printf("\n");
+ printf("#define Z_QUALITY_ZOH\t\t0\n");
+ printf("#define Z_QUALITY_LINEAR\t1\n");
+ printf("#define Z_QUALITY_SINC\t\t%d\n", \
+ floor((length(ztab) - 1) / 2) + 2);
+ printf("\n");
+ printf("#define Z_QUALITY_MIN\t\t0\n");
+ printf("#define Z_QUALITY_MAX\t\t%d\n", length(ztab) + 1);
+ printf("\n/*\n * smallest: %.32f\n * largest: %.32f\n *\n", \
+ smallest, largest);
+ printf(" * z_unshift=%d, z_interp_shift=%d\n *\n", \
+ Z_UNSHIFT, Z_INTERP_SHIFT);
+ v = shr(Z_ONE - 1, Z_UNSHIFT) * abs(largest_interp);
+ printf(" * largest interpolation multiplication: %d\n */\n", v);
+ if (v < INT32_MIN || v > INT32_MAX) {
+ printf("\n#ifndef SND_FEEDER_RATE_HP\n");
+ printf("#error interpolation overflow, please reduce" \
+ " Z_INTERP_SHIFT\n");
+ printf("#endif\n");
+ }
+
+ printf("\n#endif /* !_FEEDER_RATE_GEN_H_ */\n");
+}
OpenPOWER on IntegriCloud