[libav-devel] [PATCH 6/7] dca: support mixing LFE in Stereo downmix.

Tim Walker tdskywalker at gmail.com
Fri Nov 22 23:07:31 CET 2013


Embedded downmix coefficients can use this.
---
 libavcodec/dcadata.h | 22 +++++++++++-----------
 libavcodec/dcadec.c  | 45 +++++++++++++++++++++++++++------------------
 2 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/libavcodec/dcadata.h b/libavcodec/dcadata.h
index e6997bc..dc4e8b9 100644
--- a/libavcodec/dcadata.h
+++ b/libavcodec/dcadata.h
@@ -7551,17 +7551,17 @@ static const float dca_dmixtable[241] = {
     1.000000,
 };
 
-static const float dca_default_coeffs[10][5][2] = {
-    { { 0.707107, 0.707107 },                                                                                                 }, // A
-    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 },                                                                         }, // A + B (dual mono)
-    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 },                                                                         }, // L + R (stereo)
-    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 },                                                                         }, // (L+R) + (L-R) (sum-difference)
-    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 },                                                                         }, // LT + RT (left and right total)
-    { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 },                                                 }, // C + L + R
-    { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 },                                                 }, // L + R + S
-    { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 },                         }, // C + L + R + S
-    { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 },                         }, // L + R + SL + SR
-    { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, }, // C + L + R + SL + SR
+static const float dca_default_coeffs[10][6][2] = {
+    { { 0.707107, 0.707107 }, { 0.000000, 0.000000 },                                                                                                 }, // A [LFE]
+    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 },                                                                         }, // A + B (dual mono) [LFE]
+    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 },                                                                         }, // L + R (stereo) [LFE]
+    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 },                                                                         }, // (L+R) + (L-R) (sum-difference) [LFE]
+    { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 },                                                                         }, // LT + RT (left and right total) [LFE]
+    { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.000000, 0.000000 },                                                 }, // C + L + R [LFE]
+    { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 },                                                 }, // L + R + S [LFE]
+    { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 },                         }, // C + L + R + S [LFE]
+    { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 },                         }, // L + R + SL + SR [LFE]
+    { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + SL + SR [LFE]
 };
 
 /* downmix coeffs
diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c
index 1143d22..c59179f 100644
--- a/libavcodec/dcadec.c
+++ b/libavcodec/dcadec.c
@@ -336,7 +336,7 @@ typedef struct {
     int scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][2];    ///< scale factors (2 if transient)
     int joint_huff[DCA_PRIM_CHANNELS_MAX];                       ///< joint subband scale factors codebook
     int joint_scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< joint subband scale factors
-    float downmix_coef[DCA_PRIM_CHANNELS_MAX][2];                ///< stereo downmix coefficients
+    float downmix_coef[DCA_PRIM_CHANNELS_MAX + 1][2];            ///< stereo downmix coefficients
     int dynrange_coef;                                           ///< dynamic range coefficient
 
     /* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1)
@@ -804,14 +804,13 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
     }
 
     /* Stereo downmix coefficients */
-    if (!base_channel && s->prim_channels > 2) {
+    if (!base_channel && s->prim_channels + !!s->lfe > 2) {
         // the decoder can only downmix to 2-channel, so we need to make sure
         // embedded downmix coefficients are targeting 2-channel (if present)
-        // downmix coefficients for the LFE channel are ignored (not supported)
         if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
                                 s->core_downmix_amode == DCA_STEREO_TOTAL)) {
             int sign, code;
-            for (j = base_channel; j < s->prim_channels; j++) {
+            for (j = base_channel; j < s->prim_channels + !!s->lfe; j++) {
 
                 sign = s->core_downmix_codes[j][0] & 0x100 ? 1 : -1;
                 code = s->core_downmix_codes[j][0] & 0x0FF;
@@ -830,12 +829,13 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
                        "Invalid channel mode %d\n", am);
                 return AVERROR_INVALIDDATA;
             }
-            if (s->prim_channels > FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
+            if (s->prim_channels + !!s->lfe >
+                FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
                 avpriv_request_sample(s->avctx, "Downmixing %d channels",
-                                      s->prim_channels);
+                                      s->prim_channels + !!s->lfe);
                 return AVERROR_PATCHWELCOME;
             }
-            for (j = base_channel; j < s->prim_channels; j++) {
+            for (j = base_channel; j < s->prim_channels + !!s->lfe; j++) {
                 s->downmix_coef[j][0] = dca_default_coeffs[am][j][0];
                 s->downmix_coef[j][1] = dca_default_coeffs[am][j][1];
             }
@@ -936,9 +936,9 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
             av_log(s->avctx, AV_LOG_DEBUG, "\n");
         }
     }
