www.pudn.com > VC写的MP3播放器源代码.zip > LayerIII.cpp


///////////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "LayerIII.h" 
#include  
 
 
 
 
 
///////////////////////////////////////////////////////////////////////////// 
// 
BOOL CLayerIII::DecodeBlock(BYTE *pVarIn, // block from file passed in 
							DWORD nLength, // length of block 
                            BYTE *pVarOut, // out buffer 
							DWORD *outLevel,// acumulated bytes in out buffer 
                            DWORD mpVersion,	// fix march 30 MCO 
                            DWORD nMode,		// fix march 30 MCO 
                            DWORD modeExtension,// fix march 30 MCO 
                            DWORD freqIdx)		// fix march 30 MCO 
{ 
	DWORD	flDwm		=	0; 
    DWORD	dwGr, dwCh, dwTmp1, dwTmp2, iSb18; 
    int		nMainDataEnd	= 0; 
    int		nDiscardBytes	= 0; 
    int     nSamples        = 0; 
    int		dw				= (int)nLength; 
	int		acLeft          = *outLevel/2; 
	int		acRight         = *outLevel/2; 
    double  dblSum			; 
	// this array pass to the scope the spectrum 
	double  tdblSum[40]		={0}; 
 
 
	m_version           = mpVersion; 
	m_flMode			= nMode; 
	m_dwExtensionMode	= modeExtension; 
	m_pbyWalk			= pVarIn; 
    m_nBitsOffset		= 0; 
 
 
    GetSideInfo(); 
 
	// looking for  fast copying 
    while(--dw >= 0) 
        AddTail(Bits(8)); 
 
    nMainDataEnd = GetReadBits() >> 3; // /4 
     
    if (flDwm = (GetReadBits() & 7))  
	{ 
        GetBits(8 - flDwm); 
        nMainDataEnd++; 
    } 
     
    nDiscardBytes = m_nFrmStart - nMainDataEnd - m_SIDEINF.dataMainStart; 
     
    m_nFrmStart += nLength; 
 
    if (nDiscardBytes < 0) 
       return FALSE ; 
     
    if (nMainDataEnd > 4096)  
	{ 
        m_nFrmStart -= 4096; 
        GoBackOctets(); 
    } 
     
	while(nDiscardBytes-->0) 
	{ 
        GetBits(8); 
	} 
	    
    for (dwGr =0; dwGr < m_dwMaxGr; dwGr++)  
	{ 
         
        for (dwCh = 0; dwCh < (DWORD)m_nChanels; dwCh++)  
		{ 
            m_nPart2Start = GetReadBits(); 
            if (m_dwMaxGr == 2)	 
				GetScaleFact(dwCh, dwGr); 
            else  // MPEG-2 LSF 
				GetLSFScaleFactor(dwCh, dwGr); 
			HuffmanDecode(dwCh, dwGr); 
			DeqSample(m_cubeRo[dwCh], dwCh, dwGr); 
        } 
        if(-1 == Stereo(dwGr)) 
           return FALSE; 
	 
        for (dwCh = m_chFirst ; dwCh <= (DWORD)m_chLast; dwCh++)  
		{ 
             
			Reorder(m_cubeLr[dwCh], dwCh, dwGr); 
            AntiAlias(dwCh, dwGr); 
            Hibrid(dwCh, dwGr); 
 
            for (iSb18 = 18; iSb18 < 576;iSb18+=36)  
			{ 
			    for (dwTmp1=1; dwTmp1 < 18; dwTmp1 += 2) 
				{ 
				    m_dOutArr[iSb18 + dwTmp1] = -m_dOutArr[iSb18 + dwTmp1]; 
				} 
			} 
			 
            if (dwCh == 0 || m_nChanel == 2)  
			{ 
				for (dwTmp1=0; dwTmp1 < 18; dwTmp1++)  
				{  
                    dblSum			= 0; 
 
                    for (dwTmp2 = 0,iSb18=0; iSb18 < 576; iSb18 += 18,dwTmp2++)  
					{ 
                         tdblSum[dwTmp2] +=	m_pFilterX->InSample(m_dOutArr[iSb18 + dwTmp1],dwTmp2 ); 
                    } 
					m_pFilterX->PrepPCMSampleX(pVarOut,nSamples,acRight,m_pfnCallback); 
                } 
                (*m_pfnCallback)(0,tdblSum,dwTmp2); 
            }  
			else  
			{ 
                for (dwTmp1=0; dwTmp1 < 18; dwTmp1++)  
				{  
                     
                    for (dwTmp2 = 0,iSb18=0; iSb18 < 576; iSb18 += 18,dwTmp2++)  
					{ 
                        m_pFilterY->InSample(m_dOutArr[iSb18 + dwTmp1], dwTmp2); 
                    } 
                     
					m_pFilterY->PrepPCMSampleX(pVarOut,nSamples,acLeft,m_pfnCallback); 
                } 
            } 
        }  
    }  
	//MCO 
	*outLevel += nSamples; 
	return TRUE; 
} 
 
////////////////////////////////////////////////////////////////////////////////// 
//	The original code has been shrinked 
//	by 16 times, without losing to mutch speed(Marius C.) 
//	Also added the support for callback function pFn. If there is no pFn 
// the default gain is applied(MC) 
 
 
int SynthesisFilter::PrepPCMSampleX(BYTE* pBuff,int& samples,int& nOffset, 
                                    PFN pFn,void* pData) 
{ 
	double*	pDb				= m_pToTable; 
	int		idx			    = m_nWriteIndex; 
	double	dblV	        = 0.0f; 
	WORD*	pwOutBuf		= (WORD*)pBuff; 
	 
 
	CompNewTable(); 
	 
	// Marius C. 
	for(  double *pTd = dblISO;  pTd < dblISO + (512); pTd += 16, pDb += 16 )  
	{ 
		dblV = (double)(( 
                                ((pDb[(idx)    & 0xf] * pTd[0])) + 
	                            ((pDb[(idx-1)  & 0xf] * pTd[1])) + 
								((pDb[(idx-2)  & 0xf] * pTd[2])) + 
								((pDb[(idx-3)  & 0xf] * pTd[3])) + 
								((pDb[(idx-4)  & 0xf] * pTd[4])) + 
								((pDb[(idx-5)  & 0xf] * pTd[5])) + 
								((pDb[(idx-6)  & 0xf] * pTd[6])) + 
								((pDb[(idx-7)  & 0xf] * pTd[7])) + 
								((pDb[(idx-8)  & 0xf] * pTd[8])) + 
								((pDb[(idx-9)  & 0xf] * pTd[9])) + 
								((pDb[(idx-10) & 0xf] * pTd[10])) + 
								((pDb[(idx-11) & 0xf] * pTd[11])) + 
								((pDb[(idx-12) & 0xf] * pTd[12])) + 
								((pDb[(idx-13) & 0xf] * pTd[13])) + 
								((pDb[(idx-14) & 0xf] * pTd[14])) + 
								((pDb[(idx-15) & 0xf] * pTd[15])) 
                                )*32767.0f); 
 
        // IF CRASH HERE THAT MEANS YOU CHANGED THE MCI BUFFER SIZE 
        // OR THE MODULO IN MAIN THREAD LOOP 
		if(pFn != 0) // leave you to use the vol controland or the EQ 
			pwOutBuf[m_nCan + (nOffset<<1)] = (WORD)((*pFn) (&dblV,0,m_nCan)); 
		else // auto gain pre amplif 
		{ 
			pwOutBuf[m_nCan + (nOffset<<1)] = Clip(dblV); 
		} 
		nOffset++; 
		samples++; 
	} 
 
    m_nWriteIndex = (m_nWriteIndex + 1) & 0xf;		 
    m_pToTable = (m_pToTable == m_tableA) ? m_tableB : m_tableA; 
 
	// MCO not necesarely 
	//	ZeroMemory(m_tdbSubSamples,sizeof(m_tdbSubSamples)); 
 
	 
    return 1; 
} 
 
BOOL CLayerIII::Init(DWORD mpVersion,  
                     DWORD nMode,  
                     DWORD modeExtension,  
                     DWORD freqIdx,  
					 long pFnCallBack ) 
{ 
 
 
    m_pFilterX      = new SynthesisFilter(0); 
	m_pFilterY      = new SynthesisFilter(1); 
    if(m_pFilterY == 0 || m_pFilterY == 0) 
    { 
		delete m_pFilterX; 
		delete m_pFilterY; 
		m_pFilterY=m_pFilterX=0; 
        return FALSE; 
    } 
 
    ResolveChannels(nMode); 
	 
 
	// callback fn added by M.C 
    m_pfnCallback       = reinterpret_cast(pFnCallBack); 
    m_nFrmStart         = 0; 
 
    m_version           = mpVersion; 
    m_dwMaxGr			= (mpVersion == 1) ? 2 : 1; 
	m_flMode			= nMode; 
    m_nFreqIdx			= freqIdx + ((m_dwMaxGr == 2) ? 3 : 0); 
	m_dwExtensionMode	= modeExtension; 
 
		 
    ZeroMemory(m_PreBlkArr,sizeof(m_PreBlkArr)); 
    m_arrNonZero[0] = m_arrNonZero[1] = 576; 
	m_pbyWalk       = 0; 
 
 
	return TRUE; 
} 
 
