| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 | /* ***** BEGIN LICENSE BLOCK *****   * Source last modified: $Id: sbrside.c,v 1.2 2005/05/24 16:01:55 albertofloyd Exp $  *    * Portions Copyright (c) 1995-2005 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 (the "RPSL") available at  * http://www.helixcommunity.org/content/rpsl unless you have licensed  * the file under the current version of the RealNetworks Community  * Source License (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 HE-AAC decoder * Jon Recker (jrecker@real.com) * February 2005 * * sbrside.c - functions for unpacking side info from SBR bitstream **************************************************************************************/#include "sbr.h"/************************************************************************************** * Function:    GetSampRateIdx * * Description: get index of given sample rate * * Inputs:      sample rate (in Hz) * * Outputs:     none * * Return:      index of sample rate (table 1.15 in 14496-3:2001(E)) *              -1 if sample rate not found in table **************************************************************************************/int GetSampRateIdx(int sampRate){	int idx;	for (idx = 0; idx < NUM_SAMPLE_RATES; idx++) {		if (sampRate == sampRateTab[idx])			return idx;	}	return -1;}/************************************************************************************** * Function:    UnpackSBRHeader * * Description: unpack SBR header (table 4.56) * * Inputs:      BitStreamInfo struct pointing to start of SBR header * * Outputs:     initialized SBRHeader struct for this SCE/CPE block * * Return:      non-zero if frame reset is triggered, zero otherwise **************************************************************************************/int UnpackSBRHeader(BitStreamInfo *bsi, SBRHeader *sbrHdr){	SBRHeader sbrHdrPrev;	/* save previous values so we know whether to reset decoder */	sbrHdrPrev.startFreq =     sbrHdr->startFreq;	sbrHdrPrev.stopFreq =      sbrHdr->stopFreq;	sbrHdrPrev.freqScale =     sbrHdr->freqScale;	sbrHdrPrev.alterScale =    sbrHdr->alterScale;	sbrHdrPrev.crossOverBand = sbrHdr->crossOverBand;	sbrHdrPrev.noiseBands =    sbrHdr->noiseBands;	sbrHdr->ampRes =        GetBits(bsi, 1);	sbrHdr->startFreq =     GetBits(bsi, 4);	sbrHdr->stopFreq =      GetBits(bsi, 4);	sbrHdr->crossOverBand = GetBits(bsi, 3);	sbrHdr->resBitsHdr =    GetBits(bsi, 2);	sbrHdr->hdrExtra1 =     GetBits(bsi, 1);	sbrHdr->hdrExtra2 =     GetBits(bsi, 1);	if (sbrHdr->hdrExtra1) {		sbrHdr->freqScale =    GetBits(bsi, 2);		sbrHdr->alterScale =   GetBits(bsi, 1);		sbrHdr->noiseBands =   GetBits(bsi, 2);	} else {		/* defaults */		sbrHdr->freqScale =    2;		sbrHdr->alterScale =   1;		sbrHdr->noiseBands =   2;	}	if (sbrHdr->hdrExtra2) {		sbrHdr->limiterBands = GetBits(bsi, 2);		sbrHdr->limiterGains = GetBits(bsi, 2);		sbrHdr->interpFreq =   GetBits(bsi, 1);		sbrHdr->smoothMode =   GetBits(bsi, 1);	} else {		/* defaults */		sbrHdr->limiterBands = 2;		sbrHdr->limiterGains = 2;		sbrHdr->interpFreq =   1;		sbrHdr->smoothMode =   1;	}	sbrHdr->count++;	/* if any of these have changed from previous frame, reset the SBR module */	if (sbrHdr->startFreq != sbrHdrPrev.startFreq || sbrHdr->stopFreq != sbrHdrPrev.stopFreq ||		sbrHdr->freqScale != sbrHdrPrev.freqScale || sbrHdr->alterScale != sbrHdrPrev.alterScale ||		sbrHdr->crossOverBand != sbrHdrPrev.crossOverBand || sbrHdr->noiseBands != sbrHdrPrev.noiseBands		)		return -1;	else		return 0;}/* cLog2[i] = ceil(log2(i)) (disregard i == 0) */static const unsigned char cLog2[9] = {0, 0, 1, 2, 2, 3, 3, 3, 3};/************************************************************************************** * Function:    UnpackSBRGrid * * Description: unpack SBR grid (table 4.62) * * Inputs:      BitStreamInfo struct pointing to start of SBR grid *              initialized SBRHeader struct for this SCE/CPE block *  * Outputs:     initialized SBRGrid struct for this channel * * Return:      none **************************************************************************************/static void UnpackSBRGrid(BitStreamInfo *bsi, SBRHeader *sbrHdr, SBRGrid *sbrGrid){	int numEnvRaw, env, rel, pBits, border, middleBorder=0;	unsigned char relBordLead[MAX_NUM_ENV], relBordTrail[MAX_NUM_ENV];	unsigned char relBorder0[3], relBorder1[3], relBorder[3];	unsigned char numRelBorder0, numRelBorder1, numRelBorder, numRelLead=0, numRelTrail;	unsigned char absBordLead=0, absBordTrail=0, absBorder;		sbrGrid->ampResFrame = sbrHdr->ampRes;	sbrGrid->frameClass = GetBits(bsi, 2);	switch (sbrGrid->frameClass) {	case SBR_GRID_FIXFIX:		numEnvRaw = GetBits(bsi, 2);		sbrGrid->numEnv = (1 << numEnvRaw);		if (sbrGrid->numEnv == 1)			sbrGrid->ampResFrame = 0;		ASSERT(sbrGrid->numEnv == 1 || sbrGrid->numEnv == 2 || sbrGrid->numEnv == 4);		sbrGrid->freqRes[0] = GetBits(bsi, 1);		for (env = 1; env < sbrGrid->numEnv; env++)			 sbrGrid->freqRes[env] = sbrGrid->freqRes[0];		absBordLead =  0;		absBordTrail = NUM_TIME_SLOTS;		numRelLead =   sbrGrid->numEnv - 1;		numRelTrail =  0;		/* numEnv = 1, 2, or 4 */		if (sbrGrid->numEnv == 1)		border = NUM_TIME_SLOTS / 1;		else if (sbrGrid->numEnv == 2)	border = NUM_TIME_SLOTS / 2;		else							border = NUM_TIME_SLOTS / 4;		for (rel = 0; rel < numRelLead; rel++)			relBordLead[rel] = border;		middleBorder = (sbrGrid->numEnv >> 1);		break;	case SBR_GRID_FIXVAR:		absBorder = GetBits(bsi, 2) + NUM_TIME_SLOTS;		numRelBorder = GetBits(bsi, 2);		sbrGrid->numEnv = numRelBorder + 1;		for (rel = 0; rel < numRelBorder; rel++)			relBorder[rel] = 2*GetBits(bsi, 2) + 2;		pBits = cLog2[sbrGrid->numEnv + 1];		sbrGrid->pointer = GetBits(bsi, pBits);		for (env = sbrGrid->numEnv - 1; env >= 0; env--)			sbrGrid->freqRes[env] = GetBits(bsi, 1);		absBordLead =  0;		absBordTrail = absBorder;		numRelLead =   0;		numRelTrail =  numRelBorder;		for (rel = 0; rel < numRelTrail; rel++)			relBordTrail[rel] = relBorder[rel];		if (sbrGrid->pointer > 1)			middleBorder = sbrGrid->numEnv + 1 - sbrGrid->pointer;		else								middleBorder = sbrGrid->numEnv - 1;		break;	case SBR_GRID_VARFIX:		absBorder = GetBits(bsi, 2);		numRelBorder = GetBits(bsi, 2);		sbrGrid->numEnv = numRelBorder + 1;		for (rel = 0; rel < numRelBorder; rel++)			relBorder[rel] = 2*GetBits(bsi, 2) + 2;		pBits = cLog2[sbrGrid->numEnv + 1];		sbrGrid->pointer = GetBits(bsi, pBits);		for (env = 0; env < sbrGrid->numEnv; env++)			sbrGrid->freqRes[env] = GetBits(bsi, 1);		absBordLead =  absBorder;		absBordTrail = NUM_TIME_SLOTS;		numRelLead =   numRelBorder;		numRelTrail =  0;		for (rel = 0; rel < numRelLead; rel++)			relBordLead[rel] = relBorder[rel];		if (sbrGrid->pointer == 0)			middleBorder = 1;		else if (sbrGrid->pointer == 1)		middleBorder = sbrGrid->numEnv - 1;		else								middleBorder = sbrGrid->pointer - 1;		break;	case SBR_GRID_VARVAR:		absBordLead =   GetBits(bsi, 2);	/* absBorder0 */		absBordTrail =  GetBits(bsi, 2) + NUM_TIME_SLOTS;	/* absBorder1 */		numRelBorder0 = GetBits(bsi, 2);		numRelBorder1 = GetBits(bsi, 2);		sbrGrid->numEnv = numRelBorder0 + numRelBorder1 + 1;		ASSERT(sbrGrid->numEnv <= 5);		for (rel = 0; rel < numRelBorder0; rel++)			relBorder0[rel] = 2*GetBits(bsi, 2) + 2;		for (rel = 0; rel < numRelBorder1; rel++)			relBorder1[rel] = 2*GetBits(bsi, 2) + 2;		pBits = cLog2[numRelBorder0 + numRelBorder1 + 2];		sbrGrid->pointer = GetBits(bsi, pBits);		for (env = 0; env < sbrGrid->numEnv; env++)			sbrGrid->freqRes[env] = GetBits(bsi, 1);		numRelLead =  numRelBorder0;		numRelTrail = numRelBorder1;		for (rel = 0; rel < numRelLead; rel++)			relBordLead[rel] = relBorder0[rel];		for (rel = 0; rel < numRelTrail; rel++)			relBordTrail[rel] = relBorder1[rel];		if (sbrGrid->pointer > 1)			middleBorder = sbrGrid->numEnv + 1 - sbrGrid->pointer;		else								middleBorder = sbrGrid->numEnv - 1;		break;	}	/* build time border vector */	sbrGrid->envTimeBorder[0] = absBordLead * SAMPLES_PER_SLOT;	rel = 0;	border = absBordLead;	for (env = 1; env <= numRelLead; env++) {		border += relBordLead[rel++];		sbrGrid->envTimeBorder[env] = border * SAMPLES_PER_SLOT;	}	rel = 0;	border = absBordTrail;	for (env = sbrGrid->numEnv - 1; env > numRelLead; env--) {		border -= relBordTrail[rel++];		sbrGrid->envTimeBorder[env] = border * SAMPLES_PER_SLOT;	}	sbrGrid->envTimeBorder[sbrGrid->numEnv] = absBordTrail * SAMPLES_PER_SLOT;	if (sbrGrid->numEnv > 1) {		sbrGrid->numNoiseFloors = 2;		sbrGrid->noiseTimeBorder[0] = sbrGrid->envTimeBorder[0];		sbrGrid->noiseTimeBorder[1] = sbrGrid->envTimeBorder[middleBorder];		sbrGrid->noiseTimeBorder[2] = sbrGrid->envTimeBorder[sbrGrid->numEnv];	} else {		sbrGrid->numNoiseFloors = 1;		sbrGrid->noiseTimeBorder[0] = sbrGrid->envTimeBorder[0];		sbrGrid->noiseTimeBorder[1] = sbrGrid->envTimeBorder[1];	}}/************************************************************************************** * Function:    UnpackDeltaTimeFreq * * Description: unpack time/freq flags for delta coding of SBR envelopes (table 4.63) * * Inputs:      BitStreamInfo struct pointing to start of dt/df flags *              number of envelopes *              number of noise floors *  * Outputs:     delta flags for envelope and noise floors * * Return:      none **************************************************************************************/static void UnpackDeltaTimeFreq(BitStreamInfo *bsi, int numEnv, unsigned char *deltaFlagEnv, 								int numNoiseFloors, unsigned char *deltaFlagNoise){	int env, noiseFloor;	for (env = 0; env < numEnv; env++)		deltaFlagEnv[env] = GetBits(bsi, 1);	for (noiseFloor = 0; noiseFloor < numNoiseFloors; noiseFloor++)		deltaFlagNoise[noiseFloor] = GetBits(bsi, 1);}/************************************************************************************** * Function:    UnpackInverseFilterMode * * Description: unpack invf flags for chirp factor calculation (table 4.64) * * Inputs:      BitStreamInfo struct pointing to start of invf flags *              number of noise floor bands *  * Outputs:     invf flags for noise floor bands * * Return:      none **************************************************************************************/static void UnpackInverseFilterMode(BitStreamInfo *bsi, int numNoiseFloorBands, unsigned char *mode){	int n;		for (n = 0; n < numNoiseFloorBands; n++)		mode[n] = GetBits(bsi, 2);}/************************************************************************************** * Function:    UnpackSinusoids * * Description: unpack sinusoid (harmonic) flags for each SBR subband (table 4.67) * * Inputs:      BitStreamInfo struct pointing to start of sinusoid flags *              number of high resolution SBR subbands (nHigh) *  * Outputs:     sinusoid flags for each SBR subband, zero-filled above nHigh * * Return:      none **************************************************************************************/static void UnpackSinusoids(BitStreamInfo *bsi, int nHigh, int addHarmonicFlag, unsigned char *addHarmonic){	int n;	n = 0;	if (addHarmonicFlag) {		for (  ; n < nHigh; n++)			addHarmonic[n] = GetBits(bsi, 1);	}	/* zero out unused bands */	for (     ; n < MAX_QMF_BANDS; n++)		addHarmonic[n] = 0;}/************************************************************************************** * Function:    CopyCouplingGrid * * Description: copy grid parameters from left to right for channel coupling * * Inputs:      initialized SBRGrid struct for left channel *  * Outputs:     initialized SBRGrid struct for right channel * * Return:      none **************************************************************************************/static void CopyCouplingGrid(SBRGrid *sbrGridLeft, SBRGrid *sbrGridRight){	int env, noiseFloor;	sbrGridRight->frameClass =     sbrGridLeft->frameClass;	sbrGridRight->ampResFrame =    sbrGridLeft->ampResFrame;	sbrGridRight->pointer =        sbrGridLeft->pointer;	sbrGridRight->numEnv =         sbrGridLeft->numEnv;	for (env = 0; env < sbrGridLeft->numEnv; env++) {		sbrGridRight->envTimeBorder[env] = sbrGridLeft->envTimeBorder[env];		sbrGridRight->freqRes[env] =       sbrGridLeft->freqRes[env];	}	sbrGridRight->envTimeBorder[env] = sbrGridLeft->envTimeBorder[env];	/* borders are [0, numEnv] inclusive */	sbrGridRight->numNoiseFloors = sbrGridLeft->numNoiseFloors;	for (noiseFloor = 0; noiseFloor <= sbrGridLeft->numNoiseFloors; noiseFloor++)		sbrGridRight->noiseTimeBorder[noiseFloor] = sbrGridLeft->noiseTimeBorder[noiseFloor];	/* numEnvPrev, numNoiseFloorsPrev, freqResPrev are updated in DecodeSBREnvelope() and DecodeSBRNoise() */}/************************************************************************************** * Function:    CopyCouplingInverseFilterMode * * Description: copy invf flags from left to right for channel coupling * * Inputs:      invf flags for left channel *              number of noise floor bands *  * Outputs:     invf flags for right channel * * Return:      none **************************************************************************************/static void CopyCouplingInverseFilterMode(int numNoiseFloorBands, unsigned char *modeLeft, unsigned char *modeRight){	int band;	for (band = 0; band < numNoiseFloorBands; band++)		modeRight[band] = modeLeft[band];}/************************************************************************************** * Function:    UnpackSBRSingleChannel * * Description: unpack sideband info (grid, delta flags, invf flags, envelope and  *                noise floor configuration, sinusoids) for a single channel * * Inputs:      BitStreamInfo struct pointing to start of sideband info *              initialized PSInfoSBR struct (after parsing SBR header and building *                frequency tables) *              base output channel (range = [0, nChans-1]) *  * Outputs:     updated PSInfoSBR struct (SBRGrid and SBRChan) * * Return:      none **************************************************************************************/void UnpackSBRSingleChannel(BitStreamInfo *bsi, PSInfoSBR *psi, int chBase){	int bitsLeft;	SBRHeader *sbrHdr = &(psi->sbrHdr[chBase]);	SBRGrid *sbrGridL = &(psi->sbrGrid[chBase+0]);	SBRFreq *sbrFreq =  &(psi->sbrFreq[chBase]);	SBRChan *sbrChanL = &(psi->sbrChan[chBase+0]);	psi->dataExtra = GetBits(bsi, 1);	if (psi->dataExtra)		psi->resBitsData = GetBits(bsi, 4);	UnpackSBRGrid(bsi, sbrHdr, sbrGridL);	UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);	UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);	DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);	DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);	sbrChanL->addHarmonicFlag[1] = GetBits(bsi, 1);	UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanL->addHarmonicFlag[1], sbrChanL->addHarmonic[1]);		psi->extendedDataPresent = GetBits(bsi, 1);	if (psi->extendedDataPresent) {		psi->extendedDataSize = GetBits(bsi, 4);		if (psi->extendedDataSize == 15)			psi->extendedDataSize += GetBits(bsi, 8);		bitsLeft = 8 * psi->extendedDataSize;		/* get ID, unpack extension info, do whatever is necessary with it... */		while (bitsLeft > 0) {			GetBits(bsi, 8);			bitsLeft -= 8;		}	}}/************************************************************************************** * Function:    UnpackSBRChannelPair * * Description: unpack sideband info (grid, delta flags, invf flags, envelope and  *                noise floor configuration, sinusoids) for a channel pair * * Inputs:      BitStreamInfo struct pointing to start of sideband info *              initialized PSInfoSBR struct (after parsing SBR header and building *                frequency tables) *              base output channel (range = [0, nChans-1]) *  * Outputs:     updated PSInfoSBR struct (SBRGrid and SBRChan for both channels) * * Return:      none **************************************************************************************/void UnpackSBRChannelPair(BitStreamInfo *bsi, PSInfoSBR *psi, int chBase){	int bitsLeft;	SBRHeader *sbrHdr = &(psi->sbrHdr[chBase]);	SBRGrid *sbrGridL = &(psi->sbrGrid[chBase+0]), *sbrGridR = &(psi->sbrGrid[chBase+1]);	SBRFreq *sbrFreq =  &(psi->sbrFreq[chBase]);	SBRChan *sbrChanL = &(psi->sbrChan[chBase+0]), *sbrChanR = &(psi->sbrChan[chBase+1]);	psi->dataExtra = GetBits(bsi, 1);	if (psi->dataExtra) {		psi->resBitsData = GetBits(bsi, 4);		psi->resBitsData = GetBits(bsi, 4);	}	psi->couplingFlag = GetBits(bsi, 1);	if (psi->couplingFlag) {		UnpackSBRGrid(bsi, sbrHdr, sbrGridL);		CopyCouplingGrid(sbrGridL, sbrGridR);		UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);		UnpackDeltaTimeFreq(bsi, sbrGridR->numEnv, sbrChanR->deltaFlagEnv, sbrGridR->numNoiseFloors, sbrChanR->deltaFlagNoise);		UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);		CopyCouplingInverseFilterMode(sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1], sbrChanR->invfMode[1]);				DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);		DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);		DecodeSBREnvelope(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);		DecodeSBRNoise(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);		/* pass RIGHT sbrChan struct */		UncoupleSBREnvelope(psi, sbrGridL, sbrFreq, sbrChanR);		UncoupleSBRNoise(psi, sbrGridL, sbrFreq, sbrChanR);	} else {		UnpackSBRGrid(bsi, sbrHdr, sbrGridL);		UnpackSBRGrid(bsi, sbrHdr, sbrGridR);		UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);		UnpackDeltaTimeFreq(bsi, sbrGridR->numEnv, sbrChanR->deltaFlagEnv, sbrGridR->numNoiseFloors, sbrChanR->deltaFlagNoise);		UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);		UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanR->invfMode[1]);		DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);		DecodeSBREnvelope(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);		DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);		DecodeSBRNoise(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);	}	sbrChanL->addHarmonicFlag[1] = GetBits(bsi, 1);	UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanL->addHarmonicFlag[1], sbrChanL->addHarmonic[1]);	sbrChanR->addHarmonicFlag[1] = GetBits(bsi, 1);	UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanR->addHarmonicFlag[1], sbrChanR->addHarmonic[1]);	psi->extendedDataPresent = GetBits(bsi, 1);	if (psi->extendedDataPresent) {		psi->extendedDataSize = GetBits(bsi, 4);		if (psi->extendedDataSize == 15)			psi->extendedDataSize += GetBits(bsi, 8);		bitsLeft = 8 * psi->extendedDataSize;		/* get ID, unpack extension info, do whatever is necessary with it... */		while (bitsLeft > 0) {			GetBits(bsi, 8);			bitsLeft -= 8;		}	}}
 |