📄 mpadecl3.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "statname.h"
#include "hlxclib/string.h"
#include "mhead.h"
#include "mpadecl3.h"
#define min(a,b) ((((a)>=(b))?(b):(a)))
#include "mpalowl3.h" // low level extern C prototypes
///////////////////////////////////////////////////////////////////////////////
// Static Data:
///////////////////////////////////////////////////////////////////////////////
static const int mp_sr20_table_L3[2][4]={441,480,320,-999, 882,960,640,-999};
static const int mp_br_table_L3[2][16]=
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0, /* mpeg 2 */
0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0};
static const int sr_table_L3[8] =
{ 22050, 24000, 16000, 1,
44100, 48000, 32000, 1 };
// shorts used to save a few bytes
static const struct {
short l[23];
short s[14];} sfBandIndexTable[3][3] = {
/* mpeg-2 */
{
{{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
{0,4,8,12,18,24,32,42,56,74,100,132,174,192}},
{{0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576},
{0,4,8,12,18,26,36,48,62,80,104,136,180,192}},
{{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
{0,4,8,12,18,26,36,48,62,80,104,134,174,192}},
},
/* mpeg-1 */
{
{{0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576},
{0,4,8,12,16,22,30,40,52,66,84,106,136,192}},
{{0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576},
{0,4,8,12,16,22,28,38,50,64,80,100,126,192}},
{{0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576},
{0,4,8,12,16,22,30,42,58,78,104,138,180,192}}
},
/* mpeg-2.5, 11 & 12 KHz seem ok, 8 ok */
{
{{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
{0,4,8,12,18,26,36,48,62,80,104,134,174,192}},
{{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
{0,4,8,12,18,26,36,48,62,80,104,134,174,192}},
// this 8khz table, and only 8khz, from mpeg123)
{{0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576},
{0,8,16,24,36,52,72,96,124,160,162,164,166,192}},
},
};
static const SBT_FUNCTION_L3 sbt_table_L3[2][3][2] = {
sbt_mono_L3,
sbt_dual_L3,
#ifdef REDUCTION
sbt16_mono_L3,
sbt16_dual_L3,
sbt8_mono_L3,
sbt8_dual_L3,
#else
NULL, NULL, NULL, NULL,
#endif
#ifdef EIGHT_BIT
/*-- 8 bit output -*/
sbtB_mono_L3,
sbtB_dual_L3,
#ifdef REDUCTION
sbtB16_mono_L3,
sbtB16_dual_L3,
sbtB8_mono_L3,
sbtB8_dual_L3,
#else
NULL, NULL, NULL, NULL,
#endif
#endif
};
///////////////////////////////////////////////////////////////////////////////
// Public Functions
///////////////////////////////////////////////////////////////////////////////
CMpaDecoderL3::CMpaDecoderL3()
: CMpaDecoder(),
mpeg25_flag(0),
stereo_flag(0),
igr(0),
band_limit(576),
band_limit21(576),
band_limit12(576),
band_limit_nsb(32),
gain_adjust(0),
id(1),
ncbl_mixed(0),
half_outbytes(0),
zero_level_pcm(0),
buf_ptr0(0),
buf_ptr1(0),
main_pos_bit(0),
#ifdef REFORMAT
reformat_bytes(0),
reformat_side_bytes(0),
#endif
conceal_flag(0)
{
// memsets not really needed
//memset(samp_save, 0, sizeof(samp_save));
memset(nBand, 0, sizeof(nBand));
memset(sfBandIndex, 0, sizeof(sfBandIndex));
memset(cb_info, 0, sizeof(cb_info));
memset(&is_sf_info, 0, sizeof(is_sf_info));
memset(buf, 0, sizeof(buf));
memset(&side_info, 0, sizeof(side_info));
memset(sf, 0, sizeof(sf));
memset(nsamp, 0, sizeof(nsamp));
memset(yout, 0, sizeof(yout));
memset(sample, 0, sizeof(sample));
conceal[0] = conceal[1] = NULL;
}
CMpaDecoderL3::~CMpaDecoderL3()
{
int i;
for(i=0;i<2;i++) {
#if defined (MP3_CONCEAL_LOSS)
if( conceal[i] != NULL ) delete conceal[i];
#endif //MP3_CONCEAL_LOSS
}
}
//=======================================================================
int CMpaDecoderL3::audio_decode_init(MPEG_HEAD *h,
int framebytes_arg,
int reduction_code,
int transform_code,
int convert_code,
int freq_limit,
int conceal_enable)
{
int i, j, k;
int samprate;
int limit;
int bit_code;
int out_chans;
// could have multiple inits, free error conceal class if any
for(i=0;i<2;i++) {
if( conceal[i] != NULL ) {
#if defined (MP3_CONCEAL_LOSS)
delete conceal[i];
conceal[i] = NULL;
#endif //MP3_CONCEAL_LOSS
}
}
conceal_flag = 0;
if( conceal_enable ) conceal_flag = 1;
buf_ptr0 = 0;
buf_ptr1 = 0;
/* check if code handles */
if( h->option != 1 ) return 0; /* layer III only */
if( h->id ) ncbl_mixed = 8; /* mpeg-1 */
else ncbl_mixed = 6; /* mpeg-2 */
m_bMpeg1 = h->id;
m_nSampsPerFrame = 1152;
if (!m_bMpeg1)
m_nSampsPerFrame >>=1;
framebytes = framebytes_arg;
transform_code = transform_code; /* not used, asm compatability */
bit_code = 0;
#ifndef REDUCTION
reduction_code = 0;
#endif
#ifdef EIGHT_BIT
if( convert_code & 8 ) bit_code = 1;
#endif
convert_code = convert_code & 3; /* higher bits used by dec8 freq cvt */
if( reduction_code < 0 ) reduction_code = 0;
if( reduction_code > 2 ) reduction_code = 2;
if( freq_limit < 1000 ) freq_limit = 1000;
samprate = sr_table_L3[4*h->id + h->sr_index];
if( (h->sync & 1) == 0 ) samprate = samprate/2; // mpeg 2.5
/*----- compute nsb_limit --------*/
nsb_limit = (freq_limit*64L + samprate/2)/samprate; /*- caller limit -*/
limit = (32>>reduction_code);
if( limit > 8 ) limit--;
if( nsb_limit > limit ) nsb_limit = limit;
limit = 18*nsb_limit;
k = h->id;
if( (h->sync & 1) == 0 ) k = 2; // mpeg 2.5
if( k == 1 ) {
band_limit12 = 3*sfBandIndexTable[k][h->sr_index].s[13];
band_limit = band_limit21 = sfBandIndexTable[k][h->sr_index].l[22];
}
else {
band_limit12 = 3*sfBandIndexTable[k][h->sr_index].s[12];
band_limit = band_limit21 = sfBandIndexTable[k][h->sr_index].l[21];
}
band_limit += 8; /* allow for antialias */
if( band_limit > limit ) band_limit = limit;
if( band_limit21 > band_limit ) band_limit21 = band_limit;
if( band_limit12 > band_limit ) band_limit12 = band_limit;
band_limit_nsb = (band_limit+17)/18; /* limit nsb's rounded up */
/*----------------------------------------------*/
gain_adjust = 0; /* adjust gain e.g. cvt to mono sum channel */
if( (h->mode != 3) && (convert_code == 1) ) gain_adjust = -4;
outvalues = 1152 >> reduction_code;
if( h->id == 0 ) outvalues /= 2;
out_chans = 2;
if( h->mode == 3 ) out_chans = 1;
if( convert_code ) out_chans = 1;
sbt_L3 = sbt_table_L3[bit_code][reduction_code][out_chans-1];
k = 1 + convert_code;
if( h->mode == 3 ) k = 0;
// Store the proper xform offset in Xform. We will need to
// do a switch on Xform and call the appropriate member function.
iXform = k;
//Xform = xform_table[k];
outvalues *= out_chans;
if( bit_code ) outbytes = outvalues;
else outbytes = sizeof(short)*outvalues;
if( bit_code ) zero_level_pcm = 128; /* 8 bit output */
else zero_level_pcm = 0;
decinfo.channels = out_chans;
decinfo.outvalues = outvalues;
decinfo.samprate = samprate >> reduction_code;
if( bit_code ) decinfo.bits = 8;
else decinfo.bits = sizeof(short)*8;
decinfo.framebytes = framebytes;
decinfo.type = 0;
half_outbytes = outbytes/2;
/*------------------------------------------*/
/*- init band tables --*/
k = h->id;
if( (h->sync & 1) == 0 ) k = 2; // mpeg 2.5
for(i=0;i<22;i++)
sfBandIndex[0][i] = sfBandIndexTable[k][h->sr_index].l[i+1];
for(i=0;i<13;i++)
sfBandIndex[1][i] = 3*sfBandIndexTable[k][h->sr_index].s[i+1];
for(i=0;i<22;i++) nBand[0][i] =
sfBandIndexTable[k][h->sr_index].l[i+1]
- sfBandIndexTable[k][h->sr_index].l[i];
for(i=0;i<13;i++) nBand[1][i] =
sfBandIndexTable[k][h->sr_index].s[i+1]
- sfBandIndexTable[k][h->sr_index].s[i];
/*--- clear buffers --*/
for(i=0;i<576;i++) yout[i] = 0.0f;
for(j=0;j<2;j++) {
for(k=0;k<2;k++) {
for(i=0;i<576;i++) {
sample[j][k][i].x = 0.0f;
sample[j][k][i].s = 0;
}
}
}
// h_id used to select xform routine
h_id = h->id;
// conceal class
//conceal[0] = new CConcealment(band_limit21);
//if( h->mode != 3 ) { // need two channels of concealment
// conceal[1] = new CConcealment(band_limit21);
//}
if( conceal_flag ) {
#if defined (MP3_CONCEAL_LOSS)
conceal[0] = new CConcealment(576);
if( h->mode != 3 ) { // need two channels of concealment
conceal[1] = new CConcealment(576);
}
#endif //MP3_CONCEAL_LOSS
}
return 1;
}
//=========================================================================
IN_OUT CMpaDecoderL3::audio_decode(unsigned char *bs, unsigned char *pcm)
{
if( h_id ) {
return L3audio_decode_MPEG1(bs, pcm);
}
else {
return L3audio_decode_MPEG2(bs, pcm);
}
}
///////////////////////////////////////////////////////////////////////////////
// Private Functions
///////////////////////////////////////////////////////////////////////////////
/*---------------------------------------------------------*/
IN_OUT CMpaDecoderL3::L3audio_decode_MPEG1(unsigned char *bs,
unsigned char *pcm)
{
int sync;
IN_OUT in_out;
int side_bytes;
int nbytes;
iframe++;
bitget_init(&bitdat, bs); /* initialize bit getter */
/* test sync */
in_out.in_bytes = 0; /* assume fail */
in_out.out_bytes = 0;
sync = bitget(&bitdat, 12);
if( sync != 0xFFF ) return in_out; /* sync fail */
/*-----------*/
/*-- unpack side info --*/
side_bytes = unpack_side_MPEG1();
if( framebytes <= 0 ) return in_out; // fail bad sr or br index
padframebytes = framebytes+pad;
in_out.in_bytes = padframebytes;
/*-- load main data and update buf pointer --*/
/*-------------------------------------------
if start point < 0, must just cycle decoder
if jumping into middle of stream,
---------------------------------------------*/
buf_ptr0 = buf_ptr1 - side_info.main_data_begin; /* decode start point */
if( buf_ptr1 > BUF_TRIGGER ) { /* shift buffer */
memmove(buf, buf+buf_ptr0, side_info.main_data_begin);
buf_ptr0 = 0;
buf_ptr1 = side_info.main_data_begin;
}
nbytes = padframebytes - side_bytes - crcbytes;
if( nbytes>0 )
{
memmove(buf+buf_ptr1, bs+side_bytes+crcbytes, nbytes);
buf_ptr1 += nbytes;
}
/*-----------------------*/
if( buf_ptr0 >= 0 ) {
main_pos_bit = buf_ptr0 << 3;
unpack_main(buf, 0);
Xform(pcm, 0);
unpack_main(buf, 1);
Xform(pcm+half_outbytes, 1);
in_out.out_bytes = outbytes;
}
else {
memset(pcm, zero_level_pcm, outbytes); /* fill out skipped frames */
in_out.out_bytes = outbytes;
}
return in_out;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -