[Ffmpeg-devel] ac3enc.c modifications
Justin Ruggles
jruggle
Thu Apr 21 03:58:12 CEST 2005
Hello,
Here are some of the additions I've made to the ac3 encoder. I've added
stereo rematrixing and channel gain range. Stereo rematrixing
selectively uses [(L+R)/2, (L-R)/2] instead of [L, R] when the 2
channels are similar. Channel gain range is used in the decoder to
increase dynamic range. The only thing I've changed (rather than added)
is on line 1404. I changed v-8 to v-9 because I noticed that the output
was too quiet. Using v-8, the exponent is limited to 1-24 instead of
0-24. Changing to v-9 fixes this.
Let me know what you think.
-Justin
--- ac3enc-orig.c 2005-04-20 20:04:26.000000000 -0400
+++ ac3enc.c 2005-04-20 20:10:05.000000000 -0400
@@ -967,6 +967,9 @@
uint8_t bap[AC3_MAX_CHANNELS][N/2],
int32_t mdct_coefs[AC3_MAX_CHANNELS][N/2],
int8_t global_exp[AC3_MAX_CHANNELS],
+ uint8_t gainrng[AC3_MAX_CHANNELS],
+ uint8_t rematstr,
+ uint8_t rematflg[4],
int block_num)
{
int ch, nb_groups, group_size, i, baie, rbnd;
@@ -991,23 +994,16 @@
put_bits(&s->pb, 1, 0); /* no new coupling strategy */
}
- if (s->acmod == 2)
- {
- if(block_num==0)
- {
- /* first block must define rematrixing (rematstr) */
- put_bits(&s->pb, 1, 1);
-
- /* dummy rematrixing rematflg(1:4)=0 */
- for (rbnd=0;rbnd<4;rbnd++)
- put_bits(&s->pb, 1, 0);
- }
- else
- {
- /* no matrixing (but should be used in the future) */
- put_bits(&s->pb, 1, 0);
- }
- }
+ if(s->acmod == 2) {
+ // rematrixing strategy
+ put_bits(&s->pb, 1, rematstr);
+
+ // rematrixing flags
+ if(rematstr) {
+ for(rbnd=0; rbnd<4; rbnd++)
+ put_bits(&s->pb, 1, rematflg[rbnd]);
+ }
+ }
#if defined(DEBUG)
{
@@ -1074,7 +1070,7 @@
}
if (ch != s->lfe_channel)
- put_bits(&s->pb, 2, 0); /* no gain range info */
+ put_bits(&s->pb, 2, gainrng[ch]); /* gain range info */
}
/* bit allocation info */
@@ -1355,6 +1351,69 @@
return frame_size * 2;
}
+
+/*
+ * channel gain range
+ */
+static uint8_t
+calc_ch_gain_range(int16_t *tab, int n) {
+ int i;
+ int v = 0;
+ for(i=0; i<n; i++) {
+ v |= abs(tab[i]);
+ }
+ uint8_t gain = 0;
+ if(v >= 16384) gain = 0;
+ else if(v >= 8192) gain = 1;
+ else if(v >= 4096) gain = 2;
+ else gain = 3;
+ return gain;
+}
+
+
+/* probably should go in ac3tab.h */
+static uint8_t rematbndtab[4][2] = { {13, 24}, {25, 36}, {37, 60}, {61,
252} };
+
+static void calc_rematrixing(int32_t mdct_coef[AC3_MAX_CHANNELS][N/2],
+ uint8_t *rematstr, uint8_t
rematflg[NB_BLOCKS][4], int blk)
+{
+ uint32_t sum[4][4];
+ int32_t lt, rt, ctmp;
+ int bnd, i, chmin;
+
+ memset(sum, 0, 64);
+ *rematstr = 0;
+ for(bnd=0; bnd<4; bnd++) {
+ for(i=rematbndtab[bnd][0]; i<=rematbndtab[bnd][1]; i++) {
+ lt = mdct_coef[0][i] / 128;
+ rt = mdct_coef[1][i] / 128;
+ sum[bnd][0] += lt*lt;
+ sum[bnd][1] += rt*rt;
+ sum[bnd][2] += (lt+rt)*(lt+rt);
+ sum[bnd][3] += (lt-rt)*(lt-rt);
+ }
+ chmin = 0;
+ if(sum[bnd][1] < sum[bnd][chmin]) chmin = 1;
+ if(sum[bnd][2] < sum[bnd][chmin]) chmin = 2;
+ if(sum[bnd][3] < sum[bnd][chmin]) chmin = 3;
+ if(chmin<2) {
+ rematflg[blk][bnd] = 0;
+ }
+ else {
+ rematflg[blk][bnd] = 1;
+ for(i=rematbndtab[bnd][0]; i<=rematbndtab[bnd][1]; i++) {
+ ctmp = mdct_coef[0][i];
+ mdct_coef[0][i] = (ctmp + mdct_coef[1][i]) / 2;
+ mdct_coef[1][i] = (ctmp - mdct_coef[1][i]) / 2;
+ }
+ }
+ if(blk != 0 && *rematstr == 0 &&
+ rematflg[blk][bnd] != rematflg[blk-1][bnd]) {
+ *rematstr = 1;
+ }
+ }
+ if(blk == 0) *rematstr = 1;
+}
+
static int AC3_encode_frame(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data)
{
@@ -1368,6 +1427,9 @@
uint8_t encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
uint8_t bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
int8_t exp_samples[NB_BLOCKS][AC3_MAX_CHANNELS];
+ uint8_t gainrng[NB_BLOCKS][AC3_MAX_CHANNELS];
+ uint8_t rematstr[NB_BLOCKS];
+ uint8_t rematflg[NB_BLOCKS][4];
int frame_bits;
frame_bits = 0;
@@ -1388,6 +1450,9 @@
sptr += sinc;
}
+ /* calculate channel gain range */
+ gainrng[i][ch] = calc_ch_gain_range(input_samples, 512);
+
/* apply the MDCT window */
for(j=0;j<N/2;j++) {
input_samples[j] = MUL16(input_samples[j],
@@ -1401,12 +1466,24 @@
v = 14 - log2_tab(input_samples, N);
if (v < 0)
v = 0;
- exp_samples[i][ch] = v - 8;
+ exp_samples[i][ch] = v - 9;
lshift_tab(input_samples, N, v);
/* do the MDCT */
mdct512(mdct_coef[i][ch], input_samples);
-
+ }
+ }
+
+ // calculate rematrixing
+ if(s->acmod == 2) {
+ for(i=0;i<NB_BLOCKS;i++) {
+ calc_rematrixing(mdct_coef[i], &rematstr[i], rematflg, i);
+ }
+ }
+
+
+ for(ch=0;ch<s->nb_all_channels;ch++) {
+ for(i=0;i<NB_BLOCKS;i++) {
/* compute "exponents". We take into account the
normalization there */
for(j=0;j<N/2;j++) {
@@ -1455,7 +1532,8 @@
for(i=0;i<NB_BLOCKS;i++) {
output_audio_block(s, exp_strategy[i], encoded_exp[i],
- bap[i], mdct_coef[i], exp_samples[i], i);
+ bap[i], mdct_coef[i], exp_samples[i],
+ gainrng[i], rematstr[i], rematflg[i], i);
}
return output_frame_end(s);
}
More information about the ffmpeg-devel
mailing list