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

📄 libac3dec.c

📁 关于AC3的解码程序
💻 C
字号:
/*
* 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: libac3dec.c							
*
* Reference:
*
* Author: Li Feng,  fli_linux@yahoo.com.cn                                                 
*
* Description:
*
* 	
* 
* History:
* 02/23/2005  Li Feng    Created
*  
*
*CodeReview Log:
* 
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/timeb.h>
#include <stdarg.h>
#include <time.h>

#include "parse.h"
#include "ac3.h"
#include "decode.h"
#include "bitstream.h"
#include "imdct.h"
#include "exponent.h"
#include "mantissa.h"
#include "bit_allocate.h"
#include "crc.h"
#include "libac3dec.h"
#include "rematrix.h"
#include "downmix.h"

const struct frmsize_s frmsizecode_tbl[] = {
	{ 32  ,{64   ,69   ,96   } },
	{ 32  ,{64   ,70   ,96   } },
	{ 40  ,{80   ,87   ,120  } },
	{ 40  ,{80   ,88   ,120  } },
	{ 48  ,{96   ,104  ,144  } },
	{ 48  ,{96   ,105  ,144  } },
	{ 56  ,{112  ,121  ,168  } },
	{ 56  ,{112  ,122  ,168  } },
	{ 64  ,{128  ,139  ,192  } },
	{ 64  ,{128  ,140  ,192  } },
	{ 80  ,{160  ,174  ,240  } },
	{ 80  ,{160  ,175  ,240  } },
	{ 96  ,{192  ,208  ,288  } },
	{ 96  ,{192  ,209  ,288  } },
	{ 112 ,{224  ,243  ,336  } },
	{ 112 ,{224  ,244  ,336  } },
	{ 128 ,{256  ,278  ,384  } },
	{ 128 ,{256  ,279  ,384  } },
	{ 160 ,{320  ,348  ,480  } },
	{ 160 ,{320  ,349  ,480  } },
	{ 192 ,{384  ,417  ,576  } },
	{ 192 ,{384  ,418  ,576  } },
	{ 224 ,{448  ,487  ,672  } },
	{ 224 ,{448  ,488  ,672  } },
	{ 256 ,{512  ,557  ,768  } },
	{ 256 ,{512  ,558  ,768  } },
	{ 320 ,{640  ,696  ,960  } },
	{ 320 ,{640  ,697  ,960  } },
	{ 384 ,{768  ,835  ,1152 } },
	{ 384 ,{768  ,836  ,1152 } },
	{ 448 ,{896  ,975  ,1344 } },
	{ 448 ,{896  ,976  ,1344 } },
	{ 512 ,{1024 ,1114 ,1536 } },
	{ 512 ,{1024 ,1115 ,1536 } },
	{ 576 ,{1152 ,1253 ,1728 } },
	{ 576 ,{1152 ,1254 ,1728 } },
	{ 640 ,{1280 ,1393 ,1920 } },
	{ 640 ,{1280 ,1394 ,1920 } }};

#define BUFFER_SIZE1 3072
#define DECODE_MAGIC_NUMBER 0xdeadbeef

//static void decode_find_sync(bitstream_t *bs);
static int decode_resync(bitstream_t *bs);

static stream_coeffs_t stream_coeffs;
static stream_samples_t stream_samples;
static audblk_t audblk;
static bsi_t bsi;
static syncinfo_t syncinfo;

int m_gainlevel = 0;
int m_gain2level = 0;
int m_gaincenter = 0;
int m_gainrear = 0;
int m_gainlfe = 0;

int AC3_GetAudioInfo(uint_32* pnFrameSize, uint_32 *pnSampleRate,uint_8 *pAc3Header)
{
	uint_8 fscod;
	uint_8 frmsizecode;

	if(!(pAc3Header[0]==0x0B && pAc3Header[1]==0x77))
	{
		*pnSampleRate = 0;
		return 0;
	}
	fscod = (pAc3Header[4] & 0xC0) >> 6;
	switch (fscod)
	{
	case 2:
		*pnSampleRate = 32000;
		break;
	case 1:
		*pnSampleRate = 44100;
		break;
	case 0:
		*pnSampleRate = 48000;
		break;
	default:
		*pnSampleRate = 0;
		return 0;
	}
	frmsizecode = pAc3Header[4] & 0x3F;

	*pnFrameSize = frmsizecode_tbl[frmsizecode].frm_size[fscod];
	*pnFrameSize = *pnFrameSize * 2;

	return 1;
}

int AC3_SampleConvert(sint_16 *pPcmData, uint_32 *pnPcmDataLen, uint_8* pAc3Buf, uint_32 nAc3DataLen)
{
	int i;
	bitstream_t *bs;	
	long SampleRate = 0; /* bitstream sample-rate */
	uint_32 cbErrors = 0; /* bitstream error count returned by 							decode_sanity_check() */
	uint_32 cbMantErrors, cbExpErrors;		/* error counters for mantissa & exponent unpacking errors */
	bsi_t bsi_blank = {0};
    static audblk_t audblk_blank = {0};

	bs = bitstream_open(pAc3Buf, pAc3Buf+nAc3DataLen);

	imdct_init();
	/* initialize decoder and counter variables */

	(bsi) = bsi_blank;
	(audblk) = audblk_blank;
	decode_sanity_check_init();

	bsi_blank = bsi;
	audblk_blank = audblk;

	cbErrors = 0; 

	audblk = audblk_blank; /* clear out audioblock */

  	if(!(decode_resync(bs)))
	{
		return  0;
	}

	bsi = bsi_blank; /* v0.04 wipe bsi clear, not really necessary */

	parse_syncinfo(&syncinfo,bs);

	parse_bsi(&bsi,bs);

	switch (syncinfo.fscod)
	{
		case 2:
			SampleRate = 32000;
			break;
		case 1:
			SampleRate = 44100;
			break;
		case 0:
			SampleRate = 48000;
			break;
		default:
			return 0;
	}

		/* reset bitstream error counters */
	cbErrors =
	cbExpErrors =
	cbMantErrors = 0;
	
	memset(pPcmData, 0, BUFFER_SIZE1*2);
	*pnPcmDataLen = 0;
	for(i=0; i < 6; i++)
	{
		long buf_offset;
		parse_audblk(&bsi,&audblk,bs,i);					// CPU time 10%

		cbExpErrors = exponent_unpack(&bsi,&audblk);
		if(cbExpErrors > 0)
		{
			return 0;
			cbExpErrors =0;
		}

		bit_allocate(syncinfo.fscod,&bsi,&audblk);			// CPU TIME 1.2%

		if ( bsi.nfchans > 6 )
		{ 
			bsi.nfchans = 0; 
			return 0;//(LPBYTE) out_buf; 
		}

		cbMantErrors = mantissa_unpack(&bsi,&audblk,bs);	// CPU TIME 62.0%
		if( cbMantErrors > 0)
		{
			return 0;
            cbMantErrors = 0;
		}

		uncouple(&bsi,&audblk,&stream_coeffs);				// CPU TIME 1.7%

		if(bsi.acmod == 0x2)
			rematrix(&audblk,&stream_coeffs);				// CPU TIME 0.1%

		imdct(&bsi,&audblk,&stream_coeffs,&stream_samples);	// CPU TIME 11.2%

		buf_offset = i * 512;

		downmix( &stream_samples, pPcmData+buf_offset, &bsi, 0 );
	} /* endfor ( i = 0 ... ) */
	*pnPcmDataLen = 6*512*2;

	cbErrors = decode_sanity_check();
	if(cbErrors > 0)
	{
		return 0;
	}

	parse_auxdata(&syncinfo,bs);			// CPU TIME 2.0%
	if(!crc_validate())
	{
		return 0;
	}
	return 1;
}

static  int decode_resync(bitstream_t *bs) 
{
	uint_16 sync_word;
	//int i = 0;

	/* Make sure we sync'ed */
	sync_word = bitstream_get(bs,16);
	if(sync_word == 0x0b77 )
	{
		crc_init();
		return 1;
	}
	return 0;
}


void decode_sanity_check_init(void)
{
	syncinfo.magic = DECODE_MAGIC_NUMBER;
	bsi.magic = DECODE_MAGIC_NUMBER;
	audblk.magic1 = DECODE_MAGIC_NUMBER;
	audblk.magic2 = DECODE_MAGIC_NUMBER;
	audblk.magic3 = DECODE_MAGIC_NUMBER;
}


/* decode_sanity_check() now returns # errors detected */

long decode_sanity_check(void)
{
	int i;
	long cbError = 0; /* error count */

	if(syncinfo.magic != DECODE_MAGIC_NUMBER)
	{
		++cbError;
	}
	
	if(bsi.magic != DECODE_MAGIC_NUMBER)
	{
		++cbError;
	}

	if(audblk.magic1 != DECODE_MAGIC_NUMBER)
	{
		++cbError;
	}

	if(audblk.magic2 != DECODE_MAGIC_NUMBER)
	{
		++cbError;
	}

	if(audblk.magic3 != DECODE_MAGIC_NUMBER)
	{
		++cbError;
	}

	for(i = 0;i < 5 ; i++)
	{
		if (audblk.fbw_exp[i][255] !=0 || audblk.fbw_exp[i][254] !=0 || 
				audblk.fbw_exp[i][253] !=0)
		{
			audblk.fbw_exp[i][255] = 0;
			audblk.fbw_exp[i][254] = 0;
			audblk.fbw_exp[i][253] = 0;
			++cbError;
		}

		if (audblk.fbw_bap[i][255] !=0 || audblk.fbw_bap[i][254] !=0 || 
				audblk.fbw_bap[i][253] !=0)
		{	
			audblk.fbw_bap[i][255] = 0;
			audblk.fbw_bap[i][254] = 0;
			audblk.fbw_bap[i][253] = 0;
			++cbError;
		}

		if (audblk.chmant[i][255] !=0 || audblk.chmant[i][254] !=0 || 
				audblk.chmant[i][253] !=0)
		{
			audblk.chmant[i][255] = 0;
			audblk.chmant[i][254] = 0;
			audblk.chmant[i][253] = 0;
			++cbError;
		}
	} /* endfor ( i=0 ... ) */

	if (audblk.cpl_exp[255] !=0 || audblk.cpl_exp[254] !=0 || 
			audblk.cpl_exp[253] !=0)
	{
		audblk.cpl_exp[255] = 0;
		audblk.cpl_exp[254] = 0;
		audblk.cpl_exp[253] = 0;
		++cbError;
	}

	if (audblk.cpl_bap[255] !=0 || audblk.cpl_bap[254] !=0 || 
			audblk.cpl_bap[253] !=0)
	{
		audblk.cpl_bap[255] = 0;
		audblk.cpl_bap[254] = 0;
		audblk.cpl_bap[253] = 0;
		++cbError;
	}

	if (audblk.cplmant[255] !=0 || audblk.cplmant[254] !=0 || 
			audblk.cplmant[253] !=0)
	{
		audblk.cplmant[255] = 0;
		audblk.cplmant[254] = 0;
		audblk.cplmant[253] = 0;
		++cbError;
	}

	if ((audblk.cplinu == 1) && (audblk.cplbegf > (audblk.cplendf+2)))
	{
		++cbError;
	}

	for(i=0; i < bsi.nfchans; i++)
	{
		if((audblk.chincpl[i] == 0) && (audblk.chbwcod[i] > 60))
		{
			audblk.chbwcod[i] = 60;
			++cbError;
		}
	} /* endfor ( i = 0 ... ) */

	return cbError;
}	



⌨️ 快捷键说明

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