Getting rid of PVQ-level split

Adding one more level of band splitting so that splitting at the
PVQ encoding level is no longer necessary.
This commit is contained in:
Jean-Marc Valin 2010-05-21 00:26:03 -04:00
parent 4aa1b8df26
commit cae30df09a
7 changed files with 66 additions and 65 deletions

View file

@ -316,9 +316,7 @@ void apply_pitch(const CELTMode *m, celt_sig *X, const celt_sig *P, int gain_id,
}
}
#ifndef DISABLE_STEREO
static void stereo_band_mix(const CELTMode *m, celt_norm *X, celt_norm *Y, const celt_ener *bank, int stereo_mode, int bandID, int dir, int M)
static void stereo_band_mix(const CELTMode *m, celt_norm *X, celt_norm *Y, const celt_ener *bank, int stereo_mode, int bandID, int dir, int N)
{
int i = bandID;
const celt_int16 *eBands = m->eBands;
@ -341,7 +339,7 @@ static void stereo_band_mix(const CELTMode *m, celt_norm *X, celt_norm *Y, const
a1 = DIV32_16(SHL32(EXTEND32(left),14),norm);
a2 = dir*DIV32_16(SHL32(EXTEND32(right),14),norm);
}
for (j=0;j<M*eBands[i+1]-M*eBands[i];j++)
for (j=0;j<N;j++)
{
celt_norm r, l;
l = X[j];
@ -352,8 +350,6 @@ static void stereo_band_mix(const CELTMode *m, celt_norm *X, celt_norm *Y, const
}
#endif /* DISABLE_STEREO */
int folding_decision(const CELTMode *m, celt_norm *X, celt_word16 *average, int *last_decision, int _C, int M)
{
int i, c, N0;
@ -439,13 +435,16 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
split = stereo = Y != NULL;
/* If we need more than 32 bits, try splitting the band in two. */
if (!stereo && LM>0 && !fits_in32(N, get_pulses(bits2pulses(m, m->bits[LM][i], N, b))))
if (!stereo && LM != -1 && !fits_in32(N, get_pulses(bits2pulses(m, m->bits[LM][i], N, b))))
{
if (LM>0 || (N&1)==0)
{
N >>= 1;
Y = X+N;
split = 1;
LM -= 1;
}
}
if (split)
{
@ -468,7 +467,7 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
if (encode)
{
if (stereo)
stereo_band_mix(m, X, Y, bandE, qb==0, i, 1, 1<<LM);
stereo_band_mix(m, X, Y, bandE, qb==0, i, 1, N);
mid = renormalise_vector(X, Q15ONE, N, 1);
side = renormalise_vector(Y, Q15ONE, N, 1);
@ -644,10 +643,12 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
}
} else {
/* This is the basis no-split case */
/* This is the basic no-split case */
q = bits2pulses(m, m->bits[LM][i], N, b);
curr_bits = pulses2bits(m->bits[LM][i], N, q);
*remaining_bits -= curr_bits;
/* Ensures we can never bust the budget */
while (*remaining_bits < 0 && q > 0)
{
*remaining_bits += curr_bits;
@ -655,6 +656,11 @@ static void quant_band(int encode, const CELTMode *m, int i, celt_norm *X, celt_
curr_bits = pulses2bits(m->bits[LM][i], N, q);
*remaining_bits -= curr_bits;
}
/* Making sure we will *never* need more than 32 bits for the PVQ */
while (!fits_in32(N, get_pulses(q)))
q--;
if (encode)
alg_quant(X, N, q, spread, lowband, resynth, ec);
else
@ -746,7 +752,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, celt_norm *_X, ce
if (resynth && _Y != NULL)
{
stereo_band_mix(m, X, Y, bandE, 0, i, -1, M);
stereo_band_mix(m, X, Y, bandE, 0, i, -1, N);
renormalise_vector(X, Q15ONE, N, 1);
renormalise_vector(Y, Q15ONE, N, 1);
}

View file

@ -141,15 +141,6 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
*error = CELT_INVALID_MODE;
return NULL;
}
#ifdef DISABLE_STEREO
if (channels > 1)
{
celt_warning("Stereo support was disable from this build");
if (error)
*error = CELT_BAD_ARG;
return NULL;
}
#endif
if (channels < 0 || channels > 2)
{
@ -1217,15 +1208,6 @@ CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error)
*error = CELT_INVALID_MODE;
return NULL;
}
#ifdef DISABLE_STEREO
if (channels > 1)
{
celt_warning("Stereo support was disable from this build");
if (error)
*error = CELT_BAD_ARG;
return NULL;
}
#endif
if (channels < 0 || channels > 2)
{

View file

@ -854,21 +854,10 @@ static inline void encode_pulses32(int _n,int _k,const int *_y,ec_enc *_enc){
void encode_pulses(int *_y, int N, int K, ec_enc *enc)
{
if (K==0) {
} else if(fits_in32(N,K))
{
if (K==0)
return;
celt_assert(fits_in32(N,K));
encode_pulses32(N, K, _y, enc);
} else {
int i;
int count=0;
int split;
split = (N+1)/2;
for (i=0;i<split;i++)
count += abs(_y[i]);
ec_enc_uint(enc,count,K+1);
encode_pulses(_y, split, count, enc);
encode_pulses(_y+split, N-split, K-count, enc);
}
}
static inline void decode_pulses32(int _n,int _k,int *_y,ec_dec *_dec){
@ -900,14 +889,9 @@ void decode_pulses(int *_y, int N, int K, ec_dec *dec)
int i;
for (i=0;i<N;i++)
_y[i] = 0;
} else if(fits_in32(N,K))
} else
{
celt_assert (fits_in32(N,K));
decode_pulses32(N, K, _y, dec);
} else {
int split;
int count = ec_dec_uint(dec,K+1);
split = (N+1)/2;
decode_pulses(_y, split, count, dec);
decode_pulses(_y+split, N-split, K-count, dec);
}
}

View file

@ -380,9 +380,15 @@ CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
#endif
mode->window = window;
mode->bits = mode->_bits+1;
for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
mode->bits[i] = (const celt_int16 **)compute_alloc_cache(mode, 1, 1<<i);
if (mode->bits==NULL)
{
mode->bits[i] = (const celt_int16 **)compute_alloc_cache(mode, 1<<i);
if (mode->bits[i]==NULL)
goto failure;
}
mode->bits[-1] = (const celt_int16 **)compute_alloc_cache(mode, 0);
if (mode->bits[-1]==NULL)
goto failure;
logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
@ -459,6 +465,19 @@ void celt_mode_destroy(CELTMode *mode)
}
celt_free((celt_int16**)mode->bits[m]);
}
if (mode->bits[-1]!=NULL)
{
for (i=0;i<mode->nbEBands;i++)
{
if (mode->bits[-1][i] != prevPtr)
{
prevPtr = mode->bits[-1][i];
celt_free((int*)mode->bits[-1][i]);
}
}
}
celt_free((celt_int16**)mode->bits[-1]);
celt_free((celt_int16*)mode->eBands);
celt_free((celt_int16*)mode->allocVectors);

View file

@ -40,7 +40,7 @@
#include "mdct.h"
#include "pitch.h"
#define MAX_CONFIG_SIZES 4
#define MAX_CONFIG_SIZES 5
#define CELT_BITSTREAM_VERSION 0x8000000c
@ -93,7 +93,8 @@ struct CELTMode {
int nbAllocVectors; /**< Number of lines in the matrix below */
const celt_int16 *allocVectors; /**< Number of bits in each band for several rates */
const celt_int16 * const *(bits[MAX_CONFIG_SIZES]); /**< Cache for pulses->bits mapping in each band */
const celt_int16 * const **bits;
const celt_int16 * const *(_bits[MAX_CONFIG_SIZES]); /**< Cache for pulses->bits mapping in each band */
/* Stuff that could go in the {en,de}coder, but we save space this way */
mdct_lookup mdct[MAX_CONFIG_SIZES];

View file

@ -46,7 +46,7 @@
#ifndef STATIC_MODES
celt_int16 **compute_alloc_cache(CELTMode *m, int C, int M)
celt_int16 **compute_alloc_cache(CELTMode *m, int M)
{
int i, prevN;
int error = 0;
@ -60,8 +60,17 @@ celt_int16 **compute_alloc_cache(CELTMode *m, int C, int M)
prevN = -1;
for (i=0;i<m->nbEBands;i++)
{
int N = C*M*(eBands[i+1]-eBands[i]);
if (N == prevN && M*eBands[i] < m->pitchEnd)
int N;
if (M>0)
N = M*(eBands[i+1]-eBands[i]);
else
N = (eBands[i+1]-eBands[i])>>1;
if (N==0)
{
bits[i] = NULL;
continue;
}
if (N == prevN)
{
bits[i] = bits[i-1];
} else {
@ -85,7 +94,7 @@ celt_int16 **compute_alloc_cache(CELTMode *m, int C, int M)
{
for (i=0;i<m->nbEBands;i++)
{
if (bits[i] != prevPtr)
if (bits[i] != prevPtr && bits[i] != NULL)
{
prevPtr = bits[i];
celt_free((int*)bits[i]);

View file

@ -155,7 +155,7 @@ static inline int pulses2bits(const celt_int16 *cache, int N, int pulses)
}
/** Computes a cache of the pulses->bits mapping in each band */
celt_int16 **compute_alloc_cache(CELTMode *m, int C, int M);
celt_int16 **compute_alloc_cache(CELTMode *m, int M);
/** Compute the pulse allocation, i.e. how many pulses will go in each
* band.