⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downmix.c

📁 关于AC3的解码程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*       
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* File Name: downmix.c							
*
* Reference:
*
* Author:                                              
*
* Description:
*
* 	
* 
* History:
* 02/23/2005
*  
*
*CodeReview Log:
* 
*/
#include <stdio.h>
#include <math.h>

#include "ac3.h"
#include "decode.h"
#include "downmix.h"

const static float SQRT2_2 = 0.707106781; /* (SQRT(2))/2 */

/* these mixing gains are for the downmixing routines.  They do not directly
   correspond to elements in the AC3 bitstream */
static float lrmixgain;  /* front L/R channel mix gain */
static float lfemixgain; /* lfe channel mix gain */
static float cmixgain; /* center channel mix gain */
static float smixgain; /* surround channel mix gain */
static float slev,clev;

extern int m_gainlevel;
extern int m_gain2level;
extern int m_gaincenter;
extern int m_gainrear;
extern int m_gainlfe;

#define	GAINSCALE	32767.0


void conv480to441( sint_16 *out_samples, long samp_count, long chan )
{
	sint_16 *source, *dest, s1,s2,s3, lp;
	long	i, cl, tmp;
	double	ind=0, inc=48000/44100.0, h1, h2, f1, f2;

	source = dest = out_samples;
	for(i=0; i<samp_count ; i++){
		lp = ind;
		if ( lp>255 ) lp = 255;
		lp = lp*chan;

		h2 = modf( ind, (double*)&tmp );
		h1 = 1.0 - h2;

		for( cl=0; cl < chan; cl++){
			s1 = source[ lp+cl ];			// read samples
			s2 = source[ lp+cl+2 ];
			f1 = s1*h1;						// scale samples
			f2 = s2*h2;
			s3 = (f1+f2);					// average the samples
			if ( lp>=(255*2) )
				s3=s1;
			*out_samples++ = s3;			// store result
		}

		ind += inc;
	}
}


void PerformGlobalGain( sint_16 *out_samples )
{
	int i;
	short left,right, *samples = out_samples;
	double gainlevel, gain;


	if ( m_gainlevel<1 ) return;
	gainlevel = 1+ (m_gainlevel/100.0);

	for ( i=0; i < 256; ++i )
	{
			left = *samples++;
			right = *samples++;

			gain = (((32000-abs(left))/32000.0) * gainlevel);
			*out_samples++ = (sint_16) (left * gain);

			gain = (((32000-abs(right))/32000.0) * gainlevel);
			*out_samples++ = (sint_16) (right * gain);
	}
}

void PerformCurvedGlobalGain( sint_16 *out_samples )
{
	int i;
	short left,right, *samples = out_samples;
	double gainlevel, gain;


	if ( m_gain2level<1 ) return;
	gainlevel = 1+ (m_gain2level/100.0);

	for ( i=0; i < 256; ++i )
	{
			left = *samples++;
			right = *samples++;

			gain = (((32000-abs(left))/32000.0));
			gain = gain * gain * gainlevel;
			*out_samples++ = (sint_16) (left * gain);

			gain = (((32000-abs(right))/32000.0));
			gain = gain * gain * gainlevel;
			*out_samples++ = (sint_16) (right * gain);
	}
}



