Keep bsinc info together in a struct

This commit is contained in:
Chris Robinson
2017-08-15 04:15:50 -07:00
parent 0604b00360
commit 4dd53ab942
5 changed files with 1060 additions and 1031 deletions
+9 -22
View File
@@ -39,6 +39,7 @@
#include "static_assert.h"
#include "mixer_defs.h"
#include "bsinc_inc.c"
#include "backends/base.h"
@@ -225,20 +226,6 @@ void aluInit(void)
*/
ALboolean BsincPrepare(const ALuint increment, BsincState *state)
{
static const ALfloat scaleBase = 1.510578918e-01f, scaleRange = 1.177936623e+00f;
static const ALuint m[BSINC_SCALE_COUNT] = { 24, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 12 };
static const ALuint to[4][BSINC_SCALE_COUNT] =
{
{ 0, 24, 408, 792, 1176, 1560, 1944, 2328, 2648, 2968, 3288, 3544, 3800, 4056, 4248, 4440 },
{ 4632, 5016, 5400, 5784, 6168, 6552, 6936, 7320, 7640, 7960, 8280, 8536, 8792, 9048, 9240, 0 },
{ 0, 9432, 9816, 10200, 10584, 10968, 11352, 11736, 12056, 12376, 12696, 12952, 13208, 13464, 13656, 13848 },
{ 14040, 14424, 14808, 15192, 15576, 15960, 16344, 16728, 17048, 17368, 17688, 17944, 18200, 18456, 18648, 0 }
};
static const ALuint tm[2][BSINC_SCALE_COUNT] =
{
{ 0, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 12 },
{ 24, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 0 }
};
ALfloat sf;
ALsizei si, pi;
ALboolean uncut = AL_TRUE;
@@ -246,7 +233,7 @@ ALboolean BsincPrepare(const ALuint increment, BsincState *state)
if(increment > FRACTIONONE)
{
sf = (ALfloat)FRACTIONONE / increment;
if(sf < scaleBase)
if(sf < bsinc.scaleBase)
{
/* Signal has been completely cut. The return result can be used
* to skip the filter (and output zeros) as an optimization.
@@ -257,7 +244,7 @@ ALboolean BsincPrepare(const ALuint increment, BsincState *state)
}
else
{
sf = (BSINC_SCALE_COUNT - 1) * (sf - scaleBase) * scaleRange;
sf = (BSINC_SCALE_COUNT - 1) * (sf - bsinc.scaleBase) * bsinc.scaleRange;
si = fastf2i(sf);
/* The interpolation factor is fit to this diagonally-symmetric
* curve to reduce the transition ripple caused by interpolating
@@ -273,17 +260,17 @@ ALboolean BsincPrepare(const ALuint increment, BsincState *state)
}
state->sf = sf;
state->m = m[si];
state->l = -(ALint)((m[si] / 2) - 1);
state->m = bsinc.m[si];
state->l = -((state->m/2) - 1);
/* The CPU cost of this table re-mapping could be traded for the memory
* cost of a complete table map (1024 elements large).
*/
for(pi = 0;pi < BSINC_PHASE_COUNT;pi++)
{
state->coeffs[pi].filter = &bsincTab[to[0][si] + tm[0][si]*pi];
state->coeffs[pi].scDelta = &bsincTab[to[1][si] + tm[1][si]*pi];
state->coeffs[pi].phDelta = &bsincTab[to[2][si] + tm[0][si]*pi];
state->coeffs[pi].spDelta = &bsincTab[to[3][si] + tm[1][si]*pi];
state->coeffs[pi].filter = &bsinc.Tab[bsinc.to[0][si] + bsinc.tm[0][si]*pi];
state->coeffs[pi].scDelta = &bsinc.Tab[bsinc.to[1][si] + bsinc.tm[1][si]*pi];
state->coeffs[pi].phDelta = &bsinc.Tab[bsinc.to[2][si] + bsinc.tm[0][si]*pi];
state->coeffs[pi].spDelta = &bsinc.Tab[bsinc.to[3][si] + bsinc.tm[1][si]*pi];
}
return uncut;
}
File diff suppressed because it is too large Load Diff
-1
View File
@@ -707,7 +707,6 @@ SET(ALC_OBJS Alc/ALc.c
Alc/effects/null.c
Alc/effects/reverb.c
Alc/helpers.c
Alc/bsinc.c
Alc/hrtf.c
Alc/uhjfilter.c
Alc/ambdec.c
+1 -2
View File
@@ -71,7 +71,7 @@ extern enum Resampler ResamplerDefault;
*/
typedef struct BsincState {
ALfloat sf; /* Scale interpolation factor. */
ALuint m; /* Coefficient count. */
ALsizei m; /* Coefficient count. */
ALint l; /* Left coefficient offset. */
struct {
const ALfloat *filter; /* Filter coefficients. */
@@ -382,7 +382,6 @@ inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
{ return minu64(max, maxu64(min, val)); }
extern alignas(16) const ALfloat bsincTab[18840];
extern alignas(16) const ALfloat sinc4Tab[FRACTIONONE][4];
+60 -36
View File
@@ -245,16 +245,32 @@ static void BsiGenerateTables()
for(si = 1; si < BSINC_SCALE_COUNT; si++)
i += BSINC_PHASE_COUNT * mt[si];
fprintf(stdout, "static const float bsincTab[%d] =\n{\n", i);
fprintf(stdout, "/* Generated by bsincgen, do not edit! */\n\n"
"/* Table of windowed sinc coefficients and deltas. This 11th order filter\n"
" * has a rejection of -60 dB, yielding a transition width of ~0.302\n"
" * (normalized frequency). Order increases when downsampling to a limit of\n"
" * one octave, after which the quality of the filter (transition width)\n"
" * suffers to reduce the CPU cost. The bandlimiting will cut all sound after\n"
" * downsampling by ~2.73 octaves.\n"
" */\n"
"static const struct {\n"
" alignas(16) const float Tab[%d];\n"
" const float scaleBase, scaleRange;\n"
" const int m[BSINC_SCALE_COUNT];\n"
" const int to[4][BSINC_SCALE_COUNT];\n"
" const int tm[2][BSINC_SCALE_COUNT];\n"
"} bsinc = {\n", i);
fprintf(stdout, " /* Tab */ {\n");
/* Only output enough coefficients for the first (cut) scale as needed to
perform interpolation without extra branching.
*/
fprintf(stdout, " /* %2d,%2d */", mt[0], 0);
fprintf(stdout, " /* %2d,%2d */", mt[0], 0);
for(i = 0; i < mt[0]; i++)
fprintf(stdout, " %+14.9ef,", filter[0][0][i]);
fprintf(stdout, "\n\n");
fprintf(stdout, " /* Filters */\n");
for(si = 1; si < BSINC_SCALE_COUNT; si++)
{
const int m = mt[si];
@@ -262,7 +278,7 @@ static void BsiGenerateTables()
for(pi = 0; pi < BSINC_PHASE_COUNT; pi++)
{
fprintf(stdout, " /* %2d,%2d */", m, pi);
fprintf(stdout, " /* %2d,%2d */", m, pi);
for(i = 0; i < m; i++)
fprintf(stdout, " %+14.9ef,", filter[si][pi][o + i]);
fprintf(stdout, "\n");
@@ -271,6 +287,7 @@ static void BsiGenerateTables()
fprintf(stdout, "\n");
// There are N-1 scale deltas for N scales.
fprintf(stdout, " /* Scale deltas */\n");
for(si = 0; si < (BSINC_SCALE_COUNT - 1); si++)
{
const int m = mt[si];
@@ -278,7 +295,7 @@ static void BsiGenerateTables()
for(pi = 0; pi < BSINC_PHASE_COUNT; pi++)
{
fprintf(stdout, " /* %2d,%2d */", m, pi);
fprintf(stdout, " /* %2d,%2d */", m, pi);
for(i = 0; i < m; i++)
fprintf(stdout, " %+14.9ef,", scDeltas[si][pi][o + i]);
fprintf(stdout, "\n");
@@ -287,6 +304,7 @@ static void BsiGenerateTables()
fprintf(stdout, "\n");
// Exclude phases for the first (cut) scale.
fprintf(stdout, " /* Phase deltas */\n");
for(si = 1; si < BSINC_SCALE_COUNT; si++)
{
const int m = mt[si];
@@ -294,7 +312,7 @@ static void BsiGenerateTables()
for(pi = 0; pi < BSINC_PHASE_COUNT; pi++)
{
fprintf(stdout, " /* %2d,%2d */", m, pi);
fprintf(stdout, " /* %2d,%2d */", m, pi);
for(i = 0; i < m; i++)
fprintf(stdout, " %+14.9ef,", phDeltas[si][pi][o + i]);
fprintf(stdout, "\n");
@@ -302,6 +320,7 @@ static void BsiGenerateTables()
}
fprintf(stdout, "\n");
fprintf(stdout, " /* Scale phase deltas */\n");
for(si = 0; si < (BSINC_SCALE_COUNT - 1); si++)
{
const int m = mt[si];
@@ -309,67 +328,67 @@ static void BsiGenerateTables()
for(pi = 0; pi < BSINC_PHASE_COUNT; pi++)
{
fprintf(stdout, " /* %2d,%2d */", m, pi);
fprintf(stdout, " /* %2d,%2d */", m, pi);
for(i = 0; i < m; i++)
fprintf(stdout, " %+14.9ef,", spDeltas[si][pi][o + i]);
fprintf(stdout, "\n");
}
}
fprintf(stdout, "};\n\n");
fprintf(stdout, " },\n\n");
/* The scaleBase is calculated from the Kaiser window transition width.
It represents the absolute limit to the filter before it fully cuts
the signal. The limit in octaves can be calculated by taking the
base-2 logarithm of its inverse: log_2(1 / scaleBase)
*/
fprintf(stdout, " static const ALfloat scaleBase = %.9ef, scaleRange = %.9ef;\n", scaleBase, 1.0 / scaleRange);
fprintf(stdout, " static const ALuint m[BSINC_SCALE_COUNT] = {");
fprintf(stdout, " /* scaleBase */ %.9ef, /* scaleRange */ %.9ef,\n", scaleBase, 1.0 / scaleRange);
fprintf(stdout, " /* m */ {");
fprintf(stdout, " %d", mt[0]);
for(si = 1; si < BSINC_SCALE_COUNT; si++)
fprintf(stdout, ", %d", mt[si]);
fprintf(stdout, " };\n");
fprintf(stdout, " static const ALuint to[4][BSINC_SCALE_COUNT] =\n {\n { 0");
fprintf(stdout, " },\n");
fprintf(stdout, " /* to */ {\n { %5d", 0);
i = mt[0];
for(si = 1; si < BSINC_SCALE_COUNT; si++)
{
fprintf(stdout, ", %d", i);
fprintf(stdout, ", %5d", i);
i += BSINC_PHASE_COUNT * mt[si];
}
fprintf(stdout, " },\n {");
for(si = 0; si < (BSINC_SCALE_COUNT - 1); si++)
{
fprintf(stdout, " %d,", i);
fprintf(stdout, " %5d,", i);
i += BSINC_PHASE_COUNT * mt[si];
}
fprintf(stdout, " 0 },\n { 0");
fprintf(stdout, " %5d },\n { %5d", 0, 0);
for(si = 1; si < BSINC_SCALE_COUNT; si++)
{
fprintf(stdout, ", %d", i);
fprintf(stdout, ", %5d", i);
i += BSINC_PHASE_COUNT * mt[si];
}
fprintf (stdout, " },\n {");
for(si = 0; si < (BSINC_SCALE_COUNT - 1); si++)
{
fprintf(stdout, " %d,", i);
fprintf(stdout, " %5d,", i);
i += BSINC_PHASE_COUNT * mt[si];
}
fprintf(stdout, " 0 }\n };\n");
fprintf(stdout, " %5d }\n },\n", 0);
fprintf(stdout, " static const ALuint tm[2][BSINC_SCALE_COUNT] = \n {\n { 0");
fprintf(stdout, " /* tm */ {\n { 0");
for(si = 1; si < BSINC_SCALE_COUNT; si++)
fprintf(stdout, ", %d", mt[si]);
fprintf(stdout, " },\n {");
for(si = 0; si < (BSINC_SCALE_COUNT - 1); si++)
fprintf(stdout, " %d,", mt[si]);
fprintf(stdout, " 0 }\n };\n\n");
fprintf(stdout, " 0 }\n }\n};\n\n");
}
/* These methods generate a much simplified 4-point sinc interpolator using a
* Kaiser windows. This is much simpler to process at run-time, but has notably
* Kaiser window. This is much simpler to process at run-time, but has notably
* more aliasing noise.
*/
@@ -377,30 +396,35 @@ static void BsiGenerateTables()
#define FRACTIONBITS (12)
#define FRACTIONONE (1<<FRACTIONBITS)
static double SincKaiser(double r, double x)
{
/* Limit rippling to -60dB. */
return Kaiser(CalcKaiserBeta(60.0), x / r) * Sinc(x);
}
static void Sinc4GenerateTables(void)
{
static double filter[FRACTIONONE][4];
int i;
for(i = 0;i < FRACTIONONE;i++)
const double width = CalcKaiserWidth(BSINC_REJECTION, 4);
const double beta = CalcKaiserBeta(BSINC_REJECTION);
const double scaleBase = width / 2.0;
const double scaleRange = 1.0 - scaleBase;
const double scale = scaleBase + scaleRange;
const double a = MinDouble(4.0, 4.0 / (2.0*scale));
const int m = 2 * (int)floor(a);
const int l = (m/2) - 1;
int pi;
for(pi = 0;pi < FRACTIONONE;pi++)
{
double mu = (double)i / FRACTIONONE;
filter[i][0] = SincKaiser(2.0, mu - -1.0);
filter[i][1] = SincKaiser(2.0, mu - 0.0);
filter[i][2] = SincKaiser(2.0, mu - 1.0);
filter[i][3] = SincKaiser(2.0, mu - 2.0);
const double phase = l + ((double)pi / FRACTIONONE);
int i;
for(i = 0;i < m;i++)
{
double x = i - phase;
filter[pi][i] = Kaiser(beta, x / a) * Sinc(x);
}
}
fprintf(stdout, "static const float sinc4Tab[%d][4] =\n{\n", FRACTIONONE);
for(i = 0;i < FRACTIONONE;i++)
fprintf(stdout, "alignas(16) const float sinc4Tab[FRACTIONONE][4] = {\n");
for(pi = 0;pi < FRACTIONONE;pi++)
fprintf(stdout, " { %+14.9ef, %+14.9ef, %+14.9ef, %+14.9ef },\n",
filter[i][0], filter[i][1], filter[i][2], filter[i][3]);
filter[pi][0], filter[pi][1], filter[pi][2], filter[pi][3]);
fprintf(stdout, "};\n\n");
}