void CLayerIII::Reset() 
{ 
	 if(0 != m_pFilterX && 0 != m_pFilterY) 
     { 
        m_pFilterY->Reset(); 
        m_pFilterX->Reset(); 
        m_pbyWalk   = 0; 
        m_nFrmStart = 0; 
	    ZeroMemory(m_PreBlkArr,sizeof(m_PreBlkArr)); 
 
     } 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// Marius C 
void CLayerIII::ResolveChannels(int nMode) 
{ 
    m_chFirst           =   0; 
    m_chLast            =   1; 
    m_nChanel           =   0;  
    m_nChanels          = (nMode == 3) ? 1 : 2; 
    if(m_nChanels == 1) 
    { 
        m_nChanel            = 1; //left channel 
        m_chFirst = m_chLast = 0; 
    } 
} 
 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
BOOL CLayerIII::GetSideInfo() 
{ 
    int dwCh, dwGr; 
	STR_GRINFO*	pToCel; 
    int nChanels = m_nChanels; 
	 
     
    if (m_dwMaxGr == 2) // MPEG1 
	{ 
        m_SIDEINF.dataMainStart = Bits(9); 
        if (m_nChanels == 1) 
            m_SIDEINF.privBits		= Bits(5); 
        else 
		    m_SIDEINF.privBits		= Bits(3); 
         
        for (dwCh=0; dwCh < nChanels; dwCh++)  
		{ 
 
            m_SIDEINF.sArrCH[dwCh].arrScfSi[0] = Bits(1); 
            m_SIDEINF.sArrCH[dwCh].arrScfSi[1] = Bits(1); 
            m_SIDEINF.sArrCH[dwCh].arrScfSi[2] = Bits(1); 
            m_SIDEINF.sArrCH[dwCh].arrScfSi[3] = Bits(1); 
        } 
         
        for (dwGr=0; dwGr < 2; dwGr++)  
		{ 
            for (dwCh=0; dwCh < nChanels; dwCh++)  
			{ 
				pToCel = &m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]; 
				pToCel->p23Len				= Bits(12); 
                pToCel->bigVal				= Bits(9); 
                pToCel->glbGain				= Bits(8); 
                pToCel->scaleFactCompress	= Bits(4); 
                if(pToCel->wndSwitchFlag	= Bits(1)) 
				{ 
                    pToCel->nBlockType         = Bits(2); 
                    pToCel->mixedBlockFlag     = Bits(1); 
                    pToCel->arrSelect[0]       = Bits(5); 
                    pToCel->arrSelect[1]       = Bits(5); 
                    pToCel->arrSubBlockGain[0] = Bits(3); 
                    pToCel->arrSubBlockGain[1] = Bits(3); 
                    pToCel->arrSubBlockGain[2] = Bits(3); 
                     
                    // Set region_count parameters since they are implicit pDblIn this case. 
                    if (0 ==pToCel->nBlockType)  
					{ 
                         return FALSE; 
                    }  
					else if (2 == pToCel->nBlockType  
							&& 0 == pToCel->mixedBlockFlag )  
					{ 
                        pToCel->region0Count = 8; 
                    }  
					else  
					{ 
                        pToCel->region0Count = 7; 
                    } 
                     
					pToCel->region1Count = 20 - pToCel->region0Count; 
				}  
				else  
				{ 
                    pToCel->arrSelect[0] = Bits(5); 
                    pToCel->arrSelect[1] = Bits(5); 
                    pToCel->arrSelect[2] = Bits(5); 
                    pToCel->region0Count = Bits(4); 
                    pToCel->region1Count = Bits(3); 
                    pToCel->nBlockType = 0; 
                } 
                pToCel->preflag		  = Bits(1); 
                pToCel->scaleFactScale = Bits(1); 
                pToCel->countTblSelect = Bits(1); 
            } 
        } 
    }  
	else  
	{   // MPEG-2 LSF 
        m_SIDEINF.dataMainStart = Bits(8); 
        if (nChanels == 1) 
            	m_SIDEINF.privBits = Bits(1); 
        else 
            	m_SIDEINF.privBits = Bits(2); 
         
        for (dwCh=0; dwChp23Len			= Bits(12); 
            pToCel->bigVal			= Bits(9); 
            pToCel->glbGain			= Bits(8); 
            pToCel->scaleFactCompress = Bits(9); 
            pToCel->wndSwitchFlag	= Bits(1); 
             
            if (pToCel->wndSwitchFlag)  
			{ 
                 
                pToCel->nBlockType		= Bits(2); 
                pToCel->mixedBlockFlag	= Bits(1); 
                pToCel->arrSelect[0]	= Bits(5); 
                pToCel->arrSelect[1]	= Bits(5); 
                 
                pToCel->arrSubBlockGain[0] = Bits(3); 
                pToCel->arrSubBlockGain[1] = Bits(3); 
                pToCel->arrSubBlockGain[2] = Bits(3); 
                 
                // Set region_count parameters since they are implicit pDblIn this case. 
                 
                if (pToCel->nBlockType == 0)  
				{ 
                    // Side info bad: nBlockType == 0 pDblIn split block 
                    return FALSE; 
                }  
				else if (pToCel->nBlockType == 2 
						&& pToCel->mixedBlockFlag == 0)  
				{ 
					pToCel->region0Count = 8; 
                }  
				else  
				{ 
                    pToCel->region0Count = 7; 
                    pToCel->region1Count = 20 - pToCel->region0Count; 
                } 
                 
            }  
			else  
			{ 
                pToCel->arrSelect[0] = Bits(5); 
                pToCel->arrSelect[1] = Bits(5); 
                pToCel->arrSelect[2] = Bits(5); 
                pToCel->region0Count = Bits(4); 
                pToCel->region1Count = Bits(3); 
                pToCel->nBlockType = 0; 
            } 
            pToCel->scaleFactScale = Bits(1); 
            pToCel->countTblSelect = Bits(1); 
        }  
    }  
    return TRUE; 
} 
 
