]> git.sesse.net Git - ffmpeg/blobdiff - libswresample/rematrix.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libswresample / rematrix.c
index 27c4e1b2dc7af9895d3d70159b95f71eeb094dc6..5fa77ce5f9fae619e20a170b15c9c23d9a5c9c56 100644 (file)
@@ -26,6 +26,7 @@
 #define R(x) x
 #define SAMPLE float
 #define COEFF float
+#define INTER float
 #define RENAME(x) x ## _float
 #include "rematrix_template.c"
 #undef SAMPLE
 #undef R
 #undef ONE
 #undef COEFF
+#undef INTER
+
+#define ONE (1.0)
+#define R(x) x
+#define SAMPLE double
+#define COEFF double
+#define INTER double
+#define RENAME(x) x ## _double
+#include "rematrix_template.c"
+#undef SAMPLE
+#undef RENAME
+#undef R
+#undef ONE
+#undef COEFF
+#undef INTER
 
 #define ONE (-32768)
 #define R(x) (((x) + 16384)>>15)
 #define SAMPLE int16_t
 #define COEFF int
+#define INTER int
 #define RENAME(x) x ## _s16
 #include "rematrix_template.c"
 
@@ -184,8 +201,15 @@ static int auto_matrix(SwrContext *s)
 
     if(unaccounted & AV_CH_SIDE_LEFT){
         if(s->out_ch_layout & AV_CH_BACK_LEFT){
-            matrix[ BACK_LEFT][ SIDE_LEFT]+= 1.0;
-            matrix[BACK_RIGHT][SIDE_RIGHT]+= 1.0;
+            /* if back channels do not exist in the input, just copy side
+               channels to back channels, otherwise mix side into back */
+            if (s->in_ch_layout & AV_CH_BACK_LEFT) {
+                matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
+                matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
+            } else {
+                matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
+                matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
+            }
         }else if(s->out_ch_layout & AV_CH_BACK_CENTER){
             matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
             matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
@@ -209,6 +233,17 @@ static int auto_matrix(SwrContext *s)
         }else
             av_assert0(0);
     }
+    /* mix LFE into front left/right or center */
+    if (unaccounted & AV_CH_LOW_FREQUENCY) {
+        if (s->out_ch_layout & AV_CH_FRONT_CENTER) {
+            matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level;
+        } else if (s->out_ch_layout & AV_CH_FRONT_LEFT) {
+            matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
+            matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
+        } else
+            av_assert0(0);
+    }
+
     for(out_i=i=0; i<64; i++){
         double sum=0;
         int in_i=0;
@@ -256,6 +291,8 @@ int swri_rematrix_init(SwrContext *s){
     int nb_in  = av_get_channel_layout_nb_channels(s->in_ch_layout);
     int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout);
 
+    s->mix_any_f = NULL;
+
     if (!s->rematrix_custom) {
         int r = auto_matrix(s);
         if (r)
@@ -270,6 +307,7 @@ int swri_rematrix_init(SwrContext *s){
         *((int*)s->native_one) = 32768;
         s->mix_1_1_f = copy_s16;
         s->mix_2_1_f = sum2_s16;
+        s->mix_any_f = get_mix_any_func_s16(s);
     }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
         s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(float));
         s->native_one    = av_mallocz(sizeof(float));
@@ -279,6 +317,17 @@ int swri_rematrix_init(SwrContext *s){
         *((float*)s->native_one) = 1.0;
         s->mix_1_1_f = copy_float;
         s->mix_2_1_f = sum2_float;
+        s->mix_any_f = get_mix_any_func_float(s);
+    }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
+        s->native_matrix = av_mallocz(nb_in * nb_out * sizeof(double));
+        s->native_one    = av_mallocz(sizeof(double));
+        for (i = 0; i < nb_out; i++)
+            for (j = 0; j < nb_in; j++)
+                ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
+        *((double*)s->native_one) = 1.0;
+        s->mix_1_1_f = copy_double;
+        s->mix_2_1_f = sum2_double;
+        s->mix_any_f = get_mix_any_func_double(s);
     }else
         av_assert0(0);
     //FIXME quantize for integeres
@@ -302,13 +351,19 @@ void swri_rematrix_free(SwrContext *s){
 int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
     int out_i, in_i, i, j;
 
+    if(s->mix_any_f) {
+        s->mix_any_f(out->ch, in->ch, s->native_matrix, len);
+        return 0;
+    }
+
     av_assert0(out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
     av_assert0(in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
 
     for(out_i=0; out_i<out->ch_count; out_i++){
         switch(s->matrix_ch[out_i][0]){
         case 0:
-            memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
+            if(mustcopy)
+                memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
             break;
         case 1:
             in_i= s->matrix_ch[out_i][1];
@@ -335,6 +390,15 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus
                     }
                     ((float*)out->ch[out_i])[i]= v;
                 }
+            }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
+                for(i=0; i<len; i++){
+                    double v=0;
+                    for(j=0; j<s->matrix_ch[out_i][0]; j++){
+                        in_i= s->matrix_ch[out_i][1+j];
+                        v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
+                    }
+                    ((double*)out->ch[out_i])[i]= v;
+                }
             }else{
                 for(i=0; i<len; i++){
                     int v=0;