[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