392 lines
13 KiB
C
392 lines
13 KiB
C
/* ***** 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 ***** */
|
|
|
|
/**************************************************************************************
|
|
* Fixed-point MP3 decoder
|
|
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
|
|
* June 2003
|
|
*
|
|
* scalfact.c - scalefactor unpacking functions
|
|
**************************************************************************************/
|
|
|
|
#include "coder.h"
|
|
|
|
/* scale factor lengths (num bits) */
|
|
static const char SFLenTab[16][2] = {
|
|
{0, 0}, {0, 1},
|
|
{0, 2}, {0, 3},
|
|
{3, 0}, {1, 1},
|
|
{1, 2}, {1, 3},
|
|
{2, 1}, {2, 2},
|
|
{2, 3}, {3, 1},
|
|
{3, 2}, {3, 3},
|
|
{4, 2}, {4, 3},
|
|
};
|
|
|
|
/**************************************************************************************
|
|
* Function: UnpackSFMPEG1
|
|
*
|
|
* Description: unpack MPEG 1 scalefactors from bitstream
|
|
*
|
|
* Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this
|
|
* granule/channel
|
|
* vector of scfsi flags from side info, length = 4 (MAX_SCFBD)
|
|
* index of current granule
|
|
* ScaleFactorInfoSub from granule 0 (for granule 1, if scfsi[i] is set,
|
|
* then we just replicate the scale factors from granule 0 in the
|
|
* i'th set of scalefactor bands)
|
|
*
|
|
* Outputs: updated BitStreamInfo struct
|
|
* scalefactors in sfis (short and/or long arrays, as appropriate)
|
|
*
|
|
* Return: none
|
|
*
|
|
* Notes: set order of short blocks to s[band][window] instead of s[window][band]
|
|
* so that we index through consectutive memory locations when unpacking
|
|
* (make sure dequantizer follows same convention)
|
|
* Illegal Intensity Position = 7 (always) for MPEG1 scale factors
|
|
**************************************************************************************/
|
|
static void UnpackSFMPEG1(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int *scfsi, int gr, ScaleFactorInfoSub *sfisGr0)
|
|
{
|
|
int sfb;
|
|
int slen0, slen1;
|
|
|
|
/* these can be 0, so make sure GetBits(bsi, 0) returns 0 (no >> 32 or anything) */
|
|
slen0 = (int)SFLenTab[sis->sfCompress][0];
|
|
slen1 = (int)SFLenTab[sis->sfCompress][1];
|
|
|
|
if (sis->blockType == 2) {
|
|
/* short block, type 2 (implies winSwitchFlag == 1) */
|
|
if (sis->mixedBlock) {
|
|
/* do long block portion */
|
|
for (sfb = 0; sfb < 8; sfb++)
|
|
sfis->l[sfb] = (char)GetBits(bsi, slen0);
|
|
sfb = 3;
|
|
} else {
|
|
/* all short blocks */
|
|
sfb = 0;
|
|
}
|
|
|
|
for ( ; sfb < 6; sfb++) {
|
|
sfis->s[sfb][0] = (char)GetBits(bsi, slen0);
|
|
sfis->s[sfb][1] = (char)GetBits(bsi, slen0);
|
|
sfis->s[sfb][2] = (char)GetBits(bsi, slen0);
|
|
}
|
|
|
|
for ( ; sfb < 12; sfb++) {
|
|
sfis->s[sfb][0] = (char)GetBits(bsi, slen1);
|
|
sfis->s[sfb][1] = (char)GetBits(bsi, slen1);
|
|
sfis->s[sfb][2] = (char)GetBits(bsi, slen1);
|
|
}
|
|
|
|
/* last sf band not transmitted */
|
|
sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0;
|
|
} else {
|
|
/* long blocks, type 0, 1, or 3 */
|
|
if(gr == 0) {
|
|
/* first granule */
|
|
for (sfb = 0; sfb < 11; sfb++)
|
|
sfis->l[sfb] = (char)GetBits(bsi, slen0);
|
|
for (sfb = 11; sfb < 21; sfb++)
|
|
sfis->l[sfb] = (char)GetBits(bsi, slen1);
|
|
return;
|
|
} else {
|
|
/* second granule
|
|
* scfsi: 0 = different scalefactors for each granule, 1 = copy sf's from granule 0 into granule 1
|
|
* for block type == 2, scfsi is always 0
|
|
*/
|
|
sfb = 0;
|
|
if(scfsi[0]) for( ; sfb < 6 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
|
|
else for( ; sfb < 6 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0);
|
|
if(scfsi[1]) for( ; sfb <11 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
|
|
else for( ; sfb <11 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0);
|
|
if(scfsi[2]) for( ; sfb <16 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
|
|
else for( ; sfb <16 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1);
|
|
if(scfsi[3]) for( ; sfb <21 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
|
|
else for( ; sfb <21 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1);
|
|
}
|
|
/* last sf band not transmitted */
|
|
sfis->l[21] = 0;
|
|
sfis->l[22] = 0;
|
|
}
|
|
}
|
|
|
|
/* NRTab[size + 3*is_right][block type][partition]
|
|
* block type index: 0 = (bt0,bt1,bt3), 1 = bt2 non-mixed, 2 = bt2 mixed
|
|
* partition: scale factor groups (sfb1 through sfb4)
|
|
* for block type = 2 (mixed or non-mixed) / by 3 is rolled into this table
|
|
* (for 3 short blocks per long block)
|
|
* see 2.4.3.2 in MPEG 2 (low sample rate) spec
|
|
* stuff rolled into this table:
|
|
* NRTab[x][1][y] --> (NRTab[x][1][y]) / 3
|
|
* NRTab[x][2][>=1] --> (NRTab[x][2][>=1]) / 3 (first partition is long block)
|
|
*/
|
|
static const char NRTab[6][3][4] = {
|
|
/* non-intensity stereo */
|
|
{ {6, 5, 5, 5},
|
|
{3, 3, 3, 3}, /* includes / 3 */
|
|
{6, 3, 3, 3}, /* includes / 3 except for first entry */
|
|
},
|
|
{ {6, 5, 7, 3},
|
|
{3, 3, 4, 2},
|
|
{6, 3, 4, 2},
|
|
},
|
|
{ {11, 10, 0, 0},
|
|
{6, 6, 0, 0},
|
|
{6, 3, 6, 0}, /* spec = [15,18,0,0], but 15 = 6L + 9S, so move 9/3=3 into col 1, 18/3=6 into col 2 and adj. slen[1,2] below */
|
|
},
|
|
/* intensity stereo, right chan */
|
|
{ {7, 7, 7, 0},
|
|
{4, 4, 4, 0},
|
|
{6, 5, 4, 0},
|
|
},
|
|
{ {6, 6, 6, 3},
|
|
{4, 3, 3, 2},
|
|
{6, 4, 3, 2},
|
|
},
|
|
{ {8, 8, 5, 0},
|
|
{5, 4, 3, 0},
|
|
{6, 6, 3, 0},
|
|
}
|
|
};
|
|
|
|
/**************************************************************************************
|
|
* Function: UnpackSFMPEG2
|
|
*
|
|
* Description: unpack MPEG 2 scalefactors from bitstream
|
|
*
|
|
* Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this
|
|
* granule/channel
|
|
* index of current granule and channel
|
|
* ScaleFactorInfoSub from this granule
|
|
* modeExt field from frame header, to tell whether intensity stereo is on
|
|
* ScaleFactorJS struct for storing IIP info used in Dequant()
|
|
*
|
|
* Outputs: updated BitStreamInfo struct
|
|
* scalefactors in sfis (short and/or long arrays, as appropriate)
|
|
* updated intensityScale and preFlag flags
|
|
*
|
|
* Return: none
|
|
*
|
|
* Notes: Illegal Intensity Position = (2^slen) - 1 for MPEG2 scale factors
|
|
*
|
|
* TODO: optimize the / and % stuff (only do one divide, get modulo x
|
|
* with (x / m) * m, etc.)
|
|
**************************************************************************************/
|
|
static void UnpackSFMPEG2(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int gr, int ch, int modeExt, ScaleFactorJS *sfjs)
|
|
{
|
|
|
|
int i, sfb, sfcIdx, btIdx, nrIdx, iipTest;
|
|
int slen[4], nr[4];
|
|
int sfCompress, preFlag, intensityScale;
|
|
|
|
sfCompress = sis->sfCompress;
|
|
preFlag = 0;
|
|
intensityScale = 0;
|
|
|
|
/* stereo mode bits (1 = on): bit 1 = mid-side on/off, bit 0 = intensity on/off */
|
|
if (! ((modeExt & 0x01) && (ch == 1)) ) {
|
|
/* in other words: if ((modeExt & 0x01) == 0 || ch == 0) */
|
|
if (sfCompress < 400) {
|
|
/* max slen = floor[(399/16) / 5] = 4 */
|
|
slen[0] = (sfCompress >> 4) / 5;
|
|
slen[1]= (sfCompress >> 4) % 5;
|
|
slen[2]= (sfCompress & 0x0f) >> 2;
|
|
slen[3]= (sfCompress & 0x03);
|
|
sfcIdx = 0;
|
|
} else if (sfCompress < 500) {
|
|
/* max slen = floor[(99/4) / 5] = 4 */
|
|
sfCompress -= 400;
|
|
slen[0] = (sfCompress >> 2) / 5;
|
|
slen[1]= (sfCompress >> 2) % 5;
|
|
slen[2]= (sfCompress & 0x03);
|
|
slen[3]= 0;
|
|
sfcIdx = 1;
|
|
} else {
|
|
/* max slen = floor[11/3] = 3 (sfCompress = 9 bits in MPEG2) */
|
|
sfCompress -= 500;
|
|
slen[0] = sfCompress / 3;
|
|
slen[1] = sfCompress % 3;
|
|
slen[2] = slen[3] = 0;
|
|
if (sis->mixedBlock) {
|
|
/* adjust for long/short mix logic (see comment above in NRTab[] definition) */
|
|
slen[2] = slen[1];
|
|
slen[1] = slen[0];
|
|
}
|
|
preFlag = 1;
|
|
sfcIdx = 2;
|
|
}
|
|
} else {
|
|
/* intensity stereo ch = 1 (right) */
|
|
intensityScale = sfCompress & 0x01;
|
|
sfCompress >>= 1;
|
|
if (sfCompress < 180) {
|
|
/* max slen = floor[35/6] = 5 (from mod 36) */
|
|
slen[0] = (sfCompress / 36);
|
|
slen[1] = (sfCompress % 36) / 6;
|
|
slen[2] = (sfCompress % 36) % 6;
|
|
slen[3] = 0;
|
|
sfcIdx = 3;
|
|
} else if (sfCompress < 244) {
|
|
/* max slen = floor[63/16] = 3 */
|
|
sfCompress -= 180;
|
|
slen[0] = (sfCompress & 0x3f) >> 4;
|
|
slen[1] = (sfCompress & 0x0f) >> 2;
|
|
slen[2] = (sfCompress & 0x03);
|
|
slen[3] = 0;
|
|
sfcIdx = 4;
|
|
} else {
|
|
/* max slen = floor[11/3] = 3 (max sfCompress >> 1 = 511/2 = 255) */
|
|
sfCompress -= 244;
|
|
slen[0] = (sfCompress / 3);
|
|
slen[1] = (sfCompress % 3);
|
|
slen[2] = slen[3] = 0;
|
|
sfcIdx = 5;
|
|
}
|
|
}
|
|
|
|
/* set index based on block type: (0,1,3) --> 0, (2 non-mixed) --> 1, (2 mixed) ---> 2 */
|
|
btIdx = 0;
|
|
if (sis->blockType == 2)
|
|
btIdx = (sis->mixedBlock ? 2 : 1);
|
|
for (i = 0; i < 4; i++)
|
|
nr[i] = (int)NRTab[sfcIdx][btIdx][i];
|
|
|
|
/* save intensity stereo scale factor info */
|
|
if( (modeExt & 0x01) && (ch == 1) ) {
|
|
for (i = 0; i < 4; i++) {
|
|
sfjs->slen[i] = slen[i];
|
|
sfjs->nr[i] = nr[i];
|
|
}
|
|
sfjs->intensityScale = intensityScale;
|
|
}
|
|
sis->preFlag = preFlag;
|
|
|
|
/* short blocks */
|
|
if(sis->blockType == 2) {
|
|
if(sis->mixedBlock) {
|
|
/* do long block portion */
|
|
iipTest = (1 << slen[0]) - 1;
|
|
for (sfb=0; sfb < 6; sfb++) {
|
|
sfis->l[sfb] = (char)GetBits(bsi, slen[0]);
|
|
}
|
|
sfb = 3; /* start sfb for short */
|
|
nrIdx = 1;
|
|
} else {
|
|
/* all short blocks, so start nr, sfb at 0 */
|
|
sfb = 0;
|
|
nrIdx = 0;
|
|
}
|
|
|
|
/* remaining short blocks, sfb just keeps incrementing */
|
|
for ( ; nrIdx <= 3; nrIdx++) {
|
|
iipTest = (1 << slen[nrIdx]) - 1;
|
|
for (i=0; i < nr[nrIdx]; i++, sfb++) {
|
|
sfis->s[sfb][0] = (char)GetBits(bsi, slen[nrIdx]);
|
|
sfis->s[sfb][1] = (char)GetBits(bsi, slen[nrIdx]);
|
|
sfis->s[sfb][2] = (char)GetBits(bsi, slen[nrIdx]);
|
|
}
|
|
}
|
|
/* last sf band not transmitted */
|
|
sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0;
|
|
} else {
|
|
/* long blocks */
|
|
sfb = 0;
|
|
for (nrIdx = 0; nrIdx <= 3; nrIdx++) {
|
|
iipTest = (1 << slen[nrIdx]) - 1;
|
|
for(i=0; i < nr[nrIdx]; i++, sfb++) {
|
|
sfis->l[sfb] = (char)GetBits(bsi, slen[nrIdx]);
|
|
}
|
|
}
|
|
/* last sf band not transmitted */
|
|
sfis->l[21] = sfis->l[22] = 0;
|
|
|
|
}
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: UnpackScaleFactors
|
|
*
|
|
* Description: parse the fields of the MP3 scale factor data section
|
|
*
|
|
* Inputs: MP3DecInfo structure filled by UnpackFrameHeader() and UnpackSideInfo()
|
|
* buffer pointing to the MP3 scale factor data
|
|
* pointer to bit offset (0-7) indicating starting bit in buf[0]
|
|
* number of bits available in data buffer
|
|
* index of current granule and channel
|
|
*
|
|
* Outputs: updated platform-specific ScaleFactorInfo struct
|
|
* updated bitOffset
|
|
*
|
|
* Return: length (in bytes) of scale factor data, -1 if null input pointers
|
|
**************************************************************************************/
|
|
int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch)
|
|
{
|
|
int bitsUsed;
|
|
unsigned char *startBuf;
|
|
BitStreamInfo bitStreamInfo, *bsi;
|
|
FrameHeader *fh;
|
|
SideInfo *si;
|
|
ScaleFactorInfo *sfi;
|
|
|
|
/* validate pointers */
|
|
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS)
|
|
return -1;
|
|
fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS));
|
|
si = ((SideInfo *)(mp3DecInfo->SideInfoPS));
|
|
sfi = ((ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS));
|
|
|
|
/* init GetBits reader */
|
|
startBuf = buf;
|
|
bsi = &bitStreamInfo;
|
|
SetBitstreamPointer(bsi, (bitsAvail + *bitOffset + 7) / 8, buf);
|
|
if (*bitOffset)
|
|
GetBits(bsi, *bitOffset);
|
|
|
|
if (fh->ver == MPEG1)
|
|
UnpackSFMPEG1(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], si->scfsi[ch], gr, &sfi->sfis[0][ch]);
|
|
else
|
|
UnpackSFMPEG2(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], gr, ch, fh->modeExt, &sfi->sfjs);
|
|
|
|
mp3DecInfo->part23Length[gr][ch] = si->sis[gr][ch].part23Length;
|
|
|
|
bitsUsed = CalcBitsUsed(bsi, buf, *bitOffset);
|
|
buf += (bitsUsed + *bitOffset) >> 3;
|
|
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
|
|
|
|
return (buf - startBuf);
|
|
}
|
|
|