1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

ac3enc: shift coefficients to 24-bit following MDCT rather than using an exponent offset.

This makes channel coupling more accurate, increasing quality for stereo
content.  It also simplifies exponent extraction and mantissa quantization
by no longer needing to apply an offset to the exponents.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Justin Ruggles 2011-03-08 13:18:56 -05:00 committed by Michael Niedermayer
parent 67fc32ac61
commit 7e0a284b9f
3 changed files with 41 additions and 16 deletions

View File

@ -78,7 +78,7 @@ typedef struct AC3Block {
int16_t **band_psd; ///< psd per critical band int16_t **band_psd; ///< psd per critical band
int16_t **mask; ///< masking curve int16_t **mask; ///< masking curve
uint16_t **qmant; ///< quantized mantissas uint16_t **qmant; ///< quantized mantissas
int8_t exp_shift[AC3_MAX_CHANNELS]; ///< exponent shift values int8_t coeff_shift[AC3_MAX_CHANNELS]; ///< fixed-point coefficient shift values
uint8_t new_rematrixing_strategy; ///< send new rematrixing flags in this block uint8_t new_rematrixing_strategy; ///< send new rematrixing flags in this block
uint8_t rematrixing_flags[4]; ///< rematrixing flags uint8_t rematrixing_flags[4]; ///< rematrixing flags
} AC3Block; } AC3Block;
@ -269,7 +269,7 @@ static void apply_mdct(AC3EncodeContext *s)
apply_window(&s->dsp, s->windowed_samples, input_samples, s->mdct.window, AC3_WINDOW_SIZE); apply_window(&s->dsp, s->windowed_samples, input_samples, s->mdct.window, AC3_WINDOW_SIZE);
block->exp_shift[ch] = normalize_samples(s); block->coeff_shift[ch] = normalize_samples(s);
mdct512(&s->mdct, block->mdct_coef[ch], s->windowed_samples); mdct512(&s->mdct, block->mdct_coef[ch], s->windowed_samples);
} }
@ -416,14 +416,13 @@ static void extract_exponents(AC3EncodeContext *s)
AC3Block *block = &s->blocks[blk]; AC3Block *block = &s->blocks[blk];
uint8_t *exp = block->exp[ch]; uint8_t *exp = block->exp[ch];
int32_t *coef = block->fixed_coef[ch]; int32_t *coef = block->fixed_coef[ch];
int exp_shift = block->exp_shift[ch];
for (i = 0; i < AC3_MAX_COEFS; i++) { for (i = 0; i < AC3_MAX_COEFS; i++) {
int e; int e;
int v = abs(coef[i]); int v = abs(coef[i]);
if (v == 0) if (v == 0)
e = 24; e = 24;
else { else {
e = 23 - av_log2(v) + exp_shift; e = 23 - av_log2(v);
if (e >= 24) { if (e >= 24) {
e = 24; e = 24;
coef[i] = 0; coef[i] = 0;
@ -1139,7 +1138,7 @@ static inline int asym_quant(int c, int e, int qbits)
* Quantize a set of mantissas for a single channel in a single block. * Quantize a set of mantissas for a single channel in a single block.
*/ */
static void quantize_mantissas_blk_ch(AC3EncodeContext *s, int32_t *fixed_coef, static void quantize_mantissas_blk_ch(AC3EncodeContext *s, int32_t *fixed_coef,
int8_t exp_shift, uint8_t *exp, uint8_t *exp,
uint8_t *bap, uint16_t *qmant, int n) uint8_t *bap, uint16_t *qmant, int n)
{ {
int i; int i;
@ -1147,7 +1146,7 @@ static void quantize_mantissas_blk_ch(AC3EncodeContext *s, int32_t *fixed_coef,
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
int v; int v;
int c = fixed_coef[i]; int c = fixed_coef[i];
int e = exp[i] - exp_shift; int e = exp[i];
int b = bap[i]; int b = bap[i];
switch (b) { switch (b) {
case 0: case 0:
@ -1243,7 +1242,7 @@ static void quantize_mantissas(AC3EncodeContext *s)
s->qmant1_ptr = s->qmant2_ptr = s->qmant4_ptr = NULL; s->qmant1_ptr = s->qmant2_ptr = s->qmant4_ptr = NULL;
for (ch = 0; ch < s->channels; ch++) { for (ch = 0; ch < s->channels; ch++) {
quantize_mantissas_blk_ch(s, block->fixed_coef[ch], block->exp_shift[ch], quantize_mantissas_blk_ch(s, block->fixed_coef[ch],
block->exp[ch], block->bap[ch], block->exp[ch], block->bap[ch],
block->qmant[ch], s->nb_coefs[ch]); block->qmant[ch], s->nb_coefs[ch]);
} }

View File

@ -294,29 +294,55 @@ static void lshift_tab(int16_t *tab, int n, unsigned int lshift)
} }
/**
* Shift each value in an array by a specified amount.
* @param src input array
* @param n number of values in the array
* @param shift shift amount (negative=right, positive=left)
*/
static void shift_int32(int32_t *src, int n, int shift)
{
int i;
if (shift > 0) {
for (i = 0; i < n; i++)
src[i] <<= shift;
} else if (shift < 0) {
shift = -shift;
for (i = 0; i < n; i++)
src[i] >>= shift;
}
}
/** /**
* Normalize the input samples to use the maximum available precision. * Normalize the input samples to use the maximum available precision.
* This assumes signed 16-bit input samples. Exponents are reduced by 9 to * This assumes signed 16-bit input samples.
* match the 24-bit internal precision for MDCT coefficients.
* *
* @return exponent shift * @return coefficient shift
*/ */
static int normalize_samples(AC3EncodeContext *s) static int normalize_samples(AC3EncodeContext *s)
{ {
int v = 14 - log2_tab(s, s->windowed_samples, AC3_WINDOW_SIZE); int v = 14 - log2_tab(s, s->windowed_samples, AC3_WINDOW_SIZE);
lshift_tab(s->windowed_samples, AC3_WINDOW_SIZE, v); lshift_tab(s->windowed_samples, AC3_WINDOW_SIZE, v);
return v - 9; return 9 - v;
} }
/** /**
* Scale MDCT coefficients from float to fixed-point. * Scale MDCT coefficients to 24-bit fixed-point.
*/ */
static void scale_coefficients(AC3EncodeContext *s) static void scale_coefficients(AC3EncodeContext *s)
{ {
/* scaling/conversion is obviously not needed for the fixed-point encoder int blk, ch;
since the coefficients are already fixed-point. */
return; for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
AC3Block *block = &s->blocks[blk];
for (ch = 0; ch < s->channels; ch++) {
shift_int32(block->mdct_coef[ch], AC3_MAX_COEFS,
block->coeff_shift[ch]);
}
}
} }

View File

@ -1,2 +1,2 @@
07bd593823ebd721b3a32ef298bdfc20 *./tests/data/acodec/ac3.rm 5f1255da35a4ed00a2e932887c9aef77 *./tests/data/acodec/ac3.rm
98751 ./tests/data/acodec/ac3.rm 98751 ./tests/data/acodec/ac3.rm