]> git.sesse.net Git - vlc/blobdiff - src/ac3_decoder/ac3_downmix.c
* Fixed a few warnings with gcc 3.0.
[vlc] / src / ac3_decoder / ac3_downmix.c
index 49203132cb6c9658c3e358100fd5211758252a00..08ecbccd028f2a3821147b85084828f8ba8162dc 100644 (file)
@@ -2,8 +2,11 @@
  * ac3_downmix.c: ac3 downmix functions
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: ac3_downmix.c,v 1.22 2001/05/06 04:32:02 sam Exp $
  *
- * Authors:
+ * Authors: Michel Kaempf <maxx@via.ecp.fr>
+ *          Aaron Holtzman <aholtzma@engr.uvic.ca>
+ *          Renaud Dartus <reno@videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *****************************************************************************/
 #include "defs.h"
 
-#include "int_types.h"
-#include "ac3_decoder.h"
-#include "ac3_internal.h"
+#include <string.h>                                              /* memcpy() */
 
-#define NORM 16384
+#include "config.h"
+#include "common.h"
+#include "threads.h"
+#include "mtime.h"
 
-typedef struct prefs_s {
-    u16 use_dolby_surround;
-    u16 dual_mono_channel_select;
-} prefs_t;
+#include "tests.h"
 
-prefs_t global_prefs = {0,0};
+#include "stream_control.h"
+#include "input_ext-dec.h"
 
-/* Pre-scaled downmix coefficients */
-static float cmixlev_lut[4] = { 0.2928, 0.2468, 0.2071, 0.2468 };
-static float smixlev_lut[4] = { 0.2928, 0.2071, 0.0   , 0.2071 };
-
-/* Downmix into _two_ channels...other downmix modes aren't implemented
- * to reduce complexity. Realistically, there aren't many machines around
- * with > 2 channel output anyways */
+#include "ac3_decoder.h"
+#include "ac3_internal.h"
+#include "ac3_downmix.h"
 
