]> git.sesse.net Git - ffmpeg/blobdiff - libavresample/audio_mix_matrix.c
vf_crop: make config_props work properly when called multiple times.
[ffmpeg] / libavresample / audio_mix_matrix.c
index 6135b02422a6e3f7b44f0b781727bc77a05a4cd9..8da1b487a40e2bdb565c8df843483efb5e843af6 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <stdint.h>
 
+#include "libavutil/common.h"
 #include "libavutil/libm.h"
 #include "libavutil/samplefmt.h"
 #include "avresample.h"
@@ -53,6 +54,9 @@
 #define WIDE_RIGHT             32
 #define SURROUND_DIRECT_LEFT   33
 #define SURROUND_DIRECT_RIGHT  34
+#define LOW_FREQUENCY_2        35
+
+#define SQRT3_2      1.22474487139158904909  /* sqrt(3/2) */
 
 static av_always_inline int even(uint64_t layout)
 {
@@ -83,14 +87,21 @@ static int sane_layout(uint64_t layout)
 int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
                             double center_mix_level, double surround_mix_level,
                             double lfe_mix_level, int normalize,
-                            double *matrix_out, int stride)
+                            double *matrix_out, int stride,
+                            enum AVMatrixEncoding matrix_encoding)
 {
     int i, j, out_i, out_j;
     double matrix[64][64] = {{0}};
-    int64_t unaccounted = in_layout & ~out_layout;
+    int64_t unaccounted;
     double maxcoef = 0;
     int in_channels, out_channels;
 
+    if ((out_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == AV_CH_LAYOUT_STEREO_DOWNMIX) {
+        out_layout = AV_CH_LAYOUT_STEREO;
+    }
+
+    unaccounted = in_layout & ~out_layout;
+
     in_channels  = av_get_channel_layout_nb_channels( in_layout);
     out_channels = av_get_channel_layout_nb_channels(out_layout);
 
@@ -140,8 +151,19 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
             matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
             matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
         } else if (out_layout & AV_CH_FRONT_LEFT) {
-            matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
-            matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
+                matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+                if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
+                    matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
+                    matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+                } else {
+                    matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
+                    matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
+                }
+            } else {
+                matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+            }
         } else if (out_layout & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
         } else
@@ -163,8 +185,20 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
                 matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
             }
         } else if (out_layout & AV_CH_FRONT_LEFT) {
-            matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
-            matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
+            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+                matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
+            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+                matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
+                matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
+            } else {
+                matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
+                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
+            }
         } else if (out_layout & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
             matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
@@ -187,8 +221,20 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
             matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
             matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
         } else if (out_layout & AV_CH_FRONT_LEFT) {
-            matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
-            matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
+            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+                matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
+            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+                matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
+                matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
+            } else {
+                matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
+                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
+            }
         } else if (out_layout & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
             matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
@@ -241,106 +287,3 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
 
     return 0;
 }
-
-int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
-                          int stride)
-{
-    int in_channels, out_channels, i, o;
-
-    in_channels  = av_get_channel_layout_nb_channels(avr->in_channel_layout);
-    out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
-
-    if ( in_channels < 0 ||  in_channels > AVRESAMPLE_MAX_CHANNELS ||
-        out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
-        av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
-        return AVERROR(EINVAL);
-    }
-
-    switch (avr->mix_coeff_type) {
-    case AV_MIX_COEFF_TYPE_Q8:
-        if (!avr->am->matrix_q8[0]) {
-            av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
-            return AVERROR(EINVAL);
-        }
-        for (o = 0; o < out_channels; o++)
-            for (i = 0; i < in_channels; i++)
-                matrix[o * stride + i] = avr->am->matrix_q8[o][i] / 256.0;
-        break;
-    case AV_MIX_COEFF_TYPE_Q15:
-        if (!avr->am->matrix_q15[0]) {
-            av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
-            return AVERROR(EINVAL);
-        }
-        for (o = 0; o < out_channels; o++)
-            for (i = 0; i < in_channels; i++)
-                matrix[o * stride + i] = avr->am->matrix_q15[o][i] / 32768.0;
-        break;
-    case AV_MIX_COEFF_TYPE_FLT:
-        if (!avr->am->matrix_flt[0]) {
-            av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
-            return AVERROR(EINVAL);
-        }
-        for (o = 0; o < out_channels; o++)
-            for (i = 0; i < in_channels; i++)
-                matrix[o * stride + i] = avr->am->matrix_flt[o][i];
-        break;
-    default:
-        av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
-        return AVERROR(EINVAL);
-    }
-    return 0;
-}
-
-int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
-                          int stride)
-{
-    int in_channels, out_channels, i, o;
-
-    in_channels  = av_get_channel_layout_nb_channels(avr->in_channel_layout);
-    out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
-
-    if ( in_channels < 0 ||  in_channels > AVRESAMPLE_MAX_CHANNELS ||
-        out_channels < 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
-        av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (avr->am->matrix)
-        av_freep(avr->am->matrix);
-
-#define CONVERT_MATRIX(type, expr)                                          \
-    avr->am->matrix_## type[0] = av_mallocz(out_channels * in_channels *    \
-                                            sizeof(*avr->am->matrix_## type[0])); \
-    if (!avr->am->matrix_## type[0])                                        \
-        return AVERROR(ENOMEM);                                             \
-    for (o = 0; o < out_channels; o++) {                                    \
-        if (o > 0)                                                          \
-            avr->am->matrix_## type[o] = avr->am->matrix_## type[o - 1] +   \
-                                         in_channels;                       \
-        for (i = 0; i < in_channels; i++) {                                 \
-            double v = matrix[o * stride + i];                              \
-            avr->am->matrix_## type[o][i] = expr;                           \
-        }                                                                   \
-    }                                                                       \
-    avr->am->matrix = (void **)avr->am->matrix_## type;
-
-    switch (avr->mix_coeff_type) {
-    case AV_MIX_COEFF_TYPE_Q8:
-        CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))
-        break;
-    case AV_MIX_COEFF_TYPE_Q15:
-        CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
-        break;
-    case AV_MIX_COEFF_TYPE_FLT:
-        CONVERT_MATRIX(flt, v)
-        break;
-    default:
-        av_log(avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
-        return AVERROR(EINVAL);
-    }
-
-    /* TODO: detect situations where we can just swap around pointers
-             instead of doing matrix multiplications with 0.0 and 1.0 */
-
-    return 0;
-}