void PerformPreSampleGain( stream_samples_t *samples )
{
	int i;
	float gainlevel, gain;
	register float *sam, *sam3, *sam4, sample;

	if ( m_gaincenter>1 ){
		gainlevel = 1+ (m_gaincenter/100.0);
		if( m_gaincenter > 999 ) gainlevel = 0;

		sam = samples->channel[1];

		for ( i=0; i < 256; ++i )
		{
				sample = *sam;

				gain = (((1-fabs(sample))/1.0));
				*sam++ = sample * gain * gain * gainlevel;
		}
	}
	if ( m_gainrear>1 ){
		gainlevel = 1+ (m_gainrear/100.0);
		if( m_gainrear > 999 ) gainlevel = 0;

		sam3 = samples->channel[3];
		sam4 = samples->channel[4];

		for ( i=0; i < 256; ++i )
		{
				sample = *sam3;
				gain = (((1-fabs(sample))/1.0));
				*sam3++ = sample * gain * gain * gainlevel;
				sample = *sam4;
				gain = (((1-fabs(sample))/1.0));
				*sam4++ = sample * gain * gain * gainlevel;
		}
	}
	if ( m_gainlfe>1 ){
		gainlevel = 1+ (m_gainlfe/100.0);
		if( m_gainlfe > 999 ) gainlevel = 0;

		sam = samples->channel[5];

		for ( i=0; i < 256; ++i )
		{
				sample = *sam;

				gain = (((1-fabs(sample))/1.0));
				*sam++ = sample * gain * gain * gainlevel;
		}
	}
}


/* AC3 5.1 channel downmix, 3 front, 2 rear channels, LFE */
void
mix321to20( stream_samples_t *samples, sint_16 *out_samples, int full51output )
{
	int i;

	sint_32 left,	/* source-sample front left */
		center,	/* source-sample front center */
		right,  /* source-sample front right */
		rear,  /* source-sample (mono) rear left and right */
		lfe;	/* low frequency effects channel */

	sint_16 Acc1, Acc2; /* accumulators */
	register float *sam0, *sam1, *sam2, *sam3, *sam4, *sam5;


	sam0 = samples->channel[0];
	sam1 = samples->channel[1];
	sam2 = samples->channel[2];
	sam3 = samples->channel[3];
	sam4 = samples->channel[4];
	sam5 = samples->channel[5];

	/* AC3 5.1 channel downmix, 3 front, 2 rear channels */
	for ( i=0; i < 256; ++i )
	{
		left = *sam0++ * lrmixgain;
		center= *sam1++ * cmixgain;
		right = *sam2++ * lrmixgain;
		rear = (*sam3++ + *sam4++) * smixgain;
		lfe = *sam5++ * lfemixgain;

		Acc1 = ( 2 + left + center + lfe - rear ) >> 2;
		Acc2 = ( 2 + right+ center + lfe + rear ) >> 2;

		if( full51output ){
			*out_samples++ = left;
			*out_samples++ = right;
			*out_samples++ = center;
			*out_samples++ = rear;
			*out_samples++ = lfe;
		} else {
			*out_samples++ = Acc1;
			*out_samples++ = Acc2;
		}
	}
}

/* AC3 5.0 channel downmix, 3 front, 2 rear channels */
void mix320to20( stream_samples_t *samples, sint_16 *out_samples )
{
	int i;
	sint_32 left,	/* source-sample front left */
		center,	/* source-sample front center */
		right,  /* source-sample front right */
		rear;  /* source-sample (mono) rear left and right */

	sint_16 Acc1, Acc2; /* accumulators */
	register float *sam0, *sam1, *sam2, *sam3, *sam4;


	sam0 = samples->channel[0];
	sam1 = samples->channel[1];
	sam2 = samples->channel[2];
	sam3 = samples->channel[3];
	sam4 = samples->channel[4];

	/* AC3 5.0 channel downmix, 3 front, 2 rear channels */
	for ( i=0; i < 256; ++i )
	{
		left = *sam0++ * lrmixgain;
		center= *sam1++ * cmixgain;
		right = *sam2++ * lrmixgain;
		rear = (*sam3++ + *sam4++) * smixgain;

		Acc1 = ( 2 + left + center - rear ) >> 2;
		Acc2 = ( 2 + right+ center + rear ) >> 2;

		*out_samples++ = Acc1;
		*out_samples++ = Acc2;
	}
}