-    if (!base_channel && s->prim_channels > 2) {
+    if (!base_channel && s->prim_channels + !!s->lfe > 2) {
         av_log(s->avctx, AV_LOG_DEBUG, "Downmix coeffs:\n");
-        for (j = 0; j < s->prim_channels; j++) {
+        for (j = 0; j < s->prim_channels + !!s->lfe; j++) {
             av_log(s->avctx, AV_LOG_DEBUG, "Channel 0, %d = %f\n", j,
                    s->downmix_coef[j][0]);
             av_log(s->avctx, AV_LOG_DEBUG, "Channel 1, %d = %f\n", j,
@@ -1040,8 +1040,8 @@ static void lfe_interpolation_fir(DCAContext *s, int decimation_select,
         op2                                     \
     }
 
-static void dca_downmix(float **samples, int srcfmt,
-                        float coef[DCA_PRIM_CHANNELS_MAX][2],
+static void dca_downmix(float **samples, int srcfmt, int lfe_present,
+                        float coef[DCA_PRIM_CHANNELS_MAX + 1][2],
                         const int8_t *channel_mapping)
 {
     int c, l, r, sl, sr, s;
@@ -1091,6 +1091,14 @@ static void dca_downmix(float **samples, int srcfmt,
                           MIX_REAR2(samples, sl, sr, 3, coef));
         break;
     }
+    if (lfe_present) {
+        int lf_buf = dca_lfe_index[srcfmt];
+        int lf_idx = dca_channels [srcfmt];
+        for (i = 0; i < 256; i++) {
+            samples[0][i] += samples[lf_buf][i] * coef[lf_idx][0];
+            samples[1][i] += samples[lf_buf][i] * coef[lf_idx][1];
+        }
+    }
 }
 
 
@@ -1298,12 +1306,6 @@ static int dca_filter_channels(DCAContext *s, int block_index)
                             M_SQRT1_2 / 32768.0 /* pcm_to_double[s->source_pcm_res] */);
     }
 
-    /* Down mixing */
-    if (s->prim_channels > 2 &&
-        s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
-        dca_downmix(s->samples_chanptr, s->amode, s->downmix_coef, s->channel_order_tab);
-    }
-
     /* Generate LFE samples for this subsubframe FIXME!!! */
     if (s->output & DCA_LFE) {
         lfe_interpolation_fir(s, s->lfe, 2 * s->lfe,
@@ -1313,6 +1315,13 @@ static int dca_filter_channels(DCAContext *s, int block_index)
         /* Outputs 20bits pcm samples */
     }
 
+    /* Downmixing to Stereo */
+    if (s->prim_channels + !!s->lfe > 2 &&
+        s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+        dca_downmix(s->samples_chanptr, s->amode, !!s->lfe, s->downmix_coef,
+                    s->channel_order_tab);
+    }
+
     return 0;
 }
 
@@ -1902,7 +1911,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
             s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
             return AVERROR_INVALIDDATA;
 
-        if (s->prim_channels > 2 &&
+        if (s->prim_channels + !!s->lfe > 2 &&
             avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
             channels = 2;
             s->output = DCA_STEREO;
-- 
1.8.3.4 (Apple Git-47)



More information about the libav-devel mailing list