-void downmix (ac3dec_t * p_ac3dec, s16 * out_buf)
+void downmix_init (downmix_t * p_downmix)
 {
-    int j;
-    float right_tmp;
-    float left_tmp;
-    float clev,slev;
-    float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
-
-    /*
-    if (p_ac3dec->bsi.acmod > 7)
-        intf_ErrMsg( "ac3dec: (downmix) invalid acmod number\n" );
-    */
-
-    /* There are two main cases, with or without Dolby Surround */
-    if (global_prefs.use_dolby_surround) {
-        switch(p_ac3dec->bsi.acmod) {
-       case 7: /* 3/2 */
-           left      = p_ac3dec->samples.channel[0];
-           centre    = p_ac3dec->samples.channel[1];
-           right     = p_ac3dec->samples.channel[2];
-           left_sur  = p_ac3dec->samples.channel[3];
-           right_sur = p_ac3dec->samples.channel[4];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
-               left_tmp  = -1 * right_tmp;
-               right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
-               left_tmp  += 0.3204f * *left++  + 0.2265f * *centre++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 6: /* 2/2 */
-           left      = p_ac3dec->samples.channel[0];
-           right     = p_ac3dec->samples.channel[1];
-           left_sur  = p_ac3dec->samples.channel[2];
-           right_sur = p_ac3dec->samples.channel[3];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp = 0.2265f * *left_sur++ + 0.2265f * *right_sur++;
-               left_tmp  = -1 * right_tmp;
-               right_tmp += 0.3204f * *right++;
-               left_tmp  += 0.3204f * *left++ ;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 5: /* 3/1 */
-           left      = p_ac3dec->samples.channel[0];
-           centre    = p_ac3dec->samples.channel[1];
-           right     = p_ac3dec->samples.channel[2];
-           /* Mono surround */
-           right_sur = p_ac3dec->samples.channel[3];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp =  0.2265f * *right_sur++;
-               left_tmp  = - right_tmp;
-               right_tmp += 0.3204f * *right++ + 0.2265f * *centre;
-               left_tmp  += 0.3204f * *left++  + 0.2265f * *centre++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 4: /* 2/1 */
-           left      = p_ac3dec->samples.channel[0];
-           right     = p_ac3dec->samples.channel[1];
-           /* Mono surround */
-           right_sur = p_ac3dec->samples.channel[2];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp =  0.2265f * *right_sur++;
-               left_tmp  = - right_tmp;
-               right_tmp += 0.3204f * *right++;
-               left_tmp  += 0.3204f * *left++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 3: /* 3/0 */
-           left      = p_ac3dec->samples.channel[0];
-           centre    = p_ac3dec->samples.channel[1];
-           right     = p_ac3dec->samples.channel[2];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp = 0.3204f * *right++ + 0.2265f * *centre;
-               left_tmp  = 0.3204f * *left++  + 0.2265f * *centre++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 2: /* 2/0 */
-           left = p_ac3dec->samples.channel[0];
-           right = p_ac3dec->samples.channel[1];
-
-           for (j = 0; j < 256; j++) {
-               *(out_buf++) = *(left++) * NORM;
-               *(out_buf++) = *(right++) * NORM;
-           }
-           break;
-
-       case 1: /* 1/0 */
-           /* Mono program! */
-           right = p_ac3dec->samples.channel[0];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp = 0.7071f * *right++;
-
-               *(out_buf++) = right_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 0: /* 1+1 */
-           /* Dual mono, output selected by user */
-           right = p_ac3dec->samples.channel[global_prefs.dual_mono_channel_select];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp = 0.7071f * *right++;
-
-               *(out_buf++) = right_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-        }
-    } else {
-        /* Non-Dolby surround downmixes */
-        switch(p_ac3dec->bsi.acmod) {
-       case 7: /* 3/2 */
-           left      = p_ac3dec->samples.channel[0];
-           centre    = p_ac3dec->samples.channel[1];
-           right     = p_ac3dec->samples.channel[2];
-           left_sur  = p_ac3dec->samples.channel[3];
-           right_sur = p_ac3dec->samples.channel[4];
-
-           clev = cmixlev_lut[p_ac3dec->bsi.cmixlev];
-           slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp= 0.4142f * *right++ + clev * *centre   + slev * *right_sur++;
-               left_tmp = 0.4142f * *left++  + clev * *centre++ + slev * *left_sur++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 6: /* 2/2 */
-           left      = p_ac3dec->samples.channel[0];
-           right     = p_ac3dec->samples.channel[1];
-           left_sur  = p_ac3dec->samples.channel[2];
-           right_sur = p_ac3dec->samples.channel[3];
-
-           slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp= 0.4142f * *right++ + slev * *right_sur++;
-               left_tmp = 0.4142f * *left++  + slev * *left_sur++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 5: /* 3/1 */
-           left      = p_ac3dec->samples.channel[0];
-           centre    = p_ac3dec->samples.channel[1];
-           right     = p_ac3dec->samples.channel[2];
-           /* Mono surround */
-           right_sur = p_ac3dec->samples.channel[3];
-
-           clev = cmixlev_lut[p_ac3dec->bsi.cmixlev];
-           slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
-           
-           for (j = 0; j < 256; j++) {
-               right_tmp= 0.4142f * *right++ + clev * *centre   + slev * *right_sur;
-               left_tmp = 0.4142f * *left++  + clev * *centre++ + slev * *right_sur++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 4: /* 2/1 */
-           left      = p_ac3dec->samples.channel[0];
-           right     = p_ac3dec->samples.channel[1];
-           /* Mono surround */
-           right_sur = p_ac3dec->samples.channel[2];
-
-           slev = smixlev_lut[p_ac3dec->bsi.surmixlev];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp= 0.4142f * *right++ + slev * *right_sur;
-               left_tmp = 0.4142f * *left++  + slev * *right_sur++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 3: /* 3/0 */
-           left      = p_ac3dec->samples.channel[0];
-           centre    = p_ac3dec->samples.channel[1];
-           right     = p_ac3dec->samples.channel[2];
-
-           clev = cmixlev_lut[p_ac3dec->bsi.cmixlev];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp= 0.4142f * *right++ + clev * *centre;
-               left_tmp = 0.4142f * *left++  + clev * *centre++;
-
-               *(out_buf++) = left_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 2: /* 2/0 */
-           left = p_ac3dec->samples.channel[0];
-           right = p_ac3dec->samples.channel[1];
-
-           for (j = 0; j < 256; j++) {
-               *(out_buf++) = *(left++) * NORM;
-               *(out_buf++) = *(right++) * NORM;
-           }
-           break;
-
-       case 1: /* 1/0 */
-           /* Mono program! */
-           right = p_ac3dec->samples.channel[0];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp = 0.7071f * *right++;
-
-               *(out_buf++) = right_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-
-       case 0: /* 1+1 */
-           /* Dual mono, output selected by user */
-           right = p_ac3dec->samples.channel[global_prefs.dual_mono_channel_select];
-
-           for (j = 0; j < 256; j++) {
-               right_tmp = 0.7071f * *right++;
-
-               *(out_buf++) = right_tmp * NORM;
-               *(out_buf++) = right_tmp * NORM;
-           }
-           break;
-        }
+#if 0
+    if ( TestCPU (CPU_CAPABILITY_MMX) )
+    {
+               fprintf(stderr,"Using MMX for downmix\n");
+               p_downmix->downmix_3f_2r_to_2ch = downmix_3f_2r_to_2ch_kni;
+               p_downmix->downmix_2f_2r_to_2ch = downmix_2f_2r_to_2ch_kni;
+               p_downmix->downmix_3f_1r_to_2ch = downmix_3f_1r_to_2ch_kni;
+               p_downmix->downmix_2f_1r_to_2ch = downmix_2f_1r_to_2ch_kni;
+               p_downmix->downmix_3f_0r_to_2ch = downmix_3f_0r_to_2ch_kni;
+               p_downmix->stream_sample_2ch_to_s16 = stream_sample_2ch_to_s16_kni;
+       p_downmix->stream_sample_1ch_to_s16 = stream_sample_1ch_to_s16_kni;
+    } else 
+#endif
+    {
+               p_downmix->downmix_3f_2r_to_2ch = downmix_3f_2r_to_2ch_c;
+               p_downmix->downmix_2f_2r_to_2ch = downmix_2f_2r_to_2ch_c;
+               p_downmix->downmix_3f_1r_to_2ch = downmix_3f_1r_to_2ch_c;
+               p_downmix->downmix_2f_1r_to_2ch = downmix_2f_1r_to_2ch_c;
+               p_downmix->downmix_3f_0r_to_2ch = downmix_3f_0r_to_2ch_c;
+               p_downmix->stream_sample_2ch_to_s16 = stream_sample_2ch_to_s16_c;
+               p_downmix->stream_sample_1ch_to_s16 = stream_sample_1ch_to_s16_c;
     }
 }