ref: 67217ee746a9c1cb9420b75ecc7fba20e523d42d
parent: 6384196f763633ae028376517eba3347163f925c
author: Jean-Marc Valin <[email protected]>
date: Fri May 21 09:58:51 EDT 2010
Splitting transients in time domain
--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -420,11 +420,45 @@
return *last_decision;
}
+static void interleave_vector(celt_norm *X, int N0, int stride)
+{
+ int i,j;
+ VARDECL(celt_norm, tmp);
+ int N;
+ SAVE_STACK;
+ N = N0*stride;
+ ALLOC(tmp, N, celt_norm);
+ for (i=0;i<stride;i++)
+ for (j=0;j<N0;j++)
+ tmp[j*stride+i] = X[i*N0+j];
+ for (j=0;j<N;j++)
+ X[j] = tmp[j];
+ RESTORE_STACK;
+}
+
+static void deinterleave_vector(celt_norm *X, int N0, int stride)
+{
+ int i,j;
+ VARDECL(celt_norm, tmp);
+ int N;
+ SAVE_STACK;
+ N = N0*stride;
+ ALLOC(tmp, N, celt_norm);
+ for (i=0;i<stride;i++)
+ for (j=0;j<N0;j++)
+ tmp[i*N0+j] = X[j*stride+i];
+ for (j=0;j<N;j++)
+ X[j] = tmp[j];
+ RESTORE_STACK;
+}
+
/* This function is responsible for encoding and decoding a band for both
the mono and stereo case. Even in the mono case, it can split the band
in two and transmit the energy difference with the two half-bands. It
can be called recursively so bands can end up being split in 8 parts. */
-static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_norm *Y, int N, int b, int spread, celt_norm *lowband, int resynth, ec_enc *ec, celt_int32 *remaining_bits, int LM, celt_norm *lowband_out, const celt_ener *bandE)
+static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_norm *Y,
+ int N, int b, int spread, celt_norm *lowband, int resynth, ec_enc *ec,
+ celt_int32 *remaining_bits, int LM, celt_norm *lowband_out, const celt_ener *bandE, int level)
{
int q;
int curr_bits;
@@ -431,9 +465,22 @@
int stereo, split;
int imid=0, iside=0;
int N0=N;
+ int N_B=N;
+ int spread0=spread;
+ if (spread)
+ N_B /= spread;
+
split = stereo = Y != NULL;
+ if (!stereo && spread>1 && level==0)
+ {
+ if (encode)
+ deinterleave_vector(X, N_B, spread);
+ if (lowband)
+ deinterleave_vector(lowband, N_B, spread);
+ }
+
/* If we need more than 32 bits, try splitting the band in two. */
if (!stereo && LM != -1 && !fits_in32(N, get_pulses(bits2pulses(m, m->bits[LM][i], N, b))))
{
@@ -443,6 +490,7 @@
Y = X+N;
split = 1;
LM -= 1;
+ spread = (spread+1)>>1;
}
}
@@ -495,7 +543,7 @@
first stereo split but a triangular one for the rest. */
if (encode)
itheta = (itheta+(1<<shift>>1))>>shift;
- if (stereo || qb>9)
+ if (stereo || qb>9 || spread>1)
{
if (encode)
ec_enc_uint(ec, itheta, (1<<qb)+1);
@@ -597,17 +645,17 @@
w[0] = x2[0];
w[1] = x2[1];
}
+ /* Here we only need to encode a sign for the side */
+ if (v[0]*w[1] - v[1]*w[0] > 0)
+ sign = 1;
+ else
+ sign = -1;
}
- quant_band(encode, m, i, v, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, NULL, NULL);
+ quant_band(encode, m, i, v, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, lowband_out, NULL, level+1);
if (sbits)
{
if (encode)
{
- /* Here we only need to encode a sign for the side */
- if (v[0]*w[1] - v[1]*w[0] > 0)
- sign = 1;
- else
- sign = -1;
ec_enc_bits(ec, sign==1, 1);
} else {
sign = 2*ec_dec_bits((ec_dec*)ec, 1)-1;
@@ -632,6 +680,11 @@
} else
{
/* "Normal" split code */
+
+ /* Give more bits to low-energy MDCTs than they would otherwise deserve */
+ if (spread>1 && !stereo)
+ delta >>= 1;
+
mbits = (b-qalloc/2-delta)/2;
if (mbits > b-qalloc)
mbits = b-qalloc;
@@ -639,11 +692,14 @@
mbits=0;
sbits = b-qalloc-mbits;
*remaining_bits -= qalloc;
- quant_band(encode, m, i, X, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, NULL, NULL);
if (stereo)
- quant_band(encode, m, i, Y, NULL, N, sbits, spread, NULL, resynth, ec, remaining_bits, LM, NULL, NULL);
- else
- quant_band(encode, m, i, Y, NULL, N, sbits, spread, lowband ? lowband+N : NULL, resynth, ec, remaining_bits, LM, NULL, NULL);
+ {
+ quant_band(encode, m, i, X, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, lowband_out, NULL, level);
+ quant_band(encode, m, i, Y, NULL, N, sbits, spread, NULL, resynth, ec, remaining_bits, LM, NULL, NULL, level);
+ } else {
+ quant_band(encode, m, i, X, NULL, N, mbits, spread, lowband, resynth, ec, remaining_bits, LM, NULL, NULL, level+1);
+ quant_band(encode, m, i, Y, NULL, N, sbits, spread, lowband ? lowband+N : NULL, resynth, ec, remaining_bits, LM, NULL, NULL, level+1);
+ }
}
} else {
@@ -671,31 +727,42 @@
alg_unquant(X, N, q, spread, lowband, (ec_dec*)ec);
}
- if (resynth && lowband_out)
+ if (resynth)
{
- int j;
- celt_word16 n;
- n = celt_sqrt(SHL32(EXTEND32(N0),22));
- for (j=0;j<N0;j++)
- lowband_out[j] = MULT16_16_Q15(n,X[j]);
- }
-
- if (split && resynth)
- {
- int j;
- celt_word16 mid, side;
+ if (split)
+ {
+ int j;
+ celt_word16 mid, side;
#ifdef FIXED_POINT
- mid = imid;
- side = iside;
+ mid = imid;
+ side = iside;
#else
- mid = (1.f/32768)*imid;
- side = (1.f/32768)*iside;
+ mid = (1.f/32768)*imid;
+ side = (1.f/32768)*iside;
#endif
- for (j=0;j<N;j++)
- X[j] = MULT16_16_Q15(X[j], mid);
- for (j=0;j<N;j++)
- Y[j] = MULT16_16_Q15(Y[j], side);
+ for (j=0;j<N;j++)
+ X[j] = MULT16_16_Q15(X[j], mid);
+ for (j=0;j<N;j++)
+ Y[j] = MULT16_16_Q15(Y[j], side);
+ }
+
+ if (!stereo && spread0>1 && level==0)
+ {
+ interleave_vector(X, N_B, spread0);
+ if (lowband)
+ interleave_vector(lowband, N_B, spread0);
+ }
+
+ if (lowband_out && !stereo)
+ {
+ int j;
+ celt_word16 n;
+ n = celt_sqrt(SHL32(EXTEND32(N0),22));
+ for (j=0;j<N0;j++)
+ lowband_out[j] = MULT16_16_Q15(n,X[j]);
+ }
+
if (stereo)
{
stereo_band_mix(m, X, Y, bandE, 0, i, -1, N);
@@ -756,7 +823,7 @@
if (b<0)
b = 0;
- quant_band(encode, m, i, X, Y, N, b, spread, norm+M*eBands[start], resynth, ec, &remaining_bits, LM, norm+M*eBands[i], bandE);
+ quant_band(encode, m, i, X, Y, N, b, spread, norm+M*eBands[start], resynth, ec, &remaining_bits, LM, norm+M*eBands[i], bandE, 0);
balance += pulses[i] + tell;
}
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -74,6 +74,7 @@
static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K)
{
+ int i;
celt_word16 c, s;
celt_word16 gain, theta;
int stride2=0;
@@ -85,11 +86,6 @@
X[14] = 1;
K=5;
}*/
- /*if (stride>1)
- {
- pseudo_hadamard(X, len, dir, stride, K);
- return;
- }*/
if (2*K>=len)
return;
gain = celt_div((celt_word32)MULT16_16(Q15_ONE,len),(celt_word32)(len+10*K));
@@ -99,11 +95,7 @@
c = celt_cos_norm(EXTEND32(theta));
s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
-#if 0
if (len>=8*stride)
- stride2 = stride*floor(.5+sqrt(len*1.f/stride));
-#else
- if (len>=8*stride)
{
stride2 = 1;
/* This is just a simple way of computing sqrt(len/stride) with rounding.
@@ -111,20 +103,21 @@
I _think_ it is bit-exact */
while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
stride2++;
- stride2 *= stride;
}
-#endif
- if (dir < 0)
+ len /= stride;
+ for (i=0;i<stride;i++)
{
- if (stride2)
- exp_rotation1(X, len, dir, stride2, s, c);
- exp_rotation1(X, len, dir, stride, c, s);
- } else {
- exp_rotation1(X, len, dir, stride, c, s);
- if (stride2)
- exp_rotation1(X, len, dir, stride2, s, c);
+ if (dir < 0)
+ {
+ if (stride2)
+ exp_rotation1(X+i*len, len, dir, stride2, s, c);
+ exp_rotation1(X+i*len, len, dir, 1, c, s);
+ } else {
+ exp_rotation1(X+i*len, len, dir, 1, c, s);
+ if (stride2)
+ exp_rotation1(X+i*len, len, dir, stride2, s, c);
+ }
}
-
/*if (len>=30)
{
for (i=0;i<len;i++)