ref: 37388eb5f0aaff6bb253d87f28cdcf50b1e08da7
parent: 45a4e4e80c01e86423321344a9cedac4141b344d
author: Jean-Marc Valin <jeanmarcv@google.com>
date: Sat Jun 29 23:16:10 EDT 2024
Using 32 bits for fixed-point band split gains
--- a/celt/arch.h
+++ b/celt/arch.h
@@ -173,6 +173,7 @@
#define celt_isnan(x) 0
#define Q15ONE 32767
+#define Q31ONE 2147483647
#define SIG_SHIFT 12
/* Safe saturation value for 32-bit signals. We need to make sure that we can
@@ -252,6 +253,7 @@
#endif
#define Q15ONE 1.0f
+#define Q31ONE 1.0f
#define NORM_SCALING 1.f
--- a/celt/bands.c
+++ b/celt/bands.c
@@ -369,7 +369,7 @@
}
/* We just added some energy, so we need to renormalise */
if (renormalize)
- renormalise_vector(X, N0<<LM, Q15ONE, arch);
+ renormalise_vector(X, N0<<LM, Q31ONE, arch);
} while (++c<C);
}
}
@@ -436,12 +436,11 @@
}
}
-static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val16 mid, int N, int arch)
+static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val32 mid, int N, int arch)
{
int j;
opus_val32 xp=0, side=0;
opus_val32 El, Er;
- opus_val16 mid2;
#ifdef FIXED_POINT
int kl, kr;
#endif
@@ -450,11 +449,10 @@
/* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
dual_inner_prod(Y, X, Y, N, &xp, &side, arch);
/* Compensating for the mid normalization */
- xp = MULT16_32_Q15(mid, xp);
+ xp = MULT32_32_Q31(mid, xp);
/* mid and side are in Q15, not Q14 like X and Y */
- mid2 = SHR16(mid, 1);
- El = MULT16_16(mid2, mid2) + side - 2*xp;
- Er = MULT16_16(mid2, mid2) + side + 2*xp;
+ El = SHR32(MULT32_32_Q31(mid, mid),3) + side - 2*xp;
+ Er = SHR32(MULT32_32_Q31(mid, mid),3) + side + 2*xp;
if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28))
{
OPUS_COPY(Y, X, N);
@@ -481,7 +479,7 @@
{
celt_norm r, l;
/* Apply mid scaling (side is already scaled) */
- l = MULT16_16_P15(mid, X[j]);
+ l = MULT32_32_Q31(mid, X[j]);
r = Y[j];
X[j] = EXTRACT16(PSHR32(MULT16_16(lgain, SUB16(l,r)), kl+1));
Y[j] = EXTRACT16(PSHR32(MULT16_16(rgain, ADD16(l,r)), kr+1));
@@ -956,7 +954,7 @@
static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
int N, int b, int B, celt_norm *lowband,
int LM,
- opus_val16 gain, int fill)
+ opus_val32 gain, int fill)
{
const unsigned char *cache;
int q;
@@ -963,7 +961,7 @@
int curr_bits;
int imid=0, iside=0;
int B0=B;
- opus_val16 mid=0, side=0;
+ opus_val32 mid=0, side=0;
unsigned cm=0;
celt_norm *Y=NULL;
int encode;
@@ -1003,8 +1001,8 @@
itheta = sctx.itheta;
qalloc = sctx.qalloc;
#ifdef FIXED_POINT
- mid = imid;
- side = iside;
+ mid = SHL32(EXTEND32(imid), 16);
+ side = SHL32(EXTEND32(iside), 16);
#else
mid = (1.f/32768)*imid;
side = (1.f/32768)*iside;
@@ -1031,20 +1029,20 @@
if (mbits >= sbits)
{
cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
- MULT16_16_P15(gain,mid), fill);
+ MULT32_32_Q31(gain,mid), fill);
rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0)
sbits += rebalance - (3<<BITRES);
cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
- MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
+ MULT32_32_Q31(gain,side), fill>>B)<<(B0>>1);
} else {
cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
- MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
+ MULT32_32_Q31(gain,side), fill>>B)<<(B0>>1);
rebalance = sbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=16384)
mbits += rebalance - (3<<BITRES);
cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
- MULT16_16_P15(gain,mid), fill);
+ MULT32_32_Q31(gain,mid), fill);
}
} else {
/* This is the basic no-split case */
@@ -1122,7 +1120,7 @@
static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
int N, int b, int B, celt_norm *lowband,
int LM, celt_norm *lowband_out,
- opus_val16 gain, celt_norm *lowband_scratch, int fill)
+ opus_val32 gain, celt_norm *lowband_scratch, int fill)
{
int N0=N;
int N_B=N;
@@ -1252,7 +1250,7 @@
{
int imid=0, iside=0;
int inv = 0;
- opus_val16 mid=0, side=0;
+ opus_val32 mid=0, side=0;
unsigned cm=0;
int mbits, sbits, delta;
int itheta;
@@ -1281,8 +1279,8 @@
itheta = sctx.itheta;
qalloc = sctx.qalloc;
#ifdef FIXED_POINT
- mid = imid;
- side = iside;
+ mid = SHL32(EXTEND32(imid), 16);
+ side = SHL32(EXTEND32(iside), 16);
#else
mid = (1.f/32768)*imid;
side = (1.f/32768)*iside;
@@ -1321,7 +1319,7 @@
sign = 1-2*sign;
/* We use orig_fill here because we want to fold the side, but if
itheta==16384, we'll have cleared the low bits of fill. */
- cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+ cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
lowband_scratch, orig_fill);
/* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
and there's no need to worry about mixing with the other channel. */
@@ -1330,10 +1328,10 @@
if (ctx->resynth)
{
celt_norm tmp;
- X[0] = MULT16_16_Q15(mid, X[0]);
- X[1] = MULT16_16_Q15(mid, X[1]);
- Y[0] = MULT16_16_Q15(side, Y[0]);
- Y[1] = MULT16_16_Q15(side, Y[1]);
+ X[0] = MULT32_32_Q31(mid, X[0]);
+ X[1] = MULT32_32_Q31(mid, X[1]);
+ Y[0] = MULT32_32_Q31(side, Y[0]);
+ Y[1] = MULT32_32_Q31(side, Y[1]);
tmp = X[0];
X[0] = SUB16(tmp,Y[0]);
Y[0] = ADD16(tmp,Y[0]);
@@ -1354,7 +1352,7 @@
{
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */
- cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+ cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
lowband_scratch, fill);
rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0)
@@ -1372,7 +1370,7 @@
mbits += rebalance - (3<<BITRES);
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */
- cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+ cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q31ONE,
lowband_scratch, fill);
}
}
@@ -1586,10 +1584,10 @@
{
x_cm = quant_band(&ctx, X, N, b/2, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
- last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm);
+ last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm);
y_cm = quant_band(&ctx, Y, N, b/2, B,
effective_lowband != -1 ? norm2+effective_lowband : NULL, LM,
- last?NULL:norm2+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, y_cm);
+ last?NULL:norm2+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, y_cm);
} else {
if (Y!=NULL)
{
@@ -1665,7 +1663,7 @@
} else {
x_cm = quant_band(&ctx, X, N, b, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
- last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm);
+ last?NULL:norm+M*eBands[i]-norm_offset, Q31ONE, lowband_scratch, x_cm|y_cm);
}
y_cm = x_cm;
}
--- a/celt/celt_decoder.c
+++ b/celt/celt_decoder.c
@@ -680,7 +680,7 @@
seed = celt_lcg_rand(seed);
X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
}
- renormalise_vector(X+boffs, blen, Q15ONE, st->arch);
+ renormalise_vector(X+boffs, blen, Q31ONE, st->arch);
}
}
st->rng = seed;
--- a/celt/vq.c
+++ b/celt/vq.c
@@ -119,7 +119,7 @@
/** Takes the pitch vector and the decoded residual vector, computes the gain
that will give ||p+g*y||=1 and mixes the residual with the pitch. */
static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
- int N, opus_val32 Ryy, opus_val16 gain)
+ int N, opus_val32 Ryy, opus_val32 gain)
{
int i;
#ifdef FIXED_POINT
@@ -132,7 +132,7 @@
k = celt_ilog2(Ryy)>>1;
#endif
t = VSHR32(Ryy, 2*(k-7));
- g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
+ g = MULT32_32_Q31(celt_rsqrt_norm(t),gain);
i=0;
do
@@ -328,7 +328,7 @@
}
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
- opus_val16 gain, int resynth, int arch)
+ opus_val32 gain, int resynth, int arch)
{
VARDECL(int, iy);
opus_val16 yy;
@@ -361,7 +361,7 @@
/** Decode pulse vector and combine the result with the pitch vector to produce
the final normalised signal in the current band. */
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
- ec_dec *dec, opus_val16 gain)
+ ec_dec *dec, opus_val32 gain)
{
opus_val32 Ryy;
unsigned collapse_mask;
@@ -380,7 +380,7 @@
}
#ifndef OVERRIDE_renormalise_vector
-void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch)
+void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch)
{
int i;
#ifdef FIXED_POINT
@@ -395,7 +395,7 @@
k = celt_ilog2(E)>>1;
#endif
t = VSHR32(E, 2*(k-7));
- g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
+ g = MULT32_32_Q31(celt_rsqrt_norm(t),gain);
xptr = X;
for (i=0;i<N;i++)
--- a/celt/vq.h
+++ b/celt/vq.h
@@ -60,7 +60,7 @@
* @ret A mask indicating which blocks in the band received pulses
*/
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
- opus_val16 gain, int resynth, int arch);
+ opus_val32 gain, int resynth, int arch);
/** Algebraic pulse decoder
* @param X Decoded normalised spectrum (returned)
@@ -70,9 +70,9 @@
* @ret A mask indicating which blocks in the band received pulses
*/
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
- ec_dec *dec, opus_val16 gain);
+ ec_dec *dec, opus_val32 gain);
-void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch);
+void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch);
int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch);
--
⑨