ref: e65978fea75e6583bbea527fe92e0ffbe025b24b
parent: 100ae8ce34e25766868c11fb952cec5b1f1f57a1
author: Jean-Marc Valin <[email protected]>
date: Thu Dec 2 08:46:48 EST 2010
Adding a dual stereo option. Left and right are coded independently.
--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -902,13 +902,13 @@
void quant_all_bands(int encode, const CELTMode *m, int start, int end,
celt_norm *_X, celt_norm *_Y, const celt_ener *bandE, int *pulses,
- int shortBlocks, int fold, int intensity, int *tf_res, int resynth,
+ int shortBlocks, int fold, int dual_stereo, int intensity, int *tf_res, int resynth,
int total_bits, void *ec, int LM, int codedBands)
{
int i, balance;
celt_int32 remaining_bits;
const celt_int16 * restrict eBands = m->eBands;
- celt_norm * restrict norm;
+ celt_norm * restrict norm, * restrict norm2;
VARDECL(celt_norm, _norm);
VARDECL(celt_norm, lowband_scratch);
int B;
@@ -921,10 +921,10 @@
M = 1<<LM;
B = shortBlocks ? M : 1;
- ALLOC(_norm, M*eBands[m->nbEBands], celt_norm);
+ ALLOC(_norm, C*M*eBands[m->nbEBands], celt_norm);
ALLOC(lowband_scratch, M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]), celt_norm);
norm = _norm;
-
+ norm2 = norm + M*eBands[m->nbEBands];
if (C==2)
{
int j;
@@ -1015,10 +1015,28 @@
if (effective_lowband < M*eBands[start])
effective_lowband = M*eBands[start];
}
- quant_band(encode, m, i, X, Y, N, b, fold, B, intensity, tf_change,
- effective_lowband != -1 ? norm+effective_lowband : NULL, resynth, ec, &remaining_bits, LM,
- norm+M*eBands[i], bandE, 0, &seed, Q15ONE, lowband_scratch);
+ if (dual_stereo && i==intensity)
+ {
+ int j;
+ /* Switch off dual stereo to do intensity */
+ dual_stereo = 0;
+ for (j=0;j<M*eBands[i];j++)
+ norm[j] = HALF32(norm[j]+norm2[j]);
+ }
+ if (dual_stereo)
+ {
+ quant_band(encode, m, i, X, NULL, N, b/2, fold, B, intensity, tf_change,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, resynth, ec, &remaining_bits, LM,
+ norm+M*eBands[i], bandE, 0, &seed, Q15ONE, lowband_scratch);
+ quant_band(encode, m, i, Y, NULL, N, b/2, fold, B, intensity, tf_change,
+ effective_lowband != -1 ? norm2+effective_lowband : NULL, resynth, ec, &remaining_bits, LM,
+ norm2+M*eBands[i], bandE, 0, &seed, Q15ONE, lowband_scratch);
+ } else {
+ quant_band(encode, m, i, X, Y, N, b, fold, B, intensity, tf_change,
+ effective_lowband != -1 ? norm+effective_lowband : NULL, resynth, ec, &remaining_bits, LM,
+ norm+M*eBands[i], bandE, 0, &seed, Q15ONE, lowband_scratch);
+ }
balance += pulses[i] + tell;
/* Update the folding position only as long as we have 1 bit/sample depth */
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -80,7 +80,7 @@
*/
void quant_all_bands(int encode, const CELTMode *m, int start, int end,
celt_norm * X, celt_norm * Y, const celt_ener *bandE, int *pulses,
- int time_domain, int fold, int intensity, int *tf_res, int resynth,
+ int time_domain, int fold, int dual_stereo, int intensity, int *tf_res, int resynth,
int total_bits, void *enc, int M, int codedBands);
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -649,6 +649,37 @@
return trim_index;
}
+static int stereo_analysis(const CELTMode *m, const celt_norm *X,
+ int nbEBands, int LM, int C, int N0)
+{
+ int i;
+ int thetas;
+ celt_word32 sumLR = EPSILON, sumMS = EPSILON;
+
+ /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */
+ for (i=0;i<13;i++)
+ {
+ int j;
+ for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
+ {
+ celt_word16 L, R, M, S;
+ L = X[j];
+ R = X[N0+j];
+ M = L+R;
+ S = L-R;
+ sumLR += EXTEND32(ABS16(L)) + EXTEND32(ABS16(R));
+ sumMS += EXTEND32(ABS16(M)) + EXTEND32(ABS16(S));
+ }
+ }
+ sumMS = MULT16_32_Q15(QCONST16(0.707107f, 15), sumMS);
+ thetas = 13;
+ /* We don't need thetas for lower bands with LM<=1 */
+ if (LM<=1)
+ thetas -= 8;
+ return MULT16_32_Q15((m->eBands[13]<<(LM+1))+thetas, sumMS)
+ > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR);
+}
+
#ifdef FIXED_POINT
int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
{
@@ -689,6 +720,7 @@
int pitch_index=0;
celt_word16 gain1 = 0;
int intensity=0;
+ int dual_stereo=0;
SAVE_STACK;
if (nbCompressedBytes<0 || pcm==NULL)
@@ -1003,6 +1035,11 @@
if (C==2)
{
+ dual_stereo = stereo_analysis(st->mode, X, st->mode->nbEBands, LM, C, N);
+ ec_enc_bit_prob(enc, dual_stereo, 32768);
+ }
+ if (C==2)
+ {
int effectiveRate;
if (st->vbr_rate_norm>0)
@@ -1055,7 +1092,7 @@
/* Residual quantisation */
quant_all_bands(1, st->mode, st->start, st->end, X, C==2 ? X+N : NULL,
- bandE, pulses, shortBlocks, has_fold, intensity, tf_res, resynth,
+ bandE, pulses, shortBlocks, has_fold, dual_stereo, intensity, tf_res, resynth,
nbCompressedBytes*8, enc, LM, codedBands);
quant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(enc, 0), enc, C);
@@ -1619,6 +1656,7 @@
int postfilter_pitch;
celt_word16 postfilter_gain;
int intensity=0;
+ int dual_stereo=0;
SAVE_STACK;
if (pcm==NULL)
@@ -1747,7 +1785,10 @@
}
if (C==2)
+ {
+ dual_stereo = ec_dec_bit_prob(dec, 32768);
intensity = ec_dec_uint(dec, 1+st->end-st->start);
+ }
bits = len*8 - ec_dec_tell(dec, 0) - 1;
codedBands = compute_allocation(st->mode, st->start, st->end, offsets, alloc_trim, bits, pulses, fine_quant, fine_priority, C, LM);
@@ -1756,7 +1797,7 @@
/* Decode fixed codebook */
quant_all_bands(0, st->mode, st->start, st->end, X, C==2 ? X+N : NULL,
- NULL, pulses, shortBlocks, has_fold, intensity, tf_res, 1,
+ NULL, pulses, shortBlocks, has_fold, dual_stereo, intensity, tf_res, 1,
len*8, dec, LM, codedBands);
unquant_energy_finalise(st->mode, st->start, st->end, bandE, oldBandE,