mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2025-11-01 22:58:48 -04:00
Added ac3dec 0.6.1 with native ALSA driver.
This commit is contained in:
parent
f2d80b5b5d
commit
28ff64db0a
50 changed files with 6094 additions and 0 deletions
535
ac3dec/libac3/downmix.c
Normal file
535
ac3dec/libac3/downmix.c
Normal file
|
|
@ -0,0 +1,535 @@
|
|||
/*
|
||||
*
|
||||
* 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 "ac3_internal.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 };
|
||||
|
||||
static void
|
||||
downmix_3f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float right_tmp;
|
||||
float left_tmp;
|
||||
float clev,slev;
|
||||
float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
|
||||
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
left_sur = samples[3];
|
||||
right_sur = samples[4];
|
||||
|
||||
clev = cmixlev_lut[bsi->cmixlev];
|
||||
slev = smixlev_lut[bsi->surmixlev];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
left_tmp = 0.4142f * *left++ + clev * *centre + slev * *left_sur++;
|
||||
right_tmp= 0.4142f * *right++ + clev * *centre++ + slev * *right_sur++;
|
||||
|
||||
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||
// printf("[0] = %.6f, [1] = %.6f\n", left_tmp, right_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
downmix_3f_2r_to_4ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float right_tmp, left_tmp, rear_right_tmp, rear_left_tmp;
|
||||
float clev,slev;
|
||||
float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
|
||||
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
left_sur = samples[3];
|
||||
right_sur = samples[4];
|
||||
|
||||
clev = cmixlev_lut[bsi->cmixlev];
|
||||
slev = smixlev_lut[bsi->surmixlev];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
left_tmp = 0.4142f * *left++ + clev * *centre;
|
||||
right_tmp= 0.4142f * *right++ + clev * *centre++;
|
||||
rear_left_tmp = 0.4142f * *left_sur++;
|
||||
rear_right_tmp = 0.4142f * *right_sur++;
|
||||
|
||||
s16_samples[j * 4 ] = (sint_16) (left_tmp * 32767.0f);
|
||||
s16_samples[j * 4 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||
s16_samples[j * 4 + 2] = (sint_16) (rear_left_tmp * 32767.0f);
|
||||
s16_samples[j * 4 + 3] = (sint_16) (rear_right_tmp * 32767.0f);
|
||||
#if 0
|
||||
printf("[0] = %.6f, [1] = %.6f, [2] = %.6f, [3] = %.6f\n",
|
||||
left_tmp, right_tmp, rear_left_tmp, rear_right_tmp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
downmix_3f_2r_to_6ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float right_tmp, centre_tmp, left_tmp, rear_right_tmp, rear_left_tmp, lfe_tmp;
|
||||
float clev,slev;
|
||||
float *centre = 0, *left = 0, *right = 0, *left_sur = 0, *right_sur = 0, *lfe = 0;
|
||||
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
left_sur = samples[3];
|
||||
right_sur = samples[4];
|
||||
lfe = samples[5];
|
||||
|
||||
clev = cmixlev_lut[bsi->cmixlev];
|
||||
slev = smixlev_lut[bsi->surmixlev];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
left_tmp = 0.4142f * *left++;
|
||||
right_tmp= 0.4142f * *right++;
|
||||
centre_tmp = 0.4142f * *centre++;
|
||||
rear_left_tmp = 0.4142f * *left_sur++;
|
||||
rear_right_tmp = 0.4142f * *right_sur++;
|
||||
lfe_tmp = bsi->lfeon ? 0.4142f * *lfe++ : (float)0.0;
|
||||
|
||||
s16_samples[j * 6 ] = (sint_16) (left_tmp * 32767.0f);
|
||||
s16_samples[j * 6 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||
s16_samples[j * 6 + 2] = (sint_16) (rear_left_tmp * 32767.0f);
|
||||
s16_samples[j * 6 + 3] = (sint_16) (rear_right_tmp * 32767.0f);
|
||||
s16_samples[j * 6 + 4] = (sint_16) (centre_tmp * 32767.0f);
|
||||
s16_samples[j * 6 + 5] = (sint_16) (lfe_tmp * 32767.0f);
|
||||
#if 0
|
||||
printf("[0] = %.6f, [1] = %.6f, [2] = %.6f, [3] = %.6f, [4] = %.6f, [5] = %.6f\n",
|
||||
left_tmp, right_tmp, rear_left_tmp, rear_right_tmp,
|
||||
centre_tmp, lfe_tmp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
downmix_2f_2r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float right_tmp;
|
||||
float left_tmp;
|
||||
float slev;
|
||||
float *left = 0, *right = 0, *left_sur = 0, *right_sur = 0;
|
||||
|
||||
left = samples[0];
|
||||
right = samples[1];
|
||||
left_sur = samples[2];
|
||||
right_sur = samples[3];
|
||||
|
||||
slev = smixlev_lut[bsi->surmixlev];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
left_tmp = 0.4142f * *left++ + slev * *left_sur++;
|
||||
right_tmp= 0.4142f * *right++ + slev * *right_sur++;
|
||||
|
||||
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
downmix_3f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float right_tmp;
|
||||
float left_tmp;
|
||||
float clev,slev;
|
||||
float *centre = 0, *left = 0, *right = 0, *sur = 0;
|
||||
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
//Mono surround
|
||||
sur = samples[3];
|
||||
|
||||
clev = cmixlev_lut[bsi->cmixlev];
|
||||
slev = smixlev_lut[bsi->surmixlev];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
left_tmp = 0.4142f * *left++ + clev * *centre++ + slev * *sur;
|
||||
right_tmp= 0.4142f * *right++ + clev * *centre + slev * *sur++;
|
||||
|
||||
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
downmix_2f_1r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float right_tmp;
|
||||
float left_tmp;
|
||||
float slev;
|
||||
float *left = 0, *right = 0, *sur = 0;
|
||||
|
||||
left = samples[0];
|
||||
right = samples[1];
|
||||
//Mono surround
|
||||
sur = samples[2];
|
||||
|
||||
slev = smixlev_lut[bsi->surmixlev];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
left_tmp = 0.4142f * *left++ + slev * *sur;
|
||||
right_tmp= 0.4142f * *right++ + slev * *sur++;
|
||||
|
||||
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
downmix_3f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float right_tmp;
|
||||
float left_tmp;
|
||||
float clev;
|
||||
float *centre = 0, *left = 0, *right = 0;
|
||||
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
|
||||
clev = cmixlev_lut[bsi->cmixlev];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
left_tmp = 0.4142f * *left++ + clev * *centre;
|
||||
right_tmp= 0.4142f * *right++ + clev * *centre++;
|
||||
|
||||
s16_samples[j * 2 ] = (sint_16) (left_tmp * 32767.0f);
|
||||
s16_samples[j * 2 + 1] = (sint_16) (right_tmp * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
downmix_2f_0r_to_2ch(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float *left = 0, *right = 0;
|
||||
|
||||
left = samples[0];
|
||||
right = samples[1];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
s16_samples[j * 2 ] = (sint_16) (*left++ * 32767.0f);
|
||||
s16_samples[j * 2 + 1] = (sint_16) (*right++ * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
downmix_1f_0r_to_2ch(float *centre,sint_16 *s16_samples)
|
||||
{
|
||||
uint_32 j;
|
||||
float tmp;
|
||||
|
||||
//Mono program!
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
tmp = 32767.0f * 0.7071f * *centre++;
|
||||
|
||||
s16_samples[j * 2 ] = s16_samples[j * 2 + 1] = (sint_16) tmp;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Downmix into 2 or 4 channels (4 ch isn't in quite yet)
|
||||
//
|
||||
// The downmix function names have the following format
|
||||
//
|
||||
// downmix_Xf_Yr_to_[2|4|6]ch[_dolby]
|
||||
//
|
||||
// where X = number of front channels
|
||||
// Y = number of rear channels
|
||||
// [2|4] = number of output channels
|
||||
// [_dolby] = with or without dolby surround mix
|
||||
//
|
||||
|
||||
void downmix(bsi_t* bsi, stream_samples_t samples,sint_16 *s16_samples)
|
||||
{
|
||||
if(bsi->acmod > 7)
|
||||
dprintf("(downmix) invalid acmod number\n");
|
||||
|
||||
//
|
||||
//There are two main cases, with or without Dolby Surround
|
||||
//
|
||||
if(ac3_config.flags & AC3_DOLBY_SURR_ENABLE)
|
||||
{
|
||||
fprintf(stderr,"Dolby Surround Mixes not currently enabled\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//Non-Dolby surround downmixes
|
||||
switch(bsi->acmod)
|
||||
{
|
||||
// 3/2
|
||||
case 7:
|
||||
switch (ac3_config.num_output_ch) {
|
||||
case 2:
|
||||
downmix_3f_2r_to_2ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
case 4:
|
||||
downmix_3f_2r_to_4ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
case 6:
|
||||
downmix_3f_2r_to_6ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unsupported 3/2 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
// 2/2
|
||||
case 6:
|
||||
if (ac3_config.num_output_ch != 2) {
|
||||
fprintf(stderr,"unsupported 2/2 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
downmix_2f_2r_to_2ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
|
||||
// 3/1
|
||||
case 5:
|
||||
if (ac3_config.num_output_ch != 2) {
|
||||
fprintf(stderr,"unsupported 3/1 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
downmix_3f_1r_to_2ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
|
||||
// 2/1
|
||||
case 4:
|
||||
if (ac3_config.num_output_ch != 2) {
|
||||
fprintf(stderr,"unsupported 2/1 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
downmix_2f_1r_to_2ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
|
||||
// 3/0
|
||||
case 3:
|
||||
if (ac3_config.num_output_ch != 2) {
|
||||
fprintf(stderr,"unsupported 3/0 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
downmix_3f_0r_to_2ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
|
||||
// 2/0
|
||||
case 2:
|
||||
if (ac3_config.num_output_ch != 2) {
|
||||
fprintf(stderr,"unsupported 2/0 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
downmix_2f_0r_to_2ch(bsi,samples,s16_samples);
|
||||
break;
|
||||
|
||||
// 1/0
|
||||
case 1:
|
||||
if (ac3_config.num_output_ch != 2) {
|
||||
fprintf(stderr,"unsupported 1/0 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
downmix_1f_0r_to_2ch(samples[0],s16_samples);
|
||||
break;
|
||||
|
||||
// 1+1
|
||||
case 0:
|
||||
if (ac3_config.num_output_ch != 2) {
|
||||
fprintf(stderr,"unsupported 1/1 channels %d\n", ac3_config.num_output_ch);
|
||||
exit(1);
|
||||
}
|
||||
downmix_1f_0r_to_2ch(samples[ac3_config.dual_mono_ch_sel],s16_samples);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
//the dolby mixes lay here for the time being
|
||||
switch(bsi->acmod)
|
||||
{
|
||||
// 3/2
|
||||
case 7:
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
left_sur = samples[3];
|
||||
right_sur = samples[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++;
|
||||
|
||||
samples[1][j] = right_tmp;
|
||||
samples[0][j] = left_tmp;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// 2/2
|
||||
case 6:
|
||||
left = samples[0];
|
||||
right = samples[1];
|
||||
left_sur = samples[2];
|
||||
right_sur = samples[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++ ;
|
||||
|
||||
samples[1][j] = right_tmp;
|
||||
samples[0][j] = left_tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
// 3/1
|
||||
case 5:
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
//Mono surround
|
||||
right_sur = samples[3];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
right_tmp = 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++;
|
||||
|
||||
samples[1][j] = right_tmp;
|
||||
samples[0][j] = left_tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
// 2/1
|
||||
case 4:
|
||||
left = samples[0];
|
||||
right = samples[1];
|
||||
//Mono surround
|
||||
right_sur = samples[2];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
right_tmp = 0.2265f * *right_sur++;
|
||||
left_tmp = -1 * right_tmp;
|
||||
right_tmp += 0.3204f * *right++;
|
||||
left_tmp += 0.3204f * *left++;
|
||||
|
||||
samples[1][j] = right_tmp;
|
||||
samples[0][j] = left_tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
// 3/0
|
||||
case 3:
|
||||
left = samples[0];
|
||||
centre = samples[1];
|
||||
right = samples[2];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
right_tmp = 0.3204f * *right++ + 0.2265f * *centre;
|
||||
left_tmp = 0.3204f * *left++ + 0.2265f * *centre++;
|
||||
|
||||
samples[1][j] = right_tmp;
|
||||
samples[0][j] = left_tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
// 2/0
|
||||
case 2:
|
||||
//Do nothing!
|
||||
break;
|
||||
|
||||
// 1/0
|
||||
case 1:
|
||||
//Mono program!
|
||||
right = samples[0];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
right_tmp = 0.7071f * *right++;
|
||||
|
||||
samples[1][j] = right_tmp;
|
||||
samples[0][j] = right_tmp;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// 1+1
|
||||
case 0:
|
||||
//Dual mono, output selected by user
|
||||
right = samples[ac3_config.dual_mono_ch_sel];
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
right_tmp = 0.7071f * *right++;
|
||||
|
||||
samples[1][j] = right_tmp;
|
||||
samples[0][j] = right_tmp;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue