downmix.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:8k
- /*
- *
- * downmix.c
- *
- * Copyright (C) Aaron Holtzman - Sept 1999
- *
- * Originally based on code by Yuqing Deng.
- *
- * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
- *
- * ac3dec is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * ac3dec is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include "ac3.h"
- #include "decode.h"
- #include "downmix.h"
- #include "debug.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 */
- void downmix(bsi_t* bsi, stream_samples_t* stream_sample)
- {
- 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(bsi->acmod > 7)
- dprintf("(downmix) invalid acmod numbern");
- //There are two main cases, with or without Dolby Surround
- if(global_prefs.use_dolby_surround)
- {
- switch(bsi->acmod)
- {
- // 3/2
- case 7:
- left = stream_sample->channel[0];
- centre = stream_sample->channel[1];
- right = stream_sample->channel[2];
- left_sur = stream_sample->channel[3];
- right_sur = stream_sample->channel[4];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.2265 * *left_sur++ + 0.2265 * *right_sur++;
- left_tmp = -1 * right_tmp;
- right_tmp += 0.3204 * *right++ + 0.2265 * *centre;
- left_tmp += 0.3204 * *left++ + 0.2265 * *centre++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- break;
- // 2/2
- case 6:
- left = stream_sample->channel[0];
- right = stream_sample->channel[1];
- left_sur = stream_sample->channel[2];
- right_sur = stream_sample->channel[3];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.2265 * *left_sur++ + 0.2265 * *right_sur++;
- left_tmp = -1 * right_tmp;
- right_tmp += 0.3204 * *right++;
- left_tmp += 0.3204 * *left++ ;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- break;
- // 3/1
- case 5:
- left = stream_sample->channel[0];
- centre = stream_sample->channel[1];
- right = stream_sample->channel[2];
- //Mono surround
- right_sur = stream_sample->channel[3];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.2265 * *right_sur++;
- left_tmp = -1 * right_tmp;
- right_tmp += 0.3204 * *right++ + 0.2265 * *centre;
- left_tmp += 0.3204 * *left++ + 0.2265 * *centre++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- break;
- // 2/1
- case 4:
- left = stream_sample->channel[0];
- right = stream_sample->channel[1];
- //Mono surround
- right_sur = stream_sample->channel[2];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.2265 * *right_sur++;
- left_tmp = -1 * right_tmp;
- right_tmp += 0.3204 * *right++;
- left_tmp += 0.3204 * *left++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- break;
- // 3/0
- case 3:
- left = stream_sample->channel[0];
- centre = stream_sample->channel[1];
- right = stream_sample->channel[2];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.3204 * *right++ + 0.2265 * *centre;
- left_tmp = 0.3204 * *left++ + 0.2265 * *centre++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- break;
- // 2/0
- case 2:
- //Do nothing!
- break;
- // 1/0
- case 1:
- //Mono program!
- right = stream_sample->channel[0];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.7071 * *right++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = right_tmp;
- }
-
- break;
- // 1+1
- case 0:
- //Dual mono, output selected by user
- right = stream_sample->channel[global_prefs.dual_mono_channel_select];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.7071 * *right++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = right_tmp;
- }
- break;
- }
- }
- else
- {
- //Non-Dolby surround downmixes
- switch(bsi->acmod)
- {
- // 3/2
- case 7:
- left = stream_sample->channel[0];
- centre = stream_sample->channel[1];
- right = stream_sample->channel[2];
- left_sur = stream_sample->channel[3];
- right_sur = stream_sample->channel[4];
- clev = cmixlev_lut[bsi->cmixlev];
- slev = smixlev_lut[bsi->surmixlev];
- for (j = 0; j < 256; j++)
- {
- right_tmp= 0.4142 * *right++ + clev * *centre + slev * *right_sur++;
- left_tmp = 0.4142 * *left++ + clev * *centre++ + slev * *left_sur++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- break;
- // 2/2
- case 6:
- left = stream_sample->channel[0];
- right = stream_sample->channel[1];
- left_sur = stream_sample->channel[2];
- right_sur = stream_sample->channel[3];
- slev = smixlev_lut[bsi->surmixlev];
- for (j = 0; j < 256; j++)
- {
- right_tmp= 0.4142 * *right++ + slev * *right_sur++;
- left_tmp = 0.4142 * *left++ + slev * *left_sur++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- // 3/1
- case 5:
- left = stream_sample->channel[0];
- centre = stream_sample->channel[1];
- right = stream_sample->channel[2];
- //Mono surround
- right_sur = stream_sample->channel[3];
- clev = cmixlev_lut[bsi->cmixlev];
- slev = smixlev_lut[bsi->surmixlev];
- for (j = 0; j < 256; j++)
- {
- right_tmp= 0.4142 * *right++ + clev * *centre + slev * *right_sur;
- left_tmp = 0.4142 * *left++ + clev * *centre++ + slev * *right_sur++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
-
- break;
- // 2/1
- case 4:
- left = stream_sample->channel[0];
- right = stream_sample->channel[1];
- //Mono surround
- right_sur = stream_sample->channel[2];
- slev = smixlev_lut[bsi->surmixlev];
- for (j = 0; j < 256; j++)
- {
- right_tmp= 0.4142 * *right++ + slev * *right_sur;
- left_tmp = 0.4142 * *left++ + slev * *right_sur++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
- // 3/0
- case 3:
- left = stream_sample->channel[0];
- centre = stream_sample->channel[1];
- right = stream_sample->channel[2];
- clev = cmixlev_lut[bsi->cmixlev];
- for (j = 0; j < 256; j++)
- {
- right_tmp= 0.4142 * *right++ + clev * *centre;
- left_tmp = 0.4142 * *left++ + clev * *centre++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = left_tmp;
- }
-
- break;
- case 2:
- //Do nothing!
- break;
- // 1/0
- case 1:
- //Mono program!
- right = stream_sample->channel[0];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.7071 * *right++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = right_tmp;
- }
-
- break;
- // 1+1
- case 0:
- //Dual mono, output selected by user
- right = stream_sample->channel[global_prefs.dual_mono_channel_select];
- for (j = 0; j < 256; j++)
- {
- right_tmp = 0.7071 * *right++;
- stream_sample->channel[1][j] = right_tmp;
- stream_sample->channel[0][j] = right_tmp;
- }
- break;
- }
- }
- }