winamp/Src/vlb/shortblock.cpp

421 lines
11 KiB
C++

/* $Header: /cvs/root/winamp/vlb/shortblock.cpp,v 1.2 2011/06/13 02:06:03 audiodsp Exp $ */
/***************************************************************************\
*
* Copyright 2000-2002 Dolby Laboratories, Inc. All Rights
* Reserved. Do not copy. Do not distribute.
* Confidential information.
*
* (C) copyright Fraunhofer - IIS (1998)
* All Rights Reserved
*
* filename: shortblock.cpp
* project : MPEG-2 AAC Decoder
* contents/description: eight short window sequence object
*
\***************************************************************************/
#include <math.h> // pow()
#include "block.h"
#include "bitstream.h"
#include "channelinfo.h"
#include "overlapadd.h"
#ifdef MAIN_PROFILE
#include "prediction.h"
#endif
// ctor/dtor
CShortBlock::CShortBlock (CChannelInfo &info)
: CBlock (info)
{
m_SectBits = 3 ;
}
CShortBlock::~CShortBlock ()
{
}
// low-level access
float *CShortBlock::AccessSpectralData (int window)
{
return m_SpectralCoefficient [window] ;
}
int *CShortBlock::AccessCodeBooks (int group)
{
return m_CodeBook [group] ;
}
int *CShortBlock::AccessScaleFactors (int group)
{
return m_ScaleFactor [group] ;
}
// readers
void CShortBlock::ReadSectionData (CDolbyBitStream &bs)
{
CVLBBitSequence sect_cb (4) ;
CVLBBitSequence sect_len_incr (m_SectBits) ;
int sect_esc_val = (1 << m_SectBits) - 1 ;
//Section Information:
int iNumberOfSections;
for (int group = 0 ; group < m_IcsInfo.GetWindowGroups () ; group++)
{
int band ; // msdev not ansi
// initialize first group's section info
iNumberOfSections=0;
sSectionInfoStruct.aiSectionCount[group]=0;
sSectionInfoStruct.aaiSectionStart[group][0]=0;
for (band = 0 ; band < m_IcsInfo.GetScaleFactorBandsTransmitted () ; )
{
sect_cb.Read (bs) ;
sect_len_incr.Read (bs) ;
int sect_len = 0 ;
while (sect_len_incr == sect_esc_val)
{
sect_len += sect_esc_val ;
sect_len_incr.Read (bs) ;
}
sect_len += sect_len_incr ;
for (int top = band + sect_len ; band < top ; band++)
{
m_CodeBook [group][band] = sect_cb ;
if ((m_CodeBook [group][band] == BOOKSCL) ||
(m_CodeBook [group][band] == RESERVED_HCB)
)
{
throw EInvalidCodeBook () ;
}
}
sSectionInfoStruct.aaiSectionCodebooks[group][iNumberOfSections]=sect_cb;
sSectionInfoStruct.aaiSectionStart[group][iNumberOfSections+1]=band;
sSectionInfoStruct.aaiSectionEnd[group][iNumberOfSections]=band;
sSectionInfoStruct.aiSectionCount[group]++;
iNumberOfSections++;
} // for band
if(band < m_IcsInfo.GetScaleFactorBandsTotal() && m_IcsInfo.GetScaleFactorBandsTransmitted()){
sSectionInfoStruct.aaiSectionCodebooks[group][iNumberOfSections]=ZERO_HCB;
sSectionInfoStruct.aaiSectionEnd[group][iNumberOfSections]= m_IcsInfo.GetScaleFactorBandsTotal ();
sSectionInfoStruct.aiSectionCount[group]++;
iNumberOfSections++;
}
for ( ; band < m_IcsInfo.GetScaleFactorBandsTotal () ; band++)
{
m_CodeBook [group][band] = ZERO_HCB ;
}
} // for group..
}
void CShortBlock::ReadScaleFactorData (CDolbyBitStream &bs, const int global_gain)
{
const CodeBookDescription *hcb = &HuffmanCodeBooks [BOOKSCL] ;
int factor = global_gain ;
int position = 0 ;
int temp ;
for (int group = 0 ; group < m_IcsInfo.GetWindowGroups () ; group++)
{
for (int band = 0 ; band < m_IcsInfo.GetScaleFactorBandsTransmitted () ; band++)
{
switch (m_CodeBook [group][band])
{
case ZERO_HCB : // zero book
m_ScaleFactor [group][band] = 0 ;
break ;
default : // decode scale factor
temp = DecodeHuffmanWord (bs, hcb->CodeBook) ;
factor += temp - 60 ; // MIDFAC 1.5 dB
m_ScaleFactor [group][band] = factor - 100 ;
break ;
case INTENSITY_HCB : // intensity steering
case INTENSITY_HCB2 :
temp = DecodeHuffmanWord (bs, hcb->CodeBook) ;
position += temp - 60 ;
m_ScaleFactor [group][band] = position - 100 ;
break ;
}
}
}
}
void CShortBlock::ReadSpectralData (CDolbyBitStream &bs)
{
const int *BandOffsets = m_IcsInfo.GetScaleFactorBandOffsets () ;
int QuantizedCoef [MaximumWindows][MaximumBins] ;
int window, group ;
// // // clear coeffs
for (window = 0 ; window < MaximumWindows ; window++)
{
for (int index = 0 ; index < MaximumBins ; index++)
{
QuantizedCoef [window][index] = 0 ;
}
}
// // // read interleaved coeffs
int groupoffset = 0 ;
for (group = 0 ; group < m_IcsInfo.GetWindowGroups () ; group++)
{
for (int band = 0 ; band < m_IcsInfo.GetScaleFactorBandsTransmitted () ; band++)
{
const CodeBookDescription *hcb = &HuffmanCodeBooks [m_CodeBook [group][band]] ;
for (int groupwin = 0 ; groupwin < m_IcsInfo.GetWindowGroupLength (group) ; groupwin++)
{
if ((m_CodeBook [group][band] == ZERO_HCB) ||
(m_CodeBook [group][band] == INTENSITY_HCB) ||
(m_CodeBook [group][band] == INTENSITY_HCB2)
)
continue ;
int window = groupoffset + groupwin ;
int step = 0 ;
for (int index = BandOffsets [band] ; index < BandOffsets [band + 1] ; index += step)
{
step = UnpackIndex (DecodeHuffmanWord (bs, hcb->CodeBook), &QuantizedCoef [window][index], hcb) ;
if (!hcb->IsSigned)
{
for (int i = 0 ; i < step ; i++)
{
if (QuantizedCoef [window][index + i])
{
if (bs.Get (1)) // sign bit
{
QuantizedCoef [window][index + i] = -QuantizedCoef [window][index + i] ;
}
}
}
}
if (m_CodeBook [group][band] == ESCBOOK)
{
QuantizedCoef [window][index] = GetEscape (bs, QuantizedCoef [window][index]) ;
QuantizedCoef [window][index + 1] = GetEscape (bs, QuantizedCoef [window][index + 1]) ;
}
}
}
}
groupoffset += m_IcsInfo.GetWindowGroupLength (group) ;
}
// // //
for (window = 0, group = 0 ; group < m_IcsInfo.GetWindowGroups () ; group++)
{
for (int groupwin = 0 ; groupwin < m_IcsInfo.GetWindowGroupLength (group) ; groupwin++, window++)
{
// dequantize
for (int index = 0 ; index < MaximumBins ; index++)
{
m_SpectralCoefficient [window][index] = InverseQuantize (QuantizedCoef [window][index]) ;
}
// apply scalefactors
for (int band = 0 ; band < m_IcsInfo.GetScaleFactorBandsTransmitted () ; band++)
{
float factor = static_cast<float>(m_ScaleFactor [group][band]) ;
if ((factor >= 0) && (factor < ExpTableSize))
{
factor = m_ExpTable [m_ScaleFactor [group][band]] ;
}
else
{
factor = static_cast<float>(pow (2.0F, 0.25F * factor)) ;
}
if (m_ScaleFactor [group][band] != -100)
{
for (int index = BandOffsets [band] ; index < BandOffsets [band + 1] ; index++)
{
m_SpectralCoefficient [window][index] *= factor ;
}
}
else
{
for (int index = BandOffsets [band] ; index < BandOffsets [band + 1] ; index++)
{
m_SpectralCoefficient [window][index] = 0.0F ;
}
}
}
}
}
}
void CShortBlock::TransformWindows (COverlapAddBuffer &Previous, float EightWindowsBuffer [])
{
for (int i = 0 ; i < 2048 ; i++)
{
EightWindowsBuffer [i] = 0 ;
}
for (int window = 0 ; window < MaximumWindows ; window++)
{
float *theSpectrum = m_SpectralCoefficient [window] ;
InverseTransform (theSpectrum) ;
if (window == 0)
{
for (int i = 0 ; i < 128 ; i++)
{
theSpectrum [i] *= m_ShortWindow [Previous.GetWindowShape ()][i] ;
theSpectrum [128 + i] *= m_ShortWindow [m_IcsInfo.GetWindowShape ()][127 - i] ;
}
}
else
{
for (int i = 0 ; i < 128 ; i++)
{
theSpectrum [i] *= m_ShortWindow [m_IcsInfo.GetWindowShape ()][i] ;
theSpectrum [128 + i] *= m_ShortWindow [m_IcsInfo.GetWindowShape ()][127 - i] ;
}
}
// overlap add the 8 windows in this block
for (int i = 0 ; i < 256 ; i++)
{
EightWindowsBuffer [448 + 128 * window + i] += theSpectrum [i] ;
}
}
Previous.SetWindowShape (m_IcsInfo.GetWindowShape ()) ;
}
/*
void CShortBlock::FrequencyToTime (COverlapAddBuffer &Previous, short Output [], const int stride)
{
float EightWindowsBuffer [2048] ;
TransformWindows (Previous, EightWindowsBuffer) ;
#if defined (WIN32) && defined (_M_IX86)
PentiumOverlap (m_Output, EightWindowsBuffer, Previous.AccessBuffer (), stride) ;
#else
for (int j = 0 ; j < 1024 ; j++)
{
// add first half and old data
Output [j * stride] = FloatToShort (EightWindowsBuffer [j] + Previous [j]) ;
// store second half as old data
Previous [j] = EightWindowsBuffer [1024 + j] ;
}
#endif
}
*/
void CShortBlock::FrequencyToTime_Fast (COverlapAddBuffer &Previous)
{
float EightWindowsBuffer [2048] ;
TransformWindows (Previous, EightWindowsBuffer) ;
#if defined (WIN32) && defined (_M_IX86)
PentiumOverlap (m_Output, EightWindowsBuffer, Previous.AccessBuffer (), 1) ;
#else
for (int j = 0 ; j < 1024 ; j++)
{
// add first half and old data
m_Output [j] = EightWindowsBuffer [j] + Previous [j];
// store second half as old data
Previous [j] = EightWindowsBuffer [1024 + j] ;
}
#endif
}
void CShortBlock::FrequencyToTime (COverlapAddBuffer &Previous, float Output [], const int stride)
{
float EightWindowsBuffer [2048] ;
TransformWindows (Previous, EightWindowsBuffer) ;
for (int j = 0 ; j < 1024 ; j++)
{
// add first half and old data
Output [j * stride] = EightWindowsBuffer [j] + Previous [j] ;
// store second half as old data
Previous [j] = EightWindowsBuffer [1024 + j] ;
}
}
void CShortBlock::FrequencyToTime (COverlapAddBuffer &Previous)
{
float EightWindowsBuffer [2048] ;
TransformWindows (Previous, EightWindowsBuffer) ;
for (int j = 0 ; j < 1024 ; j++)
{
m_Output [j] = EightWindowsBuffer [j] + Previous [j] ;
Previous [j] = EightWindowsBuffer [1024 + j] ;
}
}
void CShortBlock::ApplyEqualizationMask (float Mask [])
{
for (int window = 0 ; window < MaximumWindows ; window++)
{
for (int i = 0 ; i < EqualizationMaskLength ; i++)
{
for (int j = 0 ; j < (MaximumBins / EqualizationMaskLength) ; j++)
{
m_SpectralCoefficient [window][(MaximumBins / EqualizationMaskLength) * i + j] *= Mask [i] ;
}
}
}
}