void CLayerIII::GetScaleFact(DWORD dwCh, DWORD dwGr) 
{ 
 
       int			nSfb, nWnd; 
    STR_GRINFO*	pGRLOCAL		= &(m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]); 
    int			nscaleFact   = pGRLOCAL->scaleFactCompress; 
    int			nLenLeft	   = slen[0][nscaleFact]; 
    int			nLenRight      = slen[1][nscaleFact]; 
     
 
     
    if (pGRLOCAL->wndSwitchFlag && (pGRLOCAL->nBlockType == 2)) { 
        if (pGRLOCAL->mixedBlockFlag)  
		{ // MIXED 
            for (nSfb = 0; nSfb < 8; nSfb++) 
                m_sCALEF[dwCh].l[nSfb] = GetBits( 
                slen[0][pGRLOCAL->scaleFactCompress]); 
            for (nSfb = 3; nSfb < 6; nSfb++) 
                for (nWnd=0; nWnd<3; nWnd++) 
                m_sCALEF[dwCh].s[nWnd][nSfb] = GetBits( 
                slen[0][pGRLOCAL->scaleFactCompress]); 
            for (nSfb = 6; nSfb < 12; nSfb++) 
                for (nWnd=0; nWnd<3; nWnd++) 
                m_sCALEF[dwCh].s[nWnd][nSfb] = GetBits( 
                slen[1][pGRLOCAL->scaleFactCompress]); 
            for (nSfb=12,nWnd=0; nWnd<3; nWnd++) 
                m_sCALEF[dwCh].s[nWnd][nSfb] = 0; 
             
            } else {  // SHORT 
 
            m_sCALEF[dwCh].s[0][0]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[1][0]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[2][0]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[0][1]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[1][1]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[2][1]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[0][2]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[1][2]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[2][2]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[0][3]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[1][3]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[2][3]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[0][4]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[1][4]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[2][4]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[0][5]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[1][5]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[2][5]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].s[0][6]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[1][6]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[2][6]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[0][7]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[1][7]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[2][7]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[0][8]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[1][8]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[2][8]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[0][9]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[1][9]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[2][9]  = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[0][10] = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[1][10] = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[2][10] = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[0][11] = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[1][11] = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[2][11] = GetBits(nLenRight); 
            m_sCALEF[dwCh].s[0][12] = 0; 
            m_sCALEF[dwCh].s[1][12] = 0; 
            m_sCALEF[dwCh].s[2][12] = 0; 
 
        } // SHORT 
         
        } else {   // LONG types 0,1,3 
         
        if ((m_SIDEINF.sArrCH[dwCh].arrScfSi[0] == 0) || (dwGr == 0)) { 
            m_sCALEF[dwCh].l[0]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[1]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[2]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[3]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[4]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[5]  = GetBits(nLenLeft); 
        } 
        if ((m_SIDEINF.sArrCH[dwCh].arrScfSi[1] == 0) || (dwGr == 0)) { 
            m_sCALEF[dwCh].l[6]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[7]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[8]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[9]  = GetBits(nLenLeft); 
            m_sCALEF[dwCh].l[10] = GetBits(nLenLeft); 
        } 
        if ((m_SIDEINF.sArrCH[dwCh].arrScfSi[2] == 0) || (dwGr == 0)) { 
            m_sCALEF[dwCh].l[11] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[12] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[13] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[14] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[15] = GetBits(nLenRight); 
        } 
        if ((m_SIDEINF.sArrCH[dwCh].arrScfSi[3] == 0) || (dwGr == 0)) { 
            m_sCALEF[dwCh].l[16] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[17] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[18] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[19] = GetBits(nLenRight); 
            m_sCALEF[dwCh].l[20] = GetBits(nLenRight); 
        } 
         
        m_sCALEF[dwCh].l[21] = 0; 
        m_sCALEF[dwCh].l[22] = 0; 
    } 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::GetLSFScaleData(DWORD dwCh, DWORD dwGr) 
{ 
    DWORD	newLength[4]; 
    DWORD	scFctComp, scFctCompInt; 
    int		nBlkType, nBlkNr; 
	DWORD	dwExtensionMode = m_dwExtensionMode; 
     
    STR_GRINFO *pGRLOCAL = &(m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]); 
     
    scFctComp =  pGRLOCAL->scaleFactCompress; 
     
    if (pGRLOCAL->nBlockType == 2)  
	{ 
        if (pGRLOCAL->mixedBlockFlag == 0) 
           nBlkType = 1; 
        else if (pGRLOCAL->mixedBlockFlag == 1) 
           nBlkType = 2; 
        else 
		    nBlkType = 0; 
    } else  
	{ 
        nBlkType = 0; 
    } 
     
    if(!(((dwExtensionMode == 1) || (dwExtensionMode == 3)) && (dwCh == 1)))  
	{ 
         
        if(scFctComp < 400)  
		{ 
             
            newLength[0] = (scFctComp >> 4) / 5 ; 
            newLength[1] = (scFctComp >> 4) % 5 ; 
            newLength[2] = (scFctComp & 0xF) >> 2 ; 
            newLength[3] = (scFctComp & 3); 
            m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].preflag = 0; 
            nBlkNr = 0; 
             
		} 
		else if (scFctComp  < 500)  
		{ 
             
            newLength[0] = ((scFctComp - 400) >> 2) / 5 ; 
            newLength[1] = ((scFctComp - 400) >> 2) % 5 ; 
            newLength[2] = (scFctComp - 400 ) & 3 ; 
            newLength[3] = 0; 
            m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].preflag = 0; 
             
            nBlkNr = 1; 
             
        }  
		else if (scFctComp < 512)  
		{ 
             
            newLength[0] = (scFctComp - 500 ) / 3 ; 
            newLength[1] = (scFctComp - 500)  % 3 ; 
            newLength[2] = 0; 
            newLength[3] = 0; 
            m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].preflag = 1; 
            nBlkNr = 2; 
        } 
    } 
    if((((dwExtensionMode == 1) || (dwExtensionMode == 3)) && (dwCh == 1))) 
    { 
        scFctCompInt = scFctComp >> 1; 
        if (scFctCompInt < 180) 
        { 
			newLength[0] = scFctCompInt  / 36 ; 
			newLength[1] = (scFctCompInt % 36 ) / 6 ; 
			newLength[2] = (scFctCompInt % 36) % 6; 
			newLength[3] = 0; 
			m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].preflag = 0; 
			nBlkNr = 3; 
		}  
		else if (scFctCompInt < 244)  
		{ 
			newLength[0] = ((scFctCompInt - 180 )  & 0x3F) >> 4 ; 
			newLength[1] = ((scFctCompInt - 180) & 0xF) >> 2 ; 
			newLength[2] = (scFctCompInt - 180 ) & 3 ; 
			newLength[3] = 0; 
			m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].preflag = 0; 
			nBlkNr = 4; 
		}  
		else if (scFctCompInt < 255)  
		{ 
			newLength[0] = (scFctCompInt - 244 ) / 3 ; 
			newLength[1] = (scFctCompInt - 244 )  % 3 ; 
			newLength[2] = 0 ; 
			newLength[3] = 0; 
			m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].preflag = 0; 
			nBlkNr = 5; 
        } 
    } 
    ZeroMemory(m_dwScale,sizeof(m_dwScale)); // why 45, not 54? 
     
    int m = 0; 
    for (DWORD dw=0; dw<4;dw++)  
	{ 
        for (DWORD j = 0; j < nr_of_nSfb_block[nBlkNr][nBlkType][dw];j++) 
        { 
            m_dwScale[m] = (newLength[dw] == 0) ? 0 : GetBits(newLength[dw]); 
            m++; 
        }  
    }  
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::GetLSFScaleFactor(DWORD dwCh, DWORD dwGr) 
{ 
    DWORD		m = 0; 
    DWORD		nSfb, nWnd; 
    STR_GRINFO *pGRLOCAL = &(m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]); 
     
    GetLSFScaleData(dwCh, dwGr); 
     
    if (pGRLOCAL->wndSwitchFlag && (pGRLOCAL->nBlockType == 2))  
	{ 
        if (pGRLOCAL->mixedBlockFlag)  
		{  // MIXED 
            for (nSfb = 0; nSfb < 8; nSfb++) 
            { 
                m_sCALEF[dwCh].l[nSfb] = m_dwScale[m]; 
                m++; 
            } 
 
            for (nSfb = 3; nSfb < 12; nSfb++)  
			{ 
                for (nWnd=0; nWnd<3; nWnd++) 
                { 
                    m_sCALEF[dwCh].s[nWnd][nSfb] = m_dwScale[m]; 
                    m++; 
                } 
            } 
            for (nWnd=0; nWnd<3; nWnd++) 
                m_sCALEF[dwCh].s[nWnd][12] = 0; 
             
        }  
		else  
		{  // SHORT 
             
            for (nSfb = 0; nSfb < 12; nSfb++)  
			{ 
                for (nWnd=0; nWnd<3; nWnd++) 
                { 
                    m_sCALEF[dwCh].s[nWnd][nSfb] = m_dwScale[m]; 
                    m++; 
                } 
            } 
            for (nWnd=0; nWnd < 3; nWnd++) 
                m_sCALEF[dwCh].s[nWnd][12] = 0; 
        } 
	}  
	else  
	{   // LONG types 0,1,3 
         
        for (nSfb = 0; nSfb < 21; nSfb++)  
		{ 
            m_sCALEF[dwCh].l[nSfb] = m_dwScale[m]; 
            m++; 
        } 
        m_sCALEF[dwCh].l[21] = 0; // Jeff 
        m_sCALEF[dwCh].l[22] = 0; 
    } 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::HuffmanDecode(DWORD dwCh, DWORD dwGr) 
{ 
    int x, y; 
    int v, w; 
    int part2_3_end = m_nPart2Start + m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].p23Len; 
    int num_bits; 
    int region1Start; 
    int region2Start; 
    int mIndex; 
    struct sHUFDECTAB *pHfDecTab; 
     
	 
    // Find region boundary for short block case 
    if ( (m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].wndSwitchFlag) && 
       (m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].nBlockType == 2) )  
	{ 
        // Region2. 
        region1Start = 36;  // nSfb[9/3]*3=36 
        region2Start = 576; // No Region2 for short block case 
         
    }  
	else  
	{          // Find region boundary for long block case 
        region1Start = sfBandIndex[m_nFreqIdx].l[m_SIDEINF.sArrCH[dwCh]. 
									sArrGRINF[dwGr].region0Count + 1]; 
        region2Start = sfBandIndex[m_nFreqIdx].l[m_SIDEINF.sArrCH[dwCh]. 
									sArrGRINF[dwGr].region0Count + 
									m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]. 
									region1Count + 2]; /* MI */ 
    } 
    mIndex = 0; 
    // Read bigvalues area 
    for (int dw=0; dw < (m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].bigVal<<1); dw+=2)  
	{ 
        if  (dw < (int)region1Start)  
			pHfDecTab = &ht[m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].arrSelect[0]]; 
        else if (dw < (int)region2Start)  
			pHfDecTab = &ht[m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].arrSelect[1]]; 
        else                 
			pHfDecTab = &ht[m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].arrSelect[2]]; 
        HuffmanDec(pHfDecTab, &x, &y, &v, &w); 
        m_nArray[mIndex++] = x; 
        m_nArray[mIndex++] = y; 
    } 
     
    // Read count1 area 
    pHfDecTab = &ht[m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr].countTblSelect+32]; 
    num_bits = GetReadBits(); 
     
    while ((num_bits < part2_3_end) && (mIndex < 576))  
	{ 
         
        HuffmanDec(pHfDecTab, &x, &y, &v, &w); 
         
        m_nArray[mIndex++] = v; 
        m_nArray[mIndex++] = w; 
        m_nArray[mIndex++] = x; 
        m_nArray[mIndex++] = y; 
        num_bits = GetReadBits(); 
    } 
     
    if (num_bits > part2_3_end)  
	{ 
        GoBackBits(num_bits - part2_3_end); 
        mIndex-=4; 
    } 
     
    num_bits = GetReadBits(); 
    // Dismiss stuffing bits 
    if (num_bits < part2_3_end) 
       GetBits(part2_3_end - num_bits); 
     
    // Zero pDblOut rest 
    if (mIndex < 576) 
        m_arrNonZero[dwCh] = mIndex; 
    else 
        m_arrNonZero[dwCh] = 576; 
	if(mIndex < 576) 
		ZeroMemory(m_nArray+mIndex,(576-mIndex)*sizeof(int)); 
 
} 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::DeqSample(double dbRectArr[32][18], DWORD dwCh, DWORD dwGr) 
{ 
   int			nCountb PURE; 
    int			nextCbBound, nBeginCb, nWidthCb; 
    int			mIndex=0, tIndex, j; 
    double		dblGain; 
    double*		pDblRectArr	= &dbRectArr[0][0]; 
	STR_GRINFO *pGRLOCAL	= &(m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]); 
     
    // choose correct scalefactor band per block type, initalize boundary 
    if (pGRLOCAL->wndSwitchFlag && (pGRLOCAL->nBlockType == 2) )  
	{ 
        if (pGRLOCAL->mixedBlockFlag) 
           nextCbBound=sfBandIndex[m_nFreqIdx].l[1];  // LONG blocks: 0,1,3 
        else  
		{ 
            nWidthCb = sfBandIndex[m_nFreqIdx].s[1]; 
            nextCbBound = (nWidthCb << 2) - nWidthCb; 
            nBeginCb = 0; 
        } 
    }  
	else  
	{ 
        nextCbBound=sfBandIndex[m_nFreqIdx].l[1];  // LONG blocks: 0,1,3 
    } 
    // Compute overall (global) scaling. 
    dblGain = (double) pow(2.0 , (0.25 * (pGRLOCAL->glbGain - 210.0))); 
     
    for (j=0; j 0) 
               pDblRectArr[j] = dblGain * t_43[abv]; 
            else 
                pDblRectArr[j] = -dblGain * t_43[-abv]; 
        } 
    } 
     
    // apply formula per block type 
    for (j=0; jwndSwitchFlag &&  
			   (pGRLOCAL->nBlockType == 2))  
			{ 
                if (pGRLOCAL->mixedBlockFlag)   
				{ 
                    if (mIndex == sfBandIndex[m_nFreqIdx].l[8])   
					{ 
                        nextCbBound = sfBandIndex[m_nFreqIdx].s[4]; 
                        nextCbBound = (nextCbBound << 2) - nextCbBound; 
                        nCountb = 3; 
                        nWidthCb = sfBandIndex[m_nFreqIdx].s[4] - sfBandIndex[m_nFreqIdx].s[3]; 
                        nBeginCb = sfBandIndex[m_nFreqIdx].s[3]; 
                        nBeginCb = (nBeginCb << 2) - nBeginCb; 
                         
                    }  
					else if (mIndex < sfBandIndex[m_nFreqIdx].l[8])  
					{ 
                        nextCbBound = sfBandIndex[m_nFreqIdx].l[(++nCountb)+1]; 
                    }  
					else  
					{ 
                         
                        nextCbBound = sfBandIndex[m_nFreqIdx].s[(++nCountb)+1]; 
                        nextCbBound = (nextCbBound << 2) - nextCbBound; 
                        nBeginCb = sfBandIndex[m_nFreqIdx].s[nCountb]; 
                        nWidthCb = sfBandIndex[m_nFreqIdx].s[nCountb+1] -  nBeginCb; 
                        nBeginCb = (nBeginCb << 2) - nBeginCb; 
                    } 
                     
                }  
				else   
				{ 
                    nextCbBound = sfBandIndex[m_nFreqIdx].s[(++nCountb)+1]; 
                    nextCbBound = (nextCbBound << 2) - nextCbBound; 
                    nBeginCb = sfBandIndex[m_nFreqIdx].s[nCountb]; 
                    nWidthCb = sfBandIndex[m_nFreqIdx].s[nCountb+1] - nBeginCb; 
                    nBeginCb = (nBeginCb << 2) - nBeginCb; 
                } 
           }  
		   else   
		   { // long blocks 
              nextCbBound = sfBandIndex[m_nFreqIdx].l[(++nCountb)+1]; 
           } 
        } 
        // Do long/short dependent scaling operations 
         
        if (pGRLOCAL->wndSwitchFlag && 
            (((pGRLOCAL->nBlockType == 2) &&  
		    (pGRLOCAL->mixedBlockFlag == 0)) || 
			((pGRLOCAL->nBlockType == 2) &&  
			pGRLOCAL->mixedBlockFlag && (j >= 36)) )) 
        { 
             
            tIndex = (mIndex - nBeginCb) / nWidthCb; 
            /*            dbRectArr[sb][ss] *= pow(2.0, ((-2.0 * pGRLOCAL->arrSubBlockGain[tIndex]) 
                                           -(0.5 * (1.0 + pGRLOCAL->scaleFactScale) 
                                           * m_sCALEF[dwCh].s[tIndex][nCountb]))); */ 
            DWORD idx = m_sCALEF[dwCh].s[tIndex][nCountb]  << pGRLOCAL->scaleFactScale; 
            idx += (pGRLOCAL->arrSubBlockGain[tIndex] << 2); 
            pDblRectArr[j] *= two_to_negative_half_pow[idx]; 
             
        }  
		else  
		{   // LONG block types 0,1,3 & 1st 2 subbands of switched blocks 
            /*    dbRectArr[sb][ss] *= pow(2.0, -0.5 * (1.0+pGRLOCAL->scaleFactScale) 
                                   * (m_sCALEF[dwCh].l[nCountb] 
                                   + pGRLOCAL->preflag * pretab[nCountb])); */ 
			DWORD idx = m_sCALEF[dwCh].l[nCountb]; 
             
			if (pGRLOCAL->preflag) 
				idx += pretab[nCountb]; 
			idx = idx << pGRLOCAL->scaleFactScale; 
			pDblRectArr[j] *= two_to_negative_half_pow[idx]; 
        } 
        mIndex++; 
    } 
	int nIndexx = m_arrNonZero[dwCh]; 
	ZeroMemory(pDblRectArr+nIndexx,sizeof(double)*(576-nIndexx)); 
    return; 
} 
 
 
void CLayerIII::SubBands(double dbRectArr[32][18]) 
{ 
   // 32 bands 18 samples/band 
    
    
         
 
} 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::Reorder(double dbRectArr[32][18], DWORD dwCh, DWORD dwGr) 
{ 
    DWORD		dFreq, dFrew3; 
    int			mIndex; 
    int			nSfb, nSfbStart, nSfbLines; 
    int			mSrcLine, iDesLine; 
	STR_GRINFO*	pGRLOCAL	= &(m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]); 
    double*		pDblRectArr = &dbRectArr[0][0]; 
     
    if (pGRLOCAL->wndSwitchFlag && (pGRLOCAL->nBlockType == 2))  
	{ 
         
		ZeroMemory(m_dOutArr,sizeof(m_dOutArr)); 
         
        if (pGRLOCAL->mixedBlockFlag)  
		{ 
            // NO REORDER FOR LOW 2 SUBBANDS 
			CopyMemory(m_dOutArr,pDblRectArr,sizeof(double)*36); 
 
			 
             
            // REORDERING FOR REST SWITCHED SHORT 
            for(nSfb=3,nSfbStart=sfBandIndex[m_nFreqIdx].s[3], 
				nSfbLines=sfBandIndex[m_nFreqIdx].s[4] - nSfbStart; 
				nSfb < 13; nSfb++,nSfbStart = sfBandIndex[m_nFreqIdx].s[nSfb], 
                (nSfbLines=sfBandIndex[m_nFreqIdx].s[nSfb+1] - nSfbStart)) 
            { 
                int nSfbStart3 = (nSfbStart << 2) - nSfbStart; 
                 
                for(dFreq = 0, dFrew3 = 0; dFreq < (DWORD)nSfbLines; dFreq++, dFrew3 += 3)  
				{ 
                     
                    mSrcLine = nSfbStart3 + dFreq; 
                    iDesLine = nSfbStart3 + dFrew3; 
                    m_dOutArr[iDesLine] = pDblRectArr[mSrcLine]; 
                    mSrcLine += nSfbLines; 
                    iDesLine++; 
                    m_dOutArr[iDesLine] = pDblRectArr[mSrcLine]; 
                    mSrcLine += nSfbLines; 
                    iDesLine++; 
                    m_dOutArr[iDesLine] = pDblRectArr[mSrcLine]; 
                } 
            } 
             
		}  
		else  
		{   
			mIndex = 0; 
			while(mIndex<576) 
			{ 
				m_dOutArr[mIndex] = pDblRectArr[reorder_table[m_nFreqIdx][mIndex++]]; 
			} 
        } 
    } 
    else  
	{ 
		CopyMemory(m_dOutArr,pDblRectArr,32*18*sizeof(DOUBLE));//sizeof(m_dOutArr)); 
    } 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::IStereoKValues(DWORD dwIsPos, DWORD dwIoType,  DWORD dw) 
{ 
     if (dwIsPos == 0)  
	{ 
        m_theKArray[0][dw] = 1.0f; 
		m_theKArray[1][dw] = 1.0f; 
    }  
	else if (dwIsPos & 1)  
	{ 
		m_theKArray[0][dw] = io[dwIoType][(dwIsPos + 1) >> 1]; 
        m_theKArray[1][dw] = 1.0f; 
    }  
	else  
	{ 
        m_theKArray[0][dw] = 1.0f; 
        m_theKArray[1][dw] = io[dwIoType][dwIsPos >> 1]; 
    } 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
int CLayerIII::Stereo(DWORD dwGr) 
{ 
    int sb, ss; 
 
 
 
    if  (m_nChanels == 1)  
    { 
		memcpy(m_cubeLr[0], m_cubeRo[0], sizeof(m_cubeLr[0][0][0]) * 18 * 32); 
        /* 
		for(ss=0; ss < 32; ss++) 
 
			for(sb=0; sb < 18; sb+=3)  
            { 
				m_cubeLr[0][ss][sb]   = m_cubeRo[0][ss][sb]; 
                m_cubeLr[0][ss][sb+1] = m_cubeRo[0][ss][sb+1]; 
				m_cubeLr[0][ss][sb+2] = m_cubeRo[0][ss][sb+2]; 
            } 
			*/ 
    } 
    else 
    { 
   	DWORD		dwIsPos[576]; 
	double		dRatio[576]; 
	STR_GRINFO *pGRLOCAL = &(m_SIDEINF.sArrCH[0].sArrGRINF[dwGr]); 
	DWORD		dwExtensionMode = m_dwExtensionMode; 
	int			nSfb; 
	int			dw	= 0; 
	int			lines, temp, temp2; 
 
	BOOL	bStereoMs	= (m_flMode == 1) && (dwExtensionMode & 0x2); 
	BOOL	bIStereo	= (m_flMode == 1) && (dwExtensionMode & 0x1); 
	BOOL	bLayerVers	= (m_version == 0); 
	DWORD	dwIoType	= (pGRLOCAL->scaleFactCompress & 1); 
 
	// initialization 
	while(dw < 576)         
		dwIsPos[dw++] = 7; 
	 
 
	if (bIStereo)  
	{ 
		if (pGRLOCAL->wndSwitchFlag && (pGRLOCAL->nBlockType == 2))  
		{ 
			if (pGRLOCAL->mixedBlockFlag)  
			{ 
				int iSfbMax = 0; 
             
				for (DWORD j=0; j<3; j++)  
				{ 
					int nSfbcnt = 2; 
                 
					for( nSfb=12; nSfb >=3; nSfb-- )  
					{ 
						dw		= sfBandIndex[m_nFreqIdx].s[nSfb]; 
						lines	= sfBandIndex[m_nFreqIdx].s[nSfb+1] - dw; 
						dw		= (dw << 2) - dw + (j+1) * lines - 1; 
                     
						while (lines > 0)  
						{ 
							if (m_cubeRo[1][ss_div[dw]][ss_mod[dw]] != 0.0f)  
							{ 
								nSfbcnt = nSfb; 
								nSfb = -10; 
								lines = -10; 
							} 
							lines--; 
							dw--; 
						}  
					}  
					nSfb = nSfbcnt + 1; 
					if (nSfb > iSfbMax) 
					   iSfbMax = nSfb; 
                 
					while(nSfb < 12)  
					{ 
						temp = sfBandIndex[m_nFreqIdx].s[nSfb]; 
						sb   = sfBandIndex[m_nFreqIdx].s[nSfb+1] - temp; 
						dw    = (temp << 2) - temp + j * sb; 
                     
						for ( ; sb > 0; sb--)  
						{ 
							dwIsPos[dw] = m_sCALEF[1].s[j][nSfb]; 
							if (dwIsPos[dw] != 7) 
							   if (bLayerVers) 
							   IStereoKValues(dwIsPos[dw], dwIoType, dw); 
							else 
								dRatio[dw] = TAN12[dwIsPos[dw]]; 
                         
							dw++; 
						} // for (; sb>0... 
						nSfb++; 
					} // while (nSfb < 12) 
					nSfb	= sfBandIndex[m_nFreqIdx].s[10]; 
					sb  = sfBandIndex[m_nFreqIdx].s[11] - nSfb; 
					nSfb	= (nSfb << 2) - nSfb + j * sb; 
					temp	= sfBandIndex[m_nFreqIdx].s[11]; 
					sb	= sfBandIndex[m_nFreqIdx].s[12] - temp; 
					dw		= (temp << 2) - temp + j * sb; 
					for (; sb > 0; sb--)  
					{ 
						dwIsPos[dw] = dwIsPos[nSfb]; 
                     
						if (bLayerVers)  
						{ 
							m_theKArray[0][dw] = m_theKArray[0][nSfb]; 
							m_theKArray[1][dw] = m_theKArray[1][nSfb]; 
						}  
						else  
						{ 
							dRatio[dw] = dRatio[nSfb]; 
						} 
						dw++; 
					}  
				} 
				if (iSfbMax <= 3)  
				{ 
					dw		= 2; 
					ss	= 17; 
					sb	= -1; 
 
					while (dw >= 0)  
					{ 
						if (m_cubeRo[1][dw][ss] != 0.0f)  
						{ 
							sb = (dw<<4) + (dw<<1) + ss; 
							dw = -1; 
						}  
						else  
						{ 
							ss--; 
							if (ss < 0)  
							{ 
								dw--; 
								ss = 17; 
							} 
						}  
					}  
					dw = 0; 
					while (sfBandIndex[m_nFreqIdx].l[dw] <= sb) 
						  dw++; 
					nSfb = dw; 
					dw = sfBandIndex[m_nFreqIdx].l[dw]; 
					for (; nSfb<8; nSfb++)  
					{ 
						sb = sfBandIndex[m_nFreqIdx].l[nSfb+1] -  
								 sfBandIndex[m_nFreqIdx].l[nSfb]; 
						for (; sb>0; sb--)  
						{ 
							dwIsPos[dw] = m_sCALEF[1].l[nSfb]; 
							if (dwIsPos[dw] != 7) 
							{ 
							   if (bLayerVers) 
									IStereoKValues(dwIsPos[dw], dwIoType, dw); 
							} 
							else 
								dRatio[dw] = TAN12[dwIsPos[dw]]; 
							dw++; 
						}  
					}  
				}  
			}  
			else  
			{ 
				for (DWORD j=0; j<3; j++)  
				{ 
					int nSfbcnt = -1; 
					for( nSfb=12; nSfb >=0; nSfb-- ) 
					{ 
						temp	= sfBandIndex[m_nFreqIdx].s[nSfb]; 
						lines	= sfBandIndex[m_nFreqIdx].s[nSfb+1] - temp; 
						dw		= (temp << 2) - temp + (j+1) * lines - 1; 
                     
						while (lines > 0) { 
							if (m_cubeRo[1][ss_div[dw]][ss_mod[dw]] != 0.0f)  
							{ 
								nSfbcnt = nSfb; 
								nSfb = -10; 
								lines = -10; 
							} 
							lines--; 
							dw--; 
						}  
                     
					}  
					nSfb = nSfbcnt + 1; 
					while(nSfb<12)  
					{ 
						temp	= sfBandIndex[m_nFreqIdx].s[nSfb]; 
						sb  = sfBandIndex[m_nFreqIdx].s[nSfb+1] - temp; 
						dw		= (temp << 2) - temp + j * sb; 
						for ( ; sb > 0; sb--)  
						{ 
							dwIsPos[dw] = m_sCALEF[1].s[j][nSfb]; 
							if (dwIsPos[dw] != 7) 
							   if (bLayerVers) 
							   IStereoKValues(dwIsPos[dw], dwIoType, dw); 
							else 
								dRatio[dw] = TAN12[dwIsPos[dw]]; 
							dw++; 
						} 
						nSfb++; 
					} // while (nSfb<12) 
                 
					temp	= sfBandIndex[m_nFreqIdx].s[10]; 
					temp2	= sfBandIndex[m_nFreqIdx].s[11]; 
					sb  = temp2 - temp; 
					nSfb	= (temp << 2) - temp + j * sb; 
					sb  = sfBandIndex[m_nFreqIdx].s[12] - temp2; 
					dw		= (temp2 << 2) - temp2 + j * sb; 
                 
					for (; sb>0; sb--)  
					{ 
						dwIsPos[dw] = dwIsPos[nSfb]; 
						if (bLayerVers)  
						{ 
							m_theKArray[0][dw] = m_theKArray[0][nSfb]; 
							m_theKArray[1][dw] = m_theKArray[1][nSfb]; 
						}  
						else  
						{ 
							dRatio[dw] = dRatio[nSfb]; 
						} 
						dw++; 
					}  
				}  
			} 
		}  
		else  
		{ // if (pGRLOCAL->wndSwitchFlag ... 
			dw		= 31; 
			ss	= 17; 
			sb	= 0; 
			while (dw >= 0)  
			{ 
				if (m_cubeRo[1][dw][ss] != 0.0f)  
				{ 
					sb = (dw<<4) + (dw<<1) + ss; 
					dw = -1; 
				}  
				else  
				{ 
					ss--; 
					if (ss < 0)  
					{ 
						dw--; 
						ss = 17; 
					} 
				} 
			} 
			dw = 0; 
			while (sfBandIndex[m_nFreqIdx].l[dw] <= sb) 
				  dw++; 
			nSfb	= dw; 
			dw		= sfBandIndex[m_nFreqIdx].l[dw]; 
 
			for (; nSfb<21; nSfb++)  
			{ 
				sb =	sfBandIndex[m_nFreqIdx].l[nSfb+1] -  
							sfBandIndex[m_nFreqIdx].l[nSfb]; 
				for (; sb > 0; sb--) { 
					dwIsPos[dw] = m_sCALEF[1].l[nSfb]; 
					if (dwIsPos[dw] != 7) 
					   if (bLayerVers) 
					   IStereoKValues(dwIsPos[dw], dwIoType, dw); 
					else 
						dRatio[dw] = TAN12[dwIsPos[dw]]; 
					dw++; 
				} 
			} 
			nSfb = sfBandIndex[m_nFreqIdx].l[20]; 
			for (sb = 576 - sfBandIndex[m_nFreqIdx].l[21]; (sb > 0) && (dw<576); sb--) 
			{ 
				dwIsPos[dw] = dwIsPos[nSfb]; // error here : dw >=576 
             
				if (bLayerVers) { 
					m_theKArray[0][dw] = m_theKArray[0][nSfb]; 
					m_theKArray[1][dw] = m_theKArray[1][nSfb]; 
					} else { 
					dRatio[dw] = dRatio[nSfb]; 
				} 
				dw++; 
			} // if (pGRLOCAL->mixedBlockFlag) 
		} // if (pGRLOCAL->wndSwitchFlag ... 
	} // if (bIStereo) 
 
	dw = 0; 
	for(sb=0;sb<32;sb++) 
	   for(ss=0;ss<18;ss++)  
		{ 
			if (dwIsPos[dw] == 7)  
			{ 
				if (bStereoMs)  
				{ 
					m_cubeLr[0][sb][ss] = (m_cubeRo[0][sb][ss]+ 
												m_cubeRo[1][sb][ss])  
												* 0.707106781f; 
					m_cubeLr[1][sb][ss] = (m_cubeRo[0][sb][ss]- 
												m_cubeRo[1][sb][ss])  
												* 0.707106781f; 
				}  
				else  
				{ 
					m_cubeLr[0][sb][ss] = m_cubeRo[0][sb][ss]; 
					m_cubeLr[1][sb][ss] = m_cubeRo[1][sb][ss]; 
				} 
			} 
			else if (bIStereo)  
			{ 
         
				if (bLayerVers)  
				{ 
					m_cubeLr[0][sb][ss] = m_cubeRo[0][sb][ss] *  
													m_theKArray[0][dw]; 
					m_cubeLr[1][sb][ss] = m_cubeRo[0][sb][ss] *  
													m_theKArray[1][dw]; 
					} else { 
					m_cubeLr[1][sb][ss] = m_cubeRo[0][sb][ss] /  
													(double) (1 + dRatio[dw]); 
					m_cubeLr[0][sb][ss] = m_cubeLr[1][sb][ss] *  
													dRatio[dw]; 
				} 
			} 
			else  
			{ 
				TRACE("Error Stereo processing"); 
				ASSERT(0); 
			} 
		dw++; 
	} 
 
    } 
    return 0; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::AntiAlias(DWORD dwCh, DWORD dwGr) 
{ 
    int			iSb18, ss, sb18lim; 
    STR_GRINFO *pGRLOCAL = &(m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]); 
     
    // 31 alias-reduction operations between each pair of sub-bands 
    // with 8 butterflies between each pair 
    if  (pGRLOCAL->wndSwitchFlag &&  
		(pGRLOCAL->nBlockType == 2) && 
        !pGRLOCAL->mixedBlockFlag ) 
        return; 
     
    if (pGRLOCAL->wndSwitchFlag &&  
		pGRLOCAL->mixedBlockFlag && 
       (pGRLOCAL->nBlockType == 2))  
	{ 
        sb18lim = 18; 
    }  
	else  
	{ 
        sb18lim = 558; 
    } 
     
    for (iSb18=0; iSb18 < sb18lim; iSb18+=18)  
	{ 
        for (ss=0;ss<8;ss++)  
		{ 
            int iDx1 = iSb18 + 17 - ss; 
            int iDx2 = iSb18 + 18 + ss; 
            double dBu = m_dOutArr[iDx1]; 
            double dBd = m_dOutArr[iDx2]; 
            m_dOutArr[iDx1] = (dBu * cs[ss]) - (dBd * ca[ss]); 
            m_dOutArr[iDx2] = (dBd * cs[ss]) + (dBu * ca[ss]); 
        } 
    } 
 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::Hibrid(DWORD dwCh, DWORD dwGr) 
{ 
        double		dOurRaw[36]; 
    DWORD		dwBt		PURE;	 
    int			iSb18		PURE; 
    double*		pdTsOut		PURE; 
    double*		pdPrvBlok	PURE; 
	STR_GRINFO*	pGRLOCAL = &(m_SIDEINF.sArrCH[dwCh].sArrGRINF[dwGr]); 
     
    for(iSb18=0; iSb18<576; iSb18+=18)  
	{ 
         
        dwBt = (pGRLOCAL->wndSwitchFlag && pGRLOCAL->mixedBlockFlag && 
					(iSb18 < 36)) ? 0 : pGRLOCAL->nBlockType; 
         
        pdTsOut = m_dOutArr + iSb18; 
         
        InvMdcdt(pdTsOut, dOurRaw, dwBt); 
         
        pdPrvBlok = &m_PreBlkArr[dwCh][iSb18]; 
        pdTsOut[0]   = dOurRaw[0]  + pdPrvBlok[0]; 
        pdPrvBlok[0]  = dOurRaw[18]; 
        pdTsOut[1]   = dOurRaw[1]  + pdPrvBlok[1]; 
        pdPrvBlok[1]  = dOurRaw[19]; 
        pdTsOut[2]   = dOurRaw[2]  + pdPrvBlok[2]; 
        pdPrvBlok[2]  = dOurRaw[20]; 
        pdTsOut[3]   = dOurRaw[3]  + pdPrvBlok[3]; 
        pdPrvBlok[3]  = dOurRaw[21]; 
        pdTsOut[4]   = dOurRaw[4]  + pdPrvBlok[4]; 
        pdPrvBlok[4]  = dOurRaw[22]; 
        pdTsOut[5]   = dOurRaw[5]  + pdPrvBlok[5]; 
        pdPrvBlok[5]  = dOurRaw[23]; 
        pdTsOut[6]   = dOurRaw[6]  + pdPrvBlok[6]; 
        pdPrvBlok[6]  = dOurRaw[24]; 
        pdTsOut[7]   = dOurRaw[7]  + pdPrvBlok[7]; 
        pdPrvBlok[7]  = dOurRaw[25]; 
        pdTsOut[8]   = dOurRaw[8]  + pdPrvBlok[8]; 
        pdPrvBlok[8]  = dOurRaw[26]; 
        pdTsOut[9]   = dOurRaw[9]  + pdPrvBlok[9]; 
        pdPrvBlok[9]  = dOurRaw[27]; 
        pdTsOut[10]  = dOurRaw[10] + pdPrvBlok[10]; 
        pdPrvBlok[10] = dOurRaw[28]; 
        pdTsOut[11]  = dOurRaw[11] + pdPrvBlok[11]; 
        pdPrvBlok[11] = dOurRaw[29]; 
        pdTsOut[12]  = dOurRaw[12] + pdPrvBlok[12]; 
        pdPrvBlok[12] = dOurRaw[30]; 
        pdTsOut[13]  = dOurRaw[13] + pdPrvBlok[13]; 
        pdPrvBlok[13] = dOurRaw[31]; 
        pdTsOut[14]  = dOurRaw[14] + pdPrvBlok[14]; 
        pdPrvBlok[14] = dOurRaw[32]; 
        pdTsOut[15]  = dOurRaw[15] + pdPrvBlok[15]; 
        pdPrvBlok[15] = dOurRaw[33]; 
        pdTsOut[16]  = dOurRaw[16] + pdPrvBlok[16]; 
        pdPrvBlok[16] = dOurRaw[34]; 
        pdTsOut[17]  = dOurRaw[17] + pdPrvBlok[17]; 
        pdPrvBlok[17] = dOurRaw[35]; 
    } 
 
} 
 
 
 
 
void CLayerIII::InvMdcdt(double *pDblIn, double *pDblOut, int nBlockType) 
{ 
    double    tmp[18]; 
    double    *win_bt; 
    int   dw; 
     
    if(nBlockType == 2) 
    { 
        /* 
        for(int p=0;p<36;p+=9)  
        { 
            pDblOut[p]   = pDblOut[p+1] = pDblOut[p+2] = pDblOut[p+3] = 
                pDblOut[p+4] = pDblOut[p+5] = pDblOut[p+6] = pDblOut[p+7] = 
                pDblOut[p+8] = 0.0f; 
        } 
        */ 
        ZeroMemory(pDblOut,sizeof(double)*36); 
         
        int six_i = 0; 
         
        for(dw=0;dw<3;dw++) 
        { 
             
            // 12 point IMDCT 
             
            // Begin 12 point IDCT 
             
            // Input aliasing for 12 pt IDCT 
            pDblIn[15+dw] += pDblIn[12+dw];  
            pDblIn[12+dw] += pDblIn[9+dw];  
            pDblIn[9+dw]  +=  pDblIn[6+dw]; 
            pDblIn[6+dw]  += pDblIn[3+dw];   
            pDblIn[3+dw]  += pDblIn[0+dw]; 
             
            // Input aliasing on odd indices (for 6 point IDCT) 
            pDblIn[15+dw] += pDblIn[9+dw];  pDblIn[9+dw]  += pDblIn[3+dw]; 
             
            // 3 point IDCT on even indices 
             
            { 
                double  pp1, pp2, sum; 
                pp2 = pDblIn[12+dw] * 0.500000000f; 
                pp1 = pDblIn[ 6+dw] * 0.866025403f; 
                sum = pDblIn[0+dw] + pp2; 
                tmp[1] = pDblIn[0+dw] - pDblIn[12+dw]; 
                tmp[0] = sum + pp1; 
                tmp[2] = sum - pp1; 
                 
                // End 3 point IDCT on even indices 
                 
                // 3 point IDCT on odd indices (for 6 point IDCT) 
                 
                pp2 = pDblIn[15+dw] * 0.500000000f; 
                pp1 = pDblIn[ 9+dw] * 0.866025403f; 
                sum = pDblIn[ 3+dw] + pp2; 
                tmp[4] = pDblIn[3+dw] - pDblIn[15+dw]; 
                tmp[5] = sum + pp1; 
                tmp[3] = sum - pp1; 
            } 
             
            // End 3 point IDCT on odd indices 
             
            // Twiddle factors on odd indices (for 6 point IDCT) 
             
            tmp[3] *= 1.931851653f; 
            tmp[4] *= 0.707106781f; 
            tmp[5] *= 0.517638090f; 
             
            // Output butterflies on 2 3 point IDCT's (for 6 point IDCT) 
             
            { 
                double save = tmp[0]; 
                tmp[0] += tmp[5]; 
                tmp[5] = save - tmp[5]; 
                save = tmp[1]; 
                tmp[1] += tmp[4]; 
                tmp[4] = save - tmp[4]; 
                save = tmp[2]; 
                tmp[2] += tmp[3]; 
                tmp[3] = save - tmp[3]; 
            } 
             
            // End 6 point IDCT 
             
            // Twiddle factors on indices (for 12 point IDCT) 
             
            tmp[0]  *=  0.504314480f; 
            tmp[1]  *=  0.541196100f; 
            tmp[2]  *=  0.630236207f; 
            tmp[3]  *=  0.821339815f; 
            tmp[4]  *=  1.306562965f; 
            tmp[5]  *=  3.830648788f; 
             
            // End 12 point IDCT 
             
            // Shift to 12 point modified IDCT, multiply by nWnd type 2 
            tmp[8]  = -tmp[0] * 0.793353340f; 
            tmp[9]  = -tmp[0] * 0.608761429f; 
            tmp[7]  = -tmp[1] * 0.923879532f; 
            tmp[10] = -tmp[1] * 0.382683432f; 
            tmp[6]  = -tmp[2] * 0.991444861f; 
            tmp[11] = -tmp[2] * 0.130526192f; 
             
            tmp[0]  =  tmp[3]; 
            tmp[1]  =  tmp[4] * 0.382683432f; 
            tmp[2]  =  tmp[5] * 0.608761429f; 
             
            tmp[3]  = -tmp[5] * 0.793353340f; 
            tmp[4]  = -tmp[4] * 0.923879532f; 
            tmp[5]  = -tmp[0] * 0.991444861f; 
             
            tmp[0] *= 0.130526192f; 
             
            pDblOut[six_i + 6]  += tmp[0]; 
            pDblOut[six_i + 7]  += tmp[1]; 
            pDblOut[six_i + 8]  += tmp[2]; 
            pDblOut[six_i + 9]  += tmp[3]; 
            pDblOut[six_i + 10] += tmp[4]; 
            pDblOut[six_i + 11] += tmp[5]; 
            pDblOut[six_i + 12] += tmp[6]; 
            pDblOut[six_i + 13] += tmp[7]; 
            pDblOut[six_i + 14] += tmp[8]; 
            pDblOut[six_i + 15] += tmp[9]; 
            pDblOut[six_i + 16] += tmp[10]; 
            pDblOut[six_i + 17] += tmp[11]; 
             
            six_i += 6; 
        } 
         
        } else { 
         
         
        // 36 point IDCT 
         
        // input aliasing for 36 point IDCT 
        pDblIn[17]+=pDblIn[16]; pDblIn[16]+=pDblIn[15]; pDblIn[15]+=pDblIn[14]; pDblIn[14]+=pDblIn[13]; 
        pDblIn[13]+=pDblIn[12]; pDblIn[12]+=pDblIn[11]; pDblIn[11]+=pDblIn[10]; pDblIn[10]+=pDblIn[9]; 
        pDblIn[9] +=pDblIn[8];  pDblIn[8] +=pDblIn[7];  pDblIn[7] +=pDblIn[6];  pDblIn[6] +=pDblIn[5]; 
        pDblIn[5] +=pDblIn[4];  pDblIn[4] +=pDblIn[3];  pDblIn[3] +=pDblIn[2];  pDblIn[2] +=pDblIn[1]; 
        pDblIn[1] +=pDblIn[0]; 
         
        // 18 point IDCT for odd indices 
         
        // input aliasing for 18 point IDCT 
        pDblIn[17]+=pDblIn[15]; pDblIn[15]+=pDblIn[13]; pDblIn[13]+=pDblIn[11]; pDblIn[11]+=pDblIn[9]; 
        pDblIn[9] +=pDblIn[7];  pDblIn[7] +=pDblIn[5];  pDblIn[5] +=pDblIn[3];  pDblIn[3] +=pDblIn[1]; 
         
        { 
            double tmp0,tmp1,tmp2,tmp3,tmp4,tmp0_,tmp1_,tmp2_,tmp3_; 
            double tmp0o,tmp1o,tmp2o,tmp3o,tmp4o,tmp0_o,tmp1_o,tmp2_o,tmp3_o; 
             
            // Fast 9 Point Inverse Discrete Cosine Transform 
            // 
            // By  Francois-Raymond Boyer 
            //         mailto:boyerf@iro.umontdouble.ca 
            //         http://www.iro.umontdouble.ca/~boyerf 
            // 
            // The code has been optimized for Intel processors 
            //  (takes a lot of time to convert float to and from iternal FPU representation) 
            // 
            // It is a simple "factorization" of the IDCT matrix. 
             
            // 9 point IDCT on even indices 
            { 
                // 5 points on odd indices (not doubley an IDCT) 
                double i0 = pDblIn[0]+pDblIn[0]; 
                double i0p12 = i0 + pDblIn[12]; 
                 
                tmp0 = i0p12 + pDblIn[4]*1.8793852415718f  + pDblIn[8]*1.532088886238f   + pDblIn[16]*0.34729635533386f; 
                tmp1 = i0    + pDblIn[4]                   - pDblIn[8] - pDblIn[12] - pDblIn[12] - pDblIn[16]; 
                tmp2 = i0p12 - pDblIn[4]*0.34729635533386f - pDblIn[8]*1.8793852415718f  + pDblIn[16]*1.532088886238f; 
                tmp3 = i0p12 - pDblIn[4]*1.532088886238f   + pDblIn[8]*0.34729635533386f - pDblIn[16]*1.8793852415718f; 
                tmp4 = pDblIn[0] - pDblIn[4]                   + pDblIn[8] - pDblIn[12]          + pDblIn[16]; 
                 
                // 4 points on even indices 
                double i6_ = pDblIn[6]*1.732050808f;  // Sqrt[3] 
                 
                tmp0_ = pDblIn[2]*1.9696155060244f  + i6_ + pDblIn[10]*1.2855752193731f  + pDblIn[14]*0.68404028665134f; 
                tmp1_ = (pDblIn[2]                        - pDblIn[10]                   - pDblIn[14])*1.732050808f; 
                tmp2_ = pDblIn[2]*1.2855752193731f  - i6_ - pDblIn[10]*0.68404028665134f + pDblIn[14]*1.9696155060244f; 
                tmp3_ = pDblIn[2]*0.68404028665134f - i6_ + pDblIn[10]*1.9696155060244f  - pDblIn[14]*1.2855752193731f; 
            } 
             
            // 9 point IDCT on odd indices 
            { 
                // 5 points on odd indices (not doubley an IDCT) 
                double i0 = pDblIn[0+1]+pDblIn[0+1]; 
                double i0p12 = i0 + pDblIn[12+1]; 
                 
                tmp0o = i0p12   + pDblIn[4+1]*1.8793852415718f  + pDblIn[8+1]*1.532088886238f       + pDblIn[16+1]*0.34729635533386f; 
                tmp1o = i0      + pDblIn[4+1]                   - pDblIn[8+1] - pDblIn[12+1] - pDblIn[12+1] - pDblIn[16+1]; 
                tmp2o = i0p12   - pDblIn[4+1]*0.34729635533386f - pDblIn[8+1]*1.8793852415718f      + pDblIn[16+1]*1.532088886238f; 
                tmp3o = i0p12   - pDblIn[4+1]*1.532088886238f   + pDblIn[8+1]*0.34729635533386f     - pDblIn[16+1]*1.8793852415718f; 
                tmp4o = (pDblIn[0+1] - pDblIn[4+1]                   + pDblIn[8+1] - pDblIn[12+1]            + pDblIn[16+1])*0.707106781f; // Twiddled 
                 
                // 4 points on even indices 
                double i6_ = pDblIn[6+1]*1.732050808f;  // Sqrt[3] 
                 
                tmp0_o = pDblIn[2+1]*1.9696155060244f  + i6_ + pDblIn[10+1]*1.2855752193731f  + pDblIn[14+1]*0.68404028665134f; 
                tmp1_o = (pDblIn[2+1]                        - pDblIn[10+1]                   - pDblIn[14+1])*1.732050808f; 
                tmp2_o = pDblIn[2+1]*1.2855752193731f  - i6_ - pDblIn[10+1]*0.68404028665134f + pDblIn[14+1]*1.9696155060244f; 
                tmp3_o = pDblIn[2+1]*0.68404028665134f - i6_ + pDblIn[10+1]*1.9696155060244f  - pDblIn[14+1]*1.2855752193731f; 
            } 
             
            // Twiddle factors on odd indices 
            // and 
            // Butterflies on 9 point IDCT's 
            // and 
            // twiddle factors for 36 point IDCT 
             
            double e, o; 
            e = tmp0 + tmp0_; o = (tmp0o + tmp0_o)*0.501909918f; tmp[0] = e + o;    tmp[17] = e - o; 
            e = tmp1 + tmp1_; o = (tmp1o + tmp1_o)*0.517638090f; tmp[1] = e + o;    tmp[16] = e - o; 
            e = tmp2 + tmp2_; o = (tmp2o + tmp2_o)*0.551688959f; tmp[2] = e + o;    tmp[15] = e - o; 
            e = tmp3 + tmp3_; o = (tmp3o + tmp3_o)*0.610387294f; tmp[3] = e + o;    tmp[14] = e - o; 
            tmp[4] = tmp4 + tmp4o; tmp[13] = tmp4 - tmp4o; 
            e = tmp3 - tmp3_; o = (tmp3o - tmp3_o)*0.871723397f; tmp[5] = e + o;    tmp[12] = e - o; 
            e = tmp2 - tmp2_; o = (tmp2o - tmp2_o)*1.183100792f; tmp[6] = e + o;    tmp[11] = e - o; 
            e = tmp1 - tmp1_; o = (tmp1o - tmp1_o)*1.931851653f; tmp[7] = e + o;    tmp[10] = e - o; 
            e = tmp0 - tmp0_; o = (tmp0o - tmp0_o)*5.736856623f; tmp[8] = e + o;    tmp[9] =  e - o; 
        } 
         
        // end 36 point IDCT */ 
         
        // shift to modified IDCT 
        win_bt = dblWin[nBlockType]; 
         
        pDblOut[0] =-tmp[9]  * win_bt[0]; 
        pDblOut[1] =-tmp[10] * win_bt[1]; 
        pDblOut[2] =-tmp[11] * win_bt[2]; 
        pDblOut[3] =-tmp[12] * win_bt[3]; 
        pDblOut[4] =-tmp[13] * win_bt[4]; 
        pDblOut[5] =-tmp[14] * win_bt[5]; 
        pDblOut[6] =-tmp[15] * win_bt[6]; 
        pDblOut[7] =-tmp[16] * win_bt[7]; 
        pDblOut[8] =-tmp[17] * win_bt[8]; 
         
        pDblOut[9] = tmp[17] * win_bt[9]; 
        pDblOut[10]= tmp[16] * win_bt[10]; 
        pDblOut[11]= tmp[15] * win_bt[11]; 
        pDblOut[12]= tmp[14] * win_bt[12]; 
        pDblOut[13]= tmp[13] * win_bt[13]; 
        pDblOut[14]= tmp[12] * win_bt[14]; 
        pDblOut[15]= tmp[11] * win_bt[15]; 
        pDblOut[16]= tmp[10] * win_bt[16]; 
        pDblOut[17]= tmp[9]  * win_bt[17]; 
        pDblOut[18]= tmp[8]  * win_bt[18]; 
        pDblOut[19]= tmp[7]  * win_bt[19]; 
        pDblOut[20]= tmp[6]  * win_bt[20]; 
        pDblOut[21]= tmp[5]  * win_bt[21]; 
        pDblOut[22]= tmp[4]  * win_bt[22]; 
        pDblOut[23]= tmp[3]  * win_bt[23]; 
        pDblOut[24]= tmp[2]  * win_bt[24]; 
        pDblOut[25]= tmp[1]  * win_bt[25]; 
        pDblOut[26]= tmp[0]  * win_bt[26]; 
         
        pDblOut[27]= tmp[0]  * win_bt[27]; 
        pDblOut[28]= tmp[1]  * win_bt[28]; 
        pDblOut[29]= tmp[2]  * win_bt[29]; 
        pDblOut[30]= tmp[3]  * win_bt[30]; 
        pDblOut[31]= tmp[4]  * win_bt[31]; 
        pDblOut[32]= tmp[5]  * win_bt[32]; 
        pDblOut[33]= tmp[6]  * win_bt[33]; 
        pDblOut[34]= tmp[7]  * win_bt[34]; 
        pDblOut[35]= tmp[8]  * win_bt[35]; 
    } 
} 
 
DWORD CLayerIII::Bits(int nBits) 
{ 
 
	DWORD	dwRetVal = 0;										 
    DWORD	nSumBits = m_nBitsOffset + nBits;			// update the bits index 
	DWORD	dwMask   = 0xFFFFFFFF >> (32 - nBits );		// build the mask 
	DWORD*  ptoDW    = (DWORD*)m_pbyWalk; 
	DWORD	dwValue  = *ptoDW;						// extract the pointed value 
     
    if (nSumBits <= 32) 
    { 
        dwRetVal = (dwValue >> (32 - nSumBits)) & dwMask; 
        if ((m_nBitsOffset += nBits) == 32) 
        { 
            m_nBitsOffset = 0; 
			m_pbyWalk+=4; 
        } 
    } 
    else 
	{	// walk half a long and get them 
		dwRetVal = MAKELONG(HIWORD(*(ptoDW+1)),LOWORD(*(ptoDW))); 
		m_pbyWalk+=4; 
		m_nBitsOffset	= nSumBits - 32; 
		dwRetVal >>= 48 - nSumBits;  
		dwRetVal &= dwMask; 
	} 
 
	return dwRetVal; 
} 
 
 
 
int CLayerIII::HuffmanDec(sHUFDECTAB *h, int *x, int *y, int *v, 
                     int *w) 
{ 
	 
    DWORD level; 
    int point = 0; 
    int error = 1; 
    level     = 0x80000000; 
     
    if (h->val == NULL) return 2; 
     
    /* table 0 needs no bits */ 
        if ( h->treelen == 0) 
    {  *x = *y = 0; 
        return 0; 
    } 
     
    /* Lookup in Huffman table. */ 
         
    do { 
        if (h->val[point][0]==0) {   /*end of tree*/ 
               *x = h->val[point][1] >> 4; 
            *y = h->val[point][1] & 0xf; 
             
            error = 0; 
            break; 
        } 
        if (GetFastOneBit()) { 
            while (h->val[point][1] >= 250) point += h->val[point][1]; 
            point += h->val[point][1]; 
        } 
        else { 
            while (h->val[point][0] >= 250) point += h->val[point][0]; 
            point += h->val[point][0]; 
        } 
        level >>= 1; 
    } while (level  || (point < (int)ht->treelen) ); 
     
    // Check for error. 
     
    /*  if (error) { // set x and y to a medium value as a simple concealment 
        printf("Illegal Huffman code in data.\n"); 
        *x = (h->xlen-1 << 1); 
        *y = (h->ylen-1 << 1); 
    } */ 
     
    /* Process sign encodings for quadruples tables. */ 
         
    if (h->tablename[0] == '3' 
       && (h->tablename[1] == '2' || h->tablename[1] == '3')) { 
        *v = (*y>>3) & 1; 
        *w = (*y>>2) & 1; 
        *x = (*y>>1) & 1; 
        *y = *y & 1; 
         
        /* v, w, x and y are reversed in the bitstream. 
            switch them around to make test bistream work. */ 
             
        if (*v) 
           if (GetFastOneBit()) *v = -*v; 
        if (*w) 
           if (GetFastOneBit()) *w = -*w; 
        if (*x) 
           if (GetFastOneBit()) *x = -*x; 
        if (*y) 
           if (GetFastOneBit()) *y = -*y; 
        } else { 
         
        // Process sign and escape encodings for dual tables. 
         
        // x and y are reversed in the test bitstream. 
        // Reverse x and y here to make test bitstream work. 
         
        if (h->linbits) 
           if ((h->xlen-1) == (DWORD)*x) 
           *x += GetBits(h->linbits); 
        if (*x) 
           if (GetFastOneBit()) *x = -*x; 
        if (h->linbits) 
           if ((h->ylen-1) == (DWORD)*y) 
           *y += GetBits(h->linbits); 
        if (*y) 
           if (GetFastOneBit()) *y = -*y; 
    } 
     
    return error; 
} 
 
 
 
 
////////////////////////////////////////////////////////////////////////////////////// 
// the dbScale scales the calculated float pcm m_tdbSubSamples to short values 
// (raw pcm m_tdbSubSamples are in [-1.0, 1.0], if no violations occur) 
SynthesisFilter::SynthesisFilter(DWORD nChn):m_nCan(nChn),m_countIn(0),m_lastband(-1) 
{ 
 
    Reset(); 
} 
 
////////////////////////////////////////////////////////////////////////////////////// 
// 
void SynthesisFilter::Reset() 
{ 
	ZeroMemory(m_tableA,sizeof(m_tableA)); 
	ZeroMemory(m_tableB,sizeof(m_tableB)); 
	ZeroMemory(m_tdbSubSamples,sizeof(m_tdbSubSamples)); 
    m_pToTable		= m_tableA; 
    m_nWriteIndex	= 15; 
    for(int i=0;i<40;i++) 
		m_gain[i]=1.0f; 
} 
 
////////////////////////////////////////////////////////////////////////////////////// 
//	Eliminated the old kilometric asignments lists (we have fast computers now) 
// 
 
void SynthesisFilter::CompNewTable() 
{ 
// new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3 
    double	tdbNewTbl[32];          
    double	dbTemp1[16]; 
    double	dbTmp2[16]; 
	int		j = 0; 
 
    double *pDbl1 = m_tdbSubSamples; 
	while(j<16) 
	{ 
		dbTemp1[j] = pDbl1[j] + pDbl1[31-j]; 
		j++; 
	} 
    j = 0; 
	while(j<8) 
	{ 
		dbTmp2[j] = dbTemp1[j] + dbTemp1[15-j]; 
		j++; 
	} 
	while(j<16) 
	{ 
		dbTmp2[j] = (dbTemp1[j-8] - dbTemp1[23-j]) * dbCosTable[j+8]; 
		j++; 
	} 
	 
    for(j = 0 ; j< 4 ;j++) 
	{ 
		dbTemp1[j] = dbTmp2[j] + dbTmp2[7-j]; 
		dbTemp1[j+8] = dbTmp2[j+8] + dbTmp2[15-j]; 
		dbTemp1[j+4] = (dbTmp2[j] - dbTmp2[7-j]) * dbCosTable[24+j]; 
		dbTemp1[j+12] = (dbTmp2[j+8] - dbTmp2[15-j]) * dbCosTable[24+j];// cos1_16; 
	} 
     
	for(j = 0 ; j < 2 ;j++) 
	{ 
		dbTmp2[j] = dbTemp1[j] + dbTemp1[3-j]; 
		dbTmp2[4+j] = dbTemp1[4+j] + dbTemp1[7-j]; 
		dbTmp2[8+j] = dbTemp1[8+j] + dbTemp1[11-j]; 
		dbTmp2[12+j] = dbTemp1[12+j] + dbTemp1[15-j]; 
		dbTmp2[2+j] = (dbTemp1[j] - dbTemp1[3-j]) * dbCosTable[28+j];//cos1_8; 
		dbTmp2[6+j] = (dbTemp1[4+j] - dbTemp1[7-j]) * dbCosTable[28+j]; 
		dbTmp2[10+j] = (dbTemp1[8+j] - dbTemp1[11-j]) * dbCosTable[28+j]; 
		dbTmp2[14+j] = (dbTemp1[12+j] - dbTemp1[15-j]) * dbCosTable[28+j]; 
	} 
 
	for(j = 0; j < 16 ;j+=2) 
	{ 
        dbTemp1[j]   = dbTmp2[j] + dbTmp2[j+1]; 
        dbTemp1[j+1] = (dbTmp2[j] - dbTmp2[j+1]) * dbCosTable[30]; 
	} 
 
    double dbTEmp; 
    tdbNewTbl[19] = -(tdbNewTbl[4] = (tdbNewTbl[12] = dbTemp1[7]) + dbTemp1[5]) - dbTemp1[6]; 
    tdbNewTbl[27] = -dbTemp1[6] - dbTemp1[7] - dbTemp1[4]; 
    tdbNewTbl[6] = (tdbNewTbl[10] = (tdbNewTbl[14] = dbTemp1[15]) + dbTemp1[11]) + dbTemp1[13]; 
    tdbNewTbl[17] = -(tdbNewTbl[2] = dbTemp1[15] + dbTemp1[13] + dbTemp1[9]) - dbTemp1[14]; 
    tdbNewTbl[21] = (dbTEmp = -dbTemp1[14] - dbTemp1[15] - dbTemp1[10] - dbTemp1[11]) - dbTemp1[13]; 
    tdbNewTbl[29] = -dbTemp1[14] - dbTemp1[15] - dbTemp1[12] - dbTemp1[8]; 
    tdbNewTbl[25] = dbTEmp - dbTemp1[12]; 
    tdbNewTbl[31] = -dbTemp1[0]; 
    tdbNewTbl[0] = dbTemp1[1]; 
    tdbNewTbl[23] = -(tdbNewTbl[8] = dbTemp1[3]) - dbTemp1[2]; 
         
    pDbl1 = m_tdbSubSamples; 
	 
	for(j = 0 ;j < 16 ; j++) 
	{ 
		dbTemp1[j] = (pDbl1[j] - pDbl1[31-j]) * dbCosTable[j]; 
	} 
 
	for(j = 0 ;j < 8 ; j++) 
	{ 
		dbTmp2[j] = dbTemp1[j] + dbTemp1[15-j]; 
		dbTmp2[j+8] = (dbTemp1[j] - dbTemp1[15-j]) * dbCosTable[j+16]; 
	} 
 
	for(j = 0 ;j < 4 ; j++) 
	{ 
		dbTemp1[j] = dbTmp2[j] + dbTmp2[7-j]; 
		dbTemp1[8+j] = dbTmp2[8+j] + dbTmp2[15-j]; 
		dbTemp1[4+j] = (dbTmp2[j] - dbTmp2[7-j]) * dbCosTable[j+24]; 
		dbTemp1[12+j] = (dbTmp2[8+j] - dbTmp2[15-j]) * dbCosTable[j+24]; 
	} 
 
	for(j = 0 ; j < 2 ;j++) 
	{ 
		dbTmp2[j] = dbTemp1[j] + dbTemp1[3-j]; 
		dbTmp2[4+j] = dbTemp1[4+j] + dbTemp1[7-j]; 
		dbTmp2[8+j] = dbTemp1[8+j] + dbTemp1[11-j]; 
		dbTmp2[12+j] = dbTemp1[12+j] + dbTemp1[15-j]; 
		dbTmp2[2+j] = (dbTemp1[j] - dbTemp1[3-j]) * dbCosTable[28+j];//cos1_8; 
		dbTmp2[6+j] = (dbTemp1[4+j] - dbTemp1[7-j]) * dbCosTable[28+j]; 
		dbTmp2[10+j] = (dbTemp1[8+j] - dbTemp1[11-j]) * dbCosTable[28+j]; 
		dbTmp2[14+j] = (dbTemp1[12+j] - dbTemp1[15-j]) * dbCosTable[28+j]; 
	} 
 
	for(j = 0; j < 16 ;j+=2) 
	{ 
        dbTemp1[j]   = dbTmp2[j] + dbTmp2[j+1]; 
        dbTemp1[j+1] = (dbTmp2[j] - dbTmp2[j+1]) * dbCosTable[30]; 
	} 
 
	// manually doing something that a compiler should handle sucks 
	// coding like this is hard to read 
	double dbDbTmp2Val; 
	tdbNewTbl[5] = (tdbNewTbl[11] = (tdbNewTbl[13] = (tdbNewTbl[15] = dbTemp1[15]) + dbTemp1[7]) + dbTemp1[11]) 
			   + dbTemp1[5] + dbTemp1[13]; 
	tdbNewTbl[7] = (tdbNewTbl[9] = dbTemp1[15] + dbTemp1[11] + dbTemp1[3]) + dbTemp1[13]; 
	tdbNewTbl[16] = -(tdbNewTbl[1] = (dbTEmp = dbTemp1[13] + dbTemp1[15] + dbTemp1[9]) + dbTemp1[1]) - dbTemp1[14]; 
	tdbNewTbl[18] = -(tdbNewTbl[3] = dbTEmp + dbTemp1[5] + dbTemp1[7]) - dbTemp1[6] - dbTemp1[14]; 
 
	tdbNewTbl[22] = (dbTEmp = -dbTemp1[10] - dbTemp1[11] - dbTemp1[14] - dbTemp1[15]) 
				   - dbTemp1[13] - dbTemp1[2] - dbTemp1[3]; 
	tdbNewTbl[20] = dbTEmp - dbTemp1[13] - dbTemp1[5] - dbTemp1[6] - dbTemp1[7]; 
	tdbNewTbl[24] = dbTEmp - dbTemp1[12] - dbTemp1[2] - dbTemp1[3]; 
	tdbNewTbl[26] = dbTEmp - dbTemp1[12] - (dbDbTmp2Val = dbTemp1[4] + dbTemp1[6] + dbTemp1[7]); 
	tdbNewTbl[30] = (dbTEmp = -dbTemp1[8] - dbTemp1[12] - dbTemp1[14] - dbTemp1[15]) - dbTemp1[0]; 
	tdbNewTbl[28] = dbTEmp - dbDbTmp2Val; 
     
	// insert V[0-15] (== tdbNewTbl[0-15]) into actual v: 
	double *pDblA = tdbNewTbl; 
	double *pDblB = m_pToTable + m_nWriteIndex; 
	for(j=0;j<16;j++) 
		pDblB[j*16] = pDblA[j]; 
	pDblB[256] = 0.0f; 
 
	for(j=1;j<16;j++) 
	{ 
		pDblB[256+(16*j)] = -pDblA[16-j]; 
	} 
	pDblB = (m_pToTable == m_tableA ? m_tableB : m_tableA) +  
			m_nWriteIndex; 
	pDblB[0] = -pDblA[0]; 
 
	for(j=1;j < 17;j++) 
		pDblB[j*16] = pDblA[j+15]; 
	// insert V[49-63] (== tdbNewTbl[30-16]) into other v: 
	for(j=1;j<16;j++) 
	{ 
		pDblB[256+(16*j)] = pDblA[31-j]; 
	} 
 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::GoBackBits(int nBits) 
{ 
    m_PlayedBits -= nBits; 
    m_restBits   += nBits; 
    while(m_restBits >= 8)  
	{ 
        m_restBits -= 8; 
        m_playedOctets--; 
    } 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
void CLayerIII::GoBackOctets(int nOctets) 
{ 
	m_PlayedBits		 -= (nOctets*8); 
    m_playedOctets		 -= nOctets; 
} 
 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
// 
DWORD CLayerIII::GetBits(DWORD nBits) 
{ 
 
	m_PlayedBits += nBits; 
   	DWORD	dwRetVal = 0; 
	int		contor = nBits; 
	while (contor > 0)  
	{ 
		if (m_restBits == 0)  
		{ 
			m_restBits = 8; 
			m_playedOctets++; 
		} 
		int minBidx = min((int)m_restBits,contor); 
		DWORD xmask = 0xFFFFFFFF >> (32 - m_restBits); 
		int tempVal = m_pDwBuff[m_playedOctets & 0xfff]; 
		tempVal&= xmask;		 
		m_restBits -= minBidx; 
		tempVal = tempVal >> m_restBits; 
		contor -= minBidx; 
		dwRetVal |= tempVal << contor; 
	} 
	return dwRetVal; 
}