513 lines
12 KiB
C++
513 lines
12 KiB
C++
/* $Header: /cvs/root/winamp/vlb/longblock.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: longblock.cpp
|
|
* project : MPEG-2 AAC Decoder
|
|
* contents/description: long window sequence object
|
|
*
|
|
* $Header: /cvs/root/winamp/vlb/longblock.cpp,v 1.2 2011/06/13 02:06:03 audiodsp Exp $
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#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
|
|
|
|
CLongBlock::CLongBlock (CChannelInfo &info)
|
|
: CBlock (info)
|
|
{
|
|
m_SectBits = 5 ;
|
|
}
|
|
|
|
CLongBlock::~CLongBlock ()
|
|
{
|
|
}
|
|
|
|
// low-level access
|
|
|
|
float *CLongBlock::AccessSpectralData (int /* window = 0 */)
|
|
{
|
|
return m_SpectralCoefficient ;
|
|
}
|
|
|
|
int *CLongBlock::AccessCodeBooks (int /* group */)
|
|
{
|
|
return m_CodeBook ;
|
|
}
|
|
|
|
int *CLongBlock::AccessScaleFactors (int /* group */)
|
|
{
|
|
return m_ScaleFactor ;
|
|
}
|
|
|
|
// readers
|
|
#include<stdio.h>
|
|
#include<conio.h>
|
|
#include<stdlib.h>
|
|
void CLongBlock::ReadSectionData (CDolbyBitStream &bs)
|
|
{
|
|
CVLBBitSequence sect_cb (4) ;
|
|
CVLBBitSequence sect_len_incr (m_SectBits) ;
|
|
|
|
int sect_esc_val = (1 << m_SectBits) - 1 ;
|
|
|
|
int band ; // msdev not ansi
|
|
|
|
//Section Information:
|
|
int iNumberOfSections;
|
|
iNumberOfSections=0;
|
|
sSectionInfoStruct.aiSectionCount[0]=0;
|
|
sSectionInfoStruct.aaiSectionStart[0][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 [band] = sect_cb ;
|
|
|
|
if ((m_CodeBook [band] == BOOKSCL) ||
|
|
(m_CodeBook [band] == RESERVED_HCB)
|
|
)
|
|
{
|
|
throw EInvalidCodeBook () ;
|
|
}
|
|
}
|
|
|
|
sSectionInfoStruct.aaiSectionCodebooks[0][iNumberOfSections]=sect_cb;
|
|
sSectionInfoStruct.aaiSectionStart[0][iNumberOfSections+1]=band;
|
|
sSectionInfoStruct.aaiSectionEnd[0][iNumberOfSections]=band;
|
|
sSectionInfoStruct.aiSectionCount[0]++;
|
|
iNumberOfSections++;
|
|
}
|
|
if(band < m_IcsInfo.GetScaleFactorBandsTotal() && m_IcsInfo.GetScaleFactorBandsTransmitted()){
|
|
sSectionInfoStruct.aaiSectionCodebooks[0][iNumberOfSections]=ZERO_HCB;
|
|
sSectionInfoStruct.aaiSectionEnd[0][iNumberOfSections]= m_IcsInfo.GetScaleFactorBandsTotal ();
|
|
sSectionInfoStruct.aiSectionCount[0]++;
|
|
iNumberOfSections++;
|
|
}
|
|
for ( ; band < m_IcsInfo.GetScaleFactorBandsTotal () ; band++)
|
|
{
|
|
m_CodeBook [band] = ZERO_HCB ;
|
|
}
|
|
}
|
|
|
|
void CLongBlock::ReadScaleFactorData (CDolbyBitStream &bs, const int global_gain)
|
|
{
|
|
const CodeBookDescription *hcb = &HuffmanCodeBooks [BOOKSCL] ;
|
|
|
|
int factor = global_gain ;
|
|
int position = 0 ;
|
|
|
|
int temp ;
|
|
|
|
for (int band = 0 ; band < m_IcsInfo.GetScaleFactorBandsTransmitted () ; band++)
|
|
{
|
|
switch (m_CodeBook [band])
|
|
{
|
|
case ZERO_HCB : // zero book
|
|
|
|
m_ScaleFactor [band] = 0 ;
|
|
break ;
|
|
|
|
default : // regular scale factor
|
|
|
|
temp = DecodeHuffmanWord (bs, hcb->CodeBook) ;
|
|
factor += temp - 60 ; // MIDFAC 1.5 dB
|
|
|
|
m_ScaleFactor [band] = factor - 100 ;
|
|
break ;
|
|
|
|
case INTENSITY_HCB : // intensity steering
|
|
case INTENSITY_HCB2 :
|
|
|
|
temp = DecodeHuffmanWord (bs, hcb->CodeBook) ;
|
|
position += temp - 60 ;
|
|
|
|
m_ScaleFactor [band] = position - 100 ;
|
|
|
|
#ifdef MAIN_PROFILE
|
|
// use of intensity stereo overrides prediction_used mask
|
|
m_IcsInfo.DeactivatePrediction (band) ;
|
|
#endif
|
|
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CLongBlock::ReadSpectralData (CDolbyBitStream &bs)
|
|
{
|
|
int QuantizedCoef [MaximumBins] ;
|
|
|
|
int index, band ; // msdev for scoping not ansi
|
|
|
|
for (index = 0 ; index < MaximumBins ; index++)
|
|
{
|
|
QuantizedCoef [index] = 0 ;
|
|
}
|
|
|
|
const int *BandOffsets = m_IcsInfo.GetScaleFactorBandOffsets () ;
|
|
|
|
for (band = 0 ; band < m_IcsInfo.GetScaleFactorBandsTransmitted () ; band++)
|
|
{
|
|
if ((m_CodeBook [band] == ZERO_HCB) ||
|
|
(m_CodeBook [band] == INTENSITY_HCB) ||
|
|
(m_CodeBook [band] == INTENSITY_HCB2)
|
|
)
|
|
continue ;
|
|
|
|
const CodeBookDescription *hcb = &HuffmanCodeBooks [m_CodeBook [band]] ;
|
|
|
|
int step = 0 ;
|
|
|
|
for (index = BandOffsets [band] ; index < BandOffsets [band + 1] ; index += step)
|
|
{
|
|
step = UnpackIndex (DecodeHuffmanWord (bs, hcb->CodeBook), &QuantizedCoef [index], hcb) ;
|
|
|
|
if (!hcb->IsSigned)
|
|
{
|
|
for (int i = 0 ; i < step ; i++)
|
|
{
|
|
if (QuantizedCoef [index + i])
|
|
{
|
|
if (bs.Get (1)) // sign bit
|
|
{
|
|
QuantizedCoef [index + i] = -QuantizedCoef [index + i] ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_CodeBook [band] == ESCBOOK)
|
|
{
|
|
QuantizedCoef [index] = GetEscape (bs, QuantizedCoef [index]) ;
|
|
QuantizedCoef [index + 1] = GetEscape (bs, QuantizedCoef [index + 1]) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_PulseData.Apply (m_IcsInfo, QuantizedCoef) ;
|
|
|
|
// dequantize and apply scalefactors
|
|
|
|
for (index = 0, band = 0 ; band < m_IcsInfo.GetScaleFactorBandsTransmitted () ; band++)
|
|
{
|
|
float factor = static_cast<float>(m_ScaleFactor [band]) ;
|
|
|
|
if ((factor >= 0) && (factor < ExpTableSize))
|
|
{
|
|
factor = m_ExpTable [m_ScaleFactor [band]] ;
|
|
}
|
|
else
|
|
{
|
|
if (m_ScaleFactor [band] == -100)
|
|
{
|
|
for (index = BandOffsets [band] ; index < BandOffsets [band + 1] ; index++)
|
|
{
|
|
m_SpectralCoefficient [index] = 0.0F ;
|
|
}
|
|
|
|
continue ;
|
|
}
|
|
|
|
factor = static_cast<float>(pow (2.0F, 0.25F * factor)) ;
|
|
}
|
|
|
|
for (index = BandOffsets [band] ; index < BandOffsets [band + 1] ; index++)
|
|
{
|
|
m_SpectralCoefficient [index] = InverseQuantize (QuantizedCoef [index]) * factor ;
|
|
}
|
|
}
|
|
|
|
// zero out spectral data beyond max_sfb
|
|
// index is now first bin of max_sfb+1
|
|
|
|
for ( ; index < MaximumBins ; index++)
|
|
{
|
|
m_SpectralCoefficient [index] = 0.0F ;
|
|
}
|
|
}
|
|
|
|
void CLongBlock::ApplyWindowFunction (COverlapAddBuffer &Previous)
|
|
{
|
|
int i ;
|
|
|
|
switch (m_IcsInfo.GetWindowSequence ())
|
|
{
|
|
case CChannelInfo::OnlyLongSequence :
|
|
|
|
#if defined (WIN32) && defined (_M_IX86)
|
|
|
|
PentiumWindow (m_SpectralCoefficient, m_LongWindow [Previous.GetWindowShape ()], m_LongWindow [m_IcsInfo.GetWindowShape ()]) ;
|
|
|
|
#else
|
|
|
|
for (i = 0 ; i < 1024 ; i++)
|
|
{
|
|
m_SpectralCoefficient [i] *= m_LongWindow [Previous.GetWindowShape ()][i] ;
|
|
m_SpectralCoefficient [1024 + i] *= m_LongWindow [m_IcsInfo.GetWindowShape ()][1023 - i] ;
|
|
}
|
|
|
|
#endif
|
|
|
|
break ;
|
|
|
|
case CChannelInfo::LongStartSequence :
|
|
|
|
for (i = 0 ; i < 1024 ; i++)
|
|
{
|
|
m_SpectralCoefficient [i] *= m_LongWindow [Previous.GetWindowShape ()][i] ;
|
|
}
|
|
|
|
for (i = 0 ; i < 128 ; i++)
|
|
{
|
|
m_SpectralCoefficient [1472 + i] *= m_ShortWindow [m_IcsInfo.GetWindowShape ()][127 - i] ;
|
|
}
|
|
|
|
for (i = 1600 ; i < 2048 ; i++)
|
|
{
|
|
m_SpectralCoefficient [i] = 0.0F ;
|
|
}
|
|
|
|
break ;
|
|
|
|
case CChannelInfo::LongStopSequence :
|
|
|
|
for (i = 0 ; i < 448 ; i++)
|
|
{
|
|
m_SpectralCoefficient [i] = 0.0F ;
|
|
}
|
|
|
|
for (i = 0 ; i < 128 ; i++)
|
|
{
|
|
m_SpectralCoefficient [448 + i] *= m_ShortWindow [Previous.GetWindowShape ()][i] ;
|
|
}
|
|
|
|
for (i = 0 ; i < 1024 ; i++)
|
|
{
|
|
m_SpectralCoefficient [1024 + i] *= m_LongWindow [m_IcsInfo.GetWindowShape ()][1023 - i] ;
|
|
}
|
|
|
|
break ;
|
|
}
|
|
|
|
Previous.SetWindowShape (m_IcsInfo.GetWindowShape ()) ;
|
|
}
|
|
|
|
void CLongBlock::FrequencyToTime_Fast (COverlapAddBuffer &Previous)
|
|
{
|
|
InverseTransform (m_SpectralCoefficient) ;
|
|
ApplyWindowFunction (Previous) ;
|
|
|
|
#if defined (WIN32) && defined (_M_IX86)
|
|
|
|
PentiumOverlap (m_Output, m_SpectralCoefficient, Previous.AccessBuffer (), 1) ;
|
|
|
|
#else
|
|
|
|
for (int i = 0 ; i < 1024 ; i++)
|
|
{
|
|
// add first half and old data
|
|
|
|
m_Output[i] = m_SpectralCoefficient [i] + Previous [i] ;
|
|
|
|
// store second half as old data
|
|
|
|
Previous [i] = m_SpectralCoefficient [1024 + i] ;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
void CLongBlock::FrequencyToTime (COverlapAddBuffer &Previous, float Output [], const int stride)
|
|
{
|
|
InverseTransform (m_SpectralCoefficient) ;
|
|
ApplyWindowFunction (Previous) ;
|
|
|
|
for (int i = 0 ; i < 1024 ; i++)
|
|
{
|
|
// add first half and old data
|
|
|
|
Output [i * stride] = m_SpectralCoefficient [i] + Previous [i] ;
|
|
|
|
// store second half as old data
|
|
|
|
Previous [i] = m_SpectralCoefficient [1024 + i] ;
|
|
}
|
|
}
|
|
|
|
void CLongBlock::FrequencyToTime (COverlapAddBuffer &Previous)
|
|
{
|
|
InverseTransform (m_SpectralCoefficient) ;
|
|
ApplyWindowFunction (Previous) ;
|
|
|
|
for (int i = 0 ; i < 1024 ; i++)
|
|
{
|
|
m_Output[i]=m_SpectralCoefficient [i] + Previous [i] ;
|
|
Previous [i] = m_SpectralCoefficient [1024 + i] ;
|
|
}
|
|
}
|
|
|
|
void CLongBlock::ApplyEqualizationMask (float Mask [])
|
|
{
|
|
for (int i = 0 ; i < EqualizationMaskLength ; i++)
|
|
{
|
|
for (int j = 0 ; j < (MaximumBins / EqualizationMaskLength) ; j++)
|
|
{
|
|
m_SpectralCoefficient [(MaximumBins / EqualizationMaskLength) * i + j] *= Mask [i] ;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined (WIN32) && defined (_M_IX86)
|
|
#pragma message (__FILE__": using x86 inline assembler")
|
|
|
|
// this CBlock method goes here, because we'd prefer it to be inlined
|
|
// with CLongBlock. not all compilers support inter-module optimizations.
|
|
|
|
void CBlock::PentiumOverlap (float output [], float spec [], float prev [], unsigned int stride)
|
|
{
|
|
const float minval = -32767.0F ;
|
|
|
|
__asm
|
|
{
|
|
shl stride, 2 // stride *= sizeof(float)
|
|
|
|
mov esi, dword ptr [output] // esi is pcm output pointer
|
|
|
|
mov ebx, 0x00 // ebx is buffer index
|
|
|
|
mov edx, dword ptr [spec]
|
|
mov ecx, dword ptr [prev]
|
|
|
|
entry:
|
|
|
|
fld dword ptr [edx + ebx*4] // get: spec [i]
|
|
fadd dword ptr [ecx + ebx*4] // get: spec [i] + prev [i]
|
|
mov eax, dword ptr [edx + ebx*4 + 0x1000] // get: spec [1024 + i]
|
|
mov dword ptr [ecx + ebx*4],eax // put: prev [i] = spec [1024 + i]
|
|
fst dword ptr [esi] // put: output [i] = spec [i] + prev [i]
|
|
|
|
add esi, stride
|
|
|
|
fstp st(0)
|
|
|
|
inc ebx
|
|
cmp ebx, 1024
|
|
jne entry
|
|
|
|
}
|
|
}
|
|
|
|
void CLongBlock::PentiumWindow (float spec [], const float prev [], const float curr [])
|
|
{
|
|
__asm
|
|
{
|
|
mov ebx, 0x0100
|
|
|
|
mov edx, dword ptr [spec]
|
|
mov esi, dword ptr [curr]
|
|
mov ecx, dword ptr [prev]
|
|
|
|
add esi, 4 * 0x03FC
|
|
|
|
entry:
|
|
|
|
// previous shape
|
|
|
|
fldz
|
|
|
|
fld dword ptr [edx]
|
|
fmul dword ptr [ecx]
|
|
fxch
|
|
|
|
fld dword ptr [edx + 0x04]
|
|
fmul dword ptr [ecx + 0x04]
|
|
fxch
|
|
|
|
fld dword ptr [edx + 0x08]
|
|
fmul dword ptr [ecx + 0x08]
|
|
fxch
|
|
|
|
fld dword ptr [edx + 0x0C]
|
|
fmul dword ptr [ecx + 0x0C]
|
|
fxch st(4)
|
|
|
|
fstp dword ptr [edx]
|
|
fxch st(2)
|
|
|
|
fstp dword ptr [edx + 0x04]
|
|
fstp dword ptr [edx + 0x08]
|
|
fxch
|
|
|
|
fstp dword ptr [edx + 0x0C]
|
|
|
|
// current shape
|
|
|
|
fld dword ptr [edx + 0x1000]
|
|
fmul dword ptr [esi + 0x0C]
|
|
fxch
|
|
|
|
fld dword ptr [edx + 0x1004]
|
|
fmul dword ptr [esi + 0x08]
|
|
fxch
|
|
|
|
fld dword ptr [edx + 0x1008]
|
|
fmul dword ptr [esi + 0x04]
|
|
fxch
|
|
|
|
fld dword ptr [edx + 0x100C]
|
|
fmul dword ptr [esi]
|
|
|
|
fxch st(4)
|
|
fstp dword ptr [edx + 0x1000]
|
|
|
|
fxch st(2)
|
|
fstp dword ptr [edx + 0x1004]
|
|
|
|
fstp dword ptr [edx + 0x1008]
|
|
|
|
fstp st(0)
|
|
fstp dword ptr [edx + 0x100C]
|
|
|
|
add edx, 0x10
|
|
sub esi, 0x10
|
|
add ecx, 0x10
|
|
|
|
dec ebx
|
|
jne entry
|
|
}
|
|
}
|
|
|
|
#endif
|