/* AC3 2/2 channel downmix, 2 front (left/right), 2 rear channels */
void
mix220to20( stream_samples_t *samples, sint_16 *out_samples )
{
	int i;

	sint_32 left,	/* source-sample front left */
		right,  /* source-sample front right */
		rear;  /* source-sample (mono) rear left and right */

	sint_16 Acc1, Acc2; /* accumulators */
	register float *sam0, *sam1, *sam2, *sam3;


	sam0 = samples->channel[0];
	sam1 = samples->channel[1];
	sam2 = samples->channel[2];
	sam3 = samples->channel[3];

	/* AC3 2/2 channel downmix, 2 front, 2 rear channels */
	for ( i=0; i < 256; ++i )
	{
		left = *sam0++ * lrmixgain;
		right = *sam1++ * lrmixgain;
		rear = (*sam2++ + *sam3++) * smixgain;

		Acc1 = ( 2 + left - rear ) >> 2;
		Acc2 = ( 2 + right+ rear ) >> 2;

		*out_samples++ = Acc1;
		*out_samples++ = Acc2;
	}
}


/* AC3 2/2.1 channel downmix, 2 front (left/right), 2 rear channels, lfe */
void
mix221to20( stream_samples_t *samples, sint_16 *out_samples )
{
	int i;

	sint_32 left,	/* source-sample front left */
		right,  /* source-sample front right */
		rear,  /* source-sample (mono) rear left and right */
		lfe;	/* low frequency effects channel */

	sint_16 Acc1, Acc2; /* accumulators */
	register float *sam0, *sam1, *sam2, *sam3, *sam5;


	sam0 = samples->channel[0];
	sam1 = samples->channel[1];
	sam2 = samples->channel[2];
	sam3 = samples->channel[3];
	sam5 = samples->channel[5];

	/* AC3 2/2.1 channel downmix, 2 front, 2 rear channels, lfe */
	for ( i=0; i < 256; ++i )
	{
		left = *sam0++ * lrmixgain;
		right = *sam1++ * lrmixgain;
		rear = (*sam2++ + *sam3++) * smixgain;
		lfe = *sam5++ * lfemixgain;

		Acc1 = ( 2 + left + lfe - rear ) >> 2;
		Acc2 = ( 2 + right+ lfe + rear ) >> 2;

		*out_samples++ = Acc1;
		*out_samples++ = Acc2;
	}
}


/* AC3 3/1.1 channel downmix, 3 front, 1 rear channel, LFE */
void
mix311to20( stream_samples_t *samples, sint_16 *out_samples )
{
	int i;

	sint_32 left,	/* source-sample front left */
		center,	/* source-sample front center */
		right,  /* source-sample front right */
		rear,  /* source-sample (mono) rear */
		lfe;	/* low frequency effects channel */

	sint_16 Acc1, Acc2; /* accumulators */
	register float *sam0, *sam1, *sam2, *sam3, *sam5;


	sam0 = samples->channel[0];
	sam1 = samples->channel[1];
	sam2 = samples->channel[2];
	sam3 = samples->channel[3];
	sam5 = samples->channel[5];

	/* AC3 3/1.1 channel downmix, 3 front, 1 rear channel, lfe */
	for ( i=0; i < 256; ++i )
	{
		left = *sam0++ * lrmixgain;
		center= *sam1++ * cmixgain;
		right = *sam2++ * lrmixgain;
		rear = *sam3++ * smixgain * SQRT2_2;
		lfe = *sam5++ * lfemixgain;

		Acc1 = ( 2 + left + center + lfe - rear ) >> 2;
		Acc2 = ( 2 + right+ center + lfe + rear ) >> 2;

		*out_samples++ = Acc1;
		*out_samples++ = Acc2;
	}
}



/* AC3 3/1.0 channel downmix, 3 front, 1 rear channel */
void
mix310to20( stream_samples_t *samples, sint_16 *out_samples )
{
	int i;

	sint_32 left,	/* source-sample front left */
		center,	/* source-sample front center */
		right,  /* source-sample front right */
		rear;  /* source-sample (mono) rear */

	sint_16 Acc1, Acc2; /* accumulators */
	register float *sam0, *sam1, *sam2, *sam3;


	sam0 = samples->channel[0];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -