/* ***** 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 < 3; 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 < 3; 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 < MAX_NUM_ENV; 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 < 3; rel++) {
            relBorder0[rel] = 2 * GetBits(bsi, 2) + 2;
        }

        for (rel = 0; rel < numRelBorder1 && rel < 3; 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 < MAX_NUM_ENV; 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;
        }
    }
}
