Add stereo rematrixing support to the AC-3 encoders.
authorJustin Ruggles <justin.ruggles@gmail.com>
Sat, 8 Jan 2011 23:21:17 +0000 (23:21 +0000)
committerJustin Ruggles <justin.ruggles@gmail.com>
Sat, 8 Jan 2011 23:21:17 +0000 (23:21 +0000)
This improves the audio quality significantly for stereo source with both the
fixed-point and floating-point AC-3 encoders.
Update acodec-ac3_fixed and seek-ac3_rm test references.

Originally committed as revision 26271 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/ac3dec_data.c
libavcodec/ac3dec_data.h
libavcodec/ac3enc.c
libavcodec/ac3enc_fixed.h
libavcodec/ac3enc_float.h
libavcodec/ac3tab.c
libavcodec/ac3tab.h
tests/ref/acodec/ac3_fixed
tests/ref/seek/ac3_rm

index ea13d3d..c403902 100644 (file)
@@ -43,12 +43,6 @@ const uint8_t ff_ac3_ungroup_3_in_5_bits_tab[32][3] = {
     { 3, 0, 1 }, { 3, 0, 2 }, { 3, 1, 0 }, { 3, 1, 1 }
 };
 
-/**
- * Table of bin locations for rematrixing bands
- * reference: Section 7.5.2 Rematrixing : Frequency Band Definitions
- */
-const uint8_t ff_ac3_rematrix_band_tab[5] = { 13, 25, 37, 61, 253 };
-
 const uint8_t ff_eac3_hebap_tab[64] = {
     0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
     8, 8, 9, 9, 9, 10, 10, 10, 10, 11,
index 9ed7c73..e2ab7dd 100644 (file)
@@ -25,7 +25,6 @@
 #include <stdint.h>
 
 extern const uint8_t ff_ac3_ungroup_3_in_5_bits_tab[32][3];
-extern const uint8_t ff_ac3_rematrix_band_tab[5];
 
 extern const uint8_t ff_eac3_hebap_tab[64];
 extern const uint8_t ff_eac3_default_cpl_band_struct[18];
index d9a5432..f968834 100644 (file)
 /** Maximum number of exponent groups. +1 for separate DC exponent. */
 #define AC3_MAX_EXP_GROUPS 85
 
+/* stereo rematrixing algorithms */
+#define AC3_REMATRIXING_IS_STATIC 0x1
+#define AC3_REMATRIXING_SUMS    0
+#define AC3_REMATRIXING_NONE    1
+#define AC3_REMATRIXING_ALWAYS  3
+
 /** Scale a float value by 2^bits and convert to an integer. */
 #define SCALE_FLOAT(a, bits) lrintf((a) * (float)(1 << (bits)))
 
@@ -71,6 +77,8 @@ typedef struct AC3Block {
     uint16_t **qmant;                           ///< quantized mantissas
     uint8_t  exp_strategy[AC3_MAX_CHANNELS];    ///< exponent strategies
     int8_t   exp_shift[AC3_MAX_CHANNELS];       ///< exponent shift values
+    uint8_t  new_rematrixing_strategy;          ///< send new rematrixing flags in this block
+    uint8_t  rematrixing_flags[4];              ///< rematrixing flags
 } AC3Block;
 
 /**
@@ -107,6 +115,8 @@ typedef struct AC3EncodeContext {
     int bandwidth_code[AC3_MAX_CHANNELS];   ///< bandwidth code (0 to 60)               (chbwcod)
     int nb_coefs[AC3_MAX_CHANNELS];
 
+    int rematrixing;                        ///< determines how rematrixing strategy is calculated
+
     /* bitrate allocation control */
     int slow_gain_code;                     ///< slow gain code                         (sgaincod)
     int slow_decay_code;                    ///< slow decay code                        (sdcycod)
@@ -262,6 +272,114 @@ static void apply_mdct(AC3EncodeContext *s)
 
 
 /**
+ * Initialize stereo rematrixing.
+ * If the strategy does not change for each frame, set the rematrixing flags.
+ */
+static void rematrixing_init(AC3EncodeContext *s)
+{
+    if (s->channel_mode == AC3_CHMODE_STEREO)
+        s->rematrixing = AC3_REMATRIXING_SUMS;
+    else
+        s->rematrixing = AC3_REMATRIXING_NONE;
+    /* NOTE: AC3_REMATRIXING_ALWAYS might be used in
+             the future in conjunction with channel coupling. */
+
+    if (s->rematrixing & AC3_REMATRIXING_IS_STATIC) {
+        int flag = (s->rematrixing == AC3_REMATRIXING_ALWAYS);
+        s->blocks[0].new_rematrixing_strategy = 1;
+        memset(s->blocks[0].rematrixing_flags, flag,
+               sizeof(s->blocks[0].rematrixing_flags));
+    }
+}
+
+
+/**
+ * Determine rematrixing flags for each block and band.
+ */
+static void compute_rematrixing_strategy(AC3EncodeContext *s)
+{
+    int nb_coefs;
+    int blk, bnd, i;
+    AC3Block *block, *block0;
+
+    if (s->rematrixing & AC3_REMATRIXING_IS_STATIC)
+        return;
+
+    nb_coefs = FFMIN(s->nb_coefs[0], s->nb_coefs[1]);
+
+    s->blocks[0].new_rematrixing_strategy = 1;
+    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        block = &s->blocks[blk];
+        for (bnd = 0; bnd < 4; bnd++) {
+            /* calculate calculate sum of squared coeffs for one band in one block */
+            int start = ff_ac3_rematrix_band_tab[bnd];
+            int end   = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]);
+            CoefSumType sum[4] = {0,};
+            for (i = start; i < end; i++) {
+                CoefType lt = block->mdct_coef[0][i];
+                CoefType rt = block->mdct_coef[1][i];
+                CoefType md = lt + rt;
+                CoefType sd = lt - rt;
+                sum[0] += lt * lt;
+                sum[1] += rt * rt;
+                sum[2] += md * md;
+                sum[3] += sd * sd;
+            }
+
+            /* compare sums to determine if rematrixing will be used for this band */
+            if (FFMIN(sum[2], sum[3]) < FFMIN(sum[0], sum[1]))
+                block->rematrixing_flags[bnd] = 1;
+            else
+                block->rematrixing_flags[bnd] = 0;
+
+            /* determine if new rematrixing flags will be sent */
+            if (blk &&
+                !block->new_rematrixing_strategy &&
+                block->rematrixing_flags[bnd] != block0->rematrixing_flags[bnd]) {
+                block->new_rematrixing_strategy = 1;
+            }
+        }
+        block0 = block;
+    }
+}
+
+
+/**
+ * Apply stereo rematrixing to coefficients based on rematrixing flags.
+ */
+static void apply_rematrixing(AC3EncodeContext *s)
+{
+    int nb_coefs;
+    int blk, bnd, i;
+    int start, end;
+    uint8_t *flags;
+
+    if (s->rematrixing == AC3_REMATRIXING_NONE)
+        return;
+
+    nb_coefs = FFMIN(s->nb_coefs[0], s->nb_coefs[1]);
+
+    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        AC3Block *block = &s->blocks[blk];
+        if (block->new_rematrixing_strategy)
+            flags = block->rematrixing_flags;
+        for (bnd = 0; bnd < 4; bnd++) {
+            if (flags[bnd]) {
+                start = ff_ac3_rematrix_band_tab[bnd];
+                end   = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]);
+                for (i = start; i < end; i++) {
+                    int32_t lt = block->fixed_coef[0][i];
+                    int32_t rt = block->fixed_coef[1][i];
+                    block->fixed_coef[0][i] = (lt + rt) >> 1;
+                    block->fixed_coef[1][i] = (lt - rt) >> 1;
+                }
+            }
+        }
+    }
+}
+
+
+/**
  * Initialize exponent tables.
  */
 static av_cold void exponent_init(AC3EncodeContext *s)
@@ -592,7 +710,6 @@ static void count_frame_bits_fixed(AC3EncodeContext *s)
     /* assumptions:
      *   no dynamic range codes
      *   no channel coupling
-     *   no rematrixing
      *   bit allocation parameters do not change between blocks
      *   SNR offsets do not change between blocks
      *   no delta bit allocation
@@ -609,8 +726,6 @@ static void count_frame_bits_fixed(AC3EncodeContext *s)
         frame_bits += s->fbw_channels * 2 + 2; /* blksw * c, dithflag * c, dynrnge, cplstre */
         if (s->channel_mode == AC3_CHMODE_STEREO) {
             frame_bits++; /* rematstr */
-            if (!blk)
-                frame_bits += 4;
         }
         frame_bits += 2 * s->fbw_channels; /* chexpstr[2] * c */
         if (s->lfe_on)
@@ -681,6 +796,13 @@ static void count_frame_bits(AC3EncodeContext *s)
 
     for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
         uint8_t *exp_strategy = s->blocks[blk].exp_strategy;
+
+        /* stereo rematrixing */
+        if (s->channel_mode == AC3_CHMODE_STEREO &&
+            s->blocks[blk].new_rematrixing_strategy) {
+            frame_bits += 4;
+        }
+
         for (ch = 0; ch < s->fbw_channels; ch++) {
             if (exp_strategy[ch] != EXP_REUSE)
                 frame_bits += 6 + 2; /* chbwcod[6], gainrng[2] */
@@ -1194,16 +1316,11 @@ static void output_audio_block(AC3EncodeContext *s, int block_num)
 
     /* stereo rematrixing */
     if (s->channel_mode == AC3_CHMODE_STEREO) {
-        if (!block_num) {
-            /* first block must define rematrixing (rematstr) */
-            put_bits(&s->pb, 1, 1);
-
-            /* dummy rematrixing rematflg(1:4)=0 */
+        put_bits(&s->pb, 1, block->new_rematrixing_strategy);
+        if (block->new_rematrixing_strategy) {
+            /* rematrixing flags */
             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);
+                put_bits(&s->pb, 1, block->rematrixing_flags[rbnd]);
         }
     }
 
@@ -1394,8 +1511,12 @@ static int ac3_encode_frame(AVCodecContext *avctx, unsigned char *frame,
 
     apply_mdct(s);
 
+    compute_rematrixing_strategy(s);
+
     scale_coefficients(s);
 
+    apply_rematrixing(s);
+
     process_exponents(s);
 
     ret = compute_bit_allocation(s);
@@ -1707,6 +1828,8 @@ static av_cold int ac3_encode_init(AVCodecContext *avctx)
 
     set_bandwidth(s);
 
+    rematrixing_init(s);
+
     exponent_init(s);
 
     bit_alloc_init(s);
index 32d29a9..12c8ace 100644 (file)
@@ -34,6 +34,7 @@
 
 typedef int16_t SampleType;
 typedef int32_t CoefType;
+typedef int64_t CoefSumType;
 
 
 /**
index 29a479a..1726ca0 100644 (file)
@@ -34,6 +34,7 @@
 
 typedef float SampleType;
 typedef float CoefType;
+typedef float CoefSumType;
 
 
 typedef struct AC3MDCTContext {
index 79f628f..4fc0824 100644 (file)
@@ -132,6 +132,12 @@ const uint16_t ff_ac3_bitrate_tab[19] = {
     160, 192, 224, 256, 320, 384, 448, 512, 576, 640
 };
 
+/**
+ * Table of bin locations for rematrixing bands
+ * reference: Section 7.5.2 Rematrixing : Frequency Band Definitions
+ */
+const uint8_t ff_ac3_rematrix_band_tab[5] = { 13, 25, 37, 61, 253 };
+
 /* AC-3 MDCT window */
 
 /* MDCT window */
index 4d41337..dd8cabf 100644 (file)
@@ -32,6 +32,7 @@ extern const uint8_t  ff_ac3_enc_channel_map[8][2][6];
 extern const uint8_t  ff_ac3_dec_channel_map[8][2][6];
 extern const uint16_t ff_ac3_sample_rate_tab[3];
 extern const uint16_t ff_ac3_bitrate_tab[19];
+extern const uint8_t  ff_ac3_rematrix_band_tab[5];
 extern const int16_t  ff_ac3_window[AC3_WINDOW_SIZE/2];
 extern const uint8_t  ff_ac3_log_add_tab[260];
 extern const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3];
index 3ca8219..17159e1 100644 (file)
@@ -1,2 +1,2 @@
-b315176b519a63a35cb91566e768f62b *./tests/data/acodec/ac3.rm
+9823c8f74097eab5d148cf0536ae932e *./tests/data/acodec/ac3.rm
 98751 ./tests/data/acodec/ac3.rm
index 6d47c47..7b7d5b0 100644 (file)
@@ -5,11 +5,9 @@ ret:-1         st:-1 flags:1  ts: 1.894167
 ret:-1         st: 0 flags:0  ts: 0.788000
 ret: 0         st: 0 flags:1  ts:-0.317000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    271 size:   556
-ret: 0         st:-1 flags:0  ts: 2.576668
-ret: 0         st: 0 flags:1 dts: 4.179000 pts: 4.179000 pos:  68585 size:   556
+ret:-1         st:-1 flags:0  ts: 2.576668
 ret:-1         st:-1 flags:1  ts: 1.470835
-ret: 0         st: 0 flags:0  ts: 0.365000
-ret: 0         st: 0 flags:1 dts: 0.383000 pts: 0.383000 pos:   6533 size:   558
+ret:-1         st: 0 flags:0  ts: 0.365000
 ret: 0         st: 0 flags:1  ts:-0.741000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    271 size:   556
 ret:-1         st:-1 flags:0  ts: 2.153336
@@ -18,25 +16,20 @@ ret: 0         st: 0 flags:0  ts:-0.058000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    271 size:   556
 ret:-1         st: 0 flags:1  ts: 2.836000
 ret:-1         st:-1 flags:0  ts: 1.730004
-ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 0.452000 pts: 0.452000 pos:   7671 size:   558
+ret:-1         st:-1 flags:1  ts: 0.624171
 ret: 0         st: 0 flags:0  ts:-0.482000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    271 size:   556
-ret: 0         st: 0 flags:1  ts: 2.413000
-ret: 0         st: 0 flags:1 dts: 2.333000 pts: 2.333000 pos:  38413 size:   556
+ret:-1         st: 0 flags:1  ts: 2.413000
 ret:-1         st:-1 flags:0  ts: 1.306672
 ret:-1         st:-1 flags:1  ts: 0.200839
 ret: 0         st: 0 flags:0  ts:-0.905000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    271 size:   556
-ret: 0         st: 0 flags:1  ts: 1.989000
-ret: 0         st: 0 flags:1 dts: 1.985000 pts: 1.985000 pos:  32719 size:   558
+ret:-1         st: 0 flags:1  ts: 1.989000
 ret:-1         st:-1 flags:0  ts: 0.883340
 ret: 0         st:-1 flags:1  ts:-0.222493
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    271 size:   556
-ret: 0         st: 0 flags:0  ts: 2.672000
-ret: 0         st: 0 flags:1 dts: 4.179000 pts: 4.179000 pos:  68585 size:   556
+ret:-1         st: 0 flags:0  ts: 2.672000
 ret:-1         st: 0 flags:1  ts: 1.566000
-ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 4.179000 pts: 4.179000 pos:  68585 size:   556
+ret:-1         st:-1 flags:0  ts: 0.460008
 ret: 0         st:-1 flags:1  ts:-0.645825
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:    271 size:   556