[libav-devel] [PATCH 7/9] dca: support mixing LFE in dca_downmix.

Tim Walker tdskywalker at gmail.com
Sun Nov 24 00:20:11 CET 2013


Embedded downmix coefficients can use this.
---
 libavcodec/dcadata.h | 22 +++++++++++-----------
 libavcodec/dcadec.c  | 43 ++++++++++++++++++++++++++-----------------
 2 files changed, 37 insertions(+), 28 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 cf1da8c..cd4f188 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)
@@ -991,8 +991,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;
@@ -1042,6 +1042,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];
+        }
+    }
 }
 
 
@@ -1249,12 +1257,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,
@@ -1264,6 +1266,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;
 }
 
@@ -1858,7 +1867,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
             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;
@@ -1868,12 +1877,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
              *
              * The decoder can only downmix to 2-channel, so we need to ensure
              * embedded downmix coefficients are actually targeting 2-channel.
-             *
-             * 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 (i = 0; i < s->prim_channels; i++) {
+                for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
                     sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1;
                     code = s->core_downmix_codes[i][0] & 0x0FF;
                     s->downmix_coef[i][0] = (!code ? 0.0f :
@@ -1890,18 +1898,19 @@ FF_ENABLE_DEPRECATION_WARNINGS
                            "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 (i = 0; i < s->prim_channels; i++) {
+                for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
                     s->downmix_coef[i][0] = dca_default_coeffs[am][i][0];
                     s->downmix_coef[i][1] = dca_default_coeffs[am][i][1];
                 }
             }
             av_dlog(s->avctx, "Stereo downmix coeffs:\n");
-            for (i = 0; i < s->prim_channels; i++) {
+            for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
                 av_dlog(s->avctx, "L, input channel %d = %f\n", i,
                         s->downmix_coef[i][0]);
                 av_dlog(s->avctx, "R, input channel %d = %f\n", i,
-- 
1.8.3.4 (Apple Git-47)



More information about the libav-devel mailing list