Merge branch 'sle118:master-v4.3' into led_visu-v4.3

This commit is contained in:
wizmo2
2023-07-29 09:08:23 +01:00
committed by GitHub
519 changed files with 77823 additions and 37319 deletions

View File

@@ -5,7 +5,7 @@ project(bell)
# Configurable options
option(BELL_DISABLE_CODECS "Disable the entire audio codec wrapper" OFF)
option(BELL_CODEC_AAC "Support libhelix-aac codec" ON)
option(BELL_CODEC_AAC "Support opencore-aac codec" ON)
option(BELL_CODEC_MP3 "Support libhelix-mp3 codec" ON)
option(BELL_DISABLE_MQTT "Disable the built-in MQTT wrapper" OFF)
option(BELL_DISABLE_WEBSERVER "Disable the built-in Web server" OFF)
@@ -136,7 +136,11 @@ endfunction()
if(ESP_PLATFORM)
list(APPEND EXTRA_LIBS idf::mdns idf::mbedtls idf::pthread idf::driver idf::lwip)
if (IDF_VERSION_MAJOR LESS_EQUAL 4)
list(APPEND EXTRA_LIBS idf::mdns idf::mbedtls idf::pthread idf::driver idf::lwip)
else()
list(APPEND EXTRA_LIBS idf::espressif__mdns idf::mbedtls idf::pthread idf::driver idf::lwip)
endif()
add_definitions(-Wunused-const-variable -Wchar-subscripts -Wunused-label -Wmaybe-uninitialized -Wmisleading-indentation -Wno-stringop-overflow -Wno-error=format -Wno-format -Wno-stringop-overread -Wno-stringop-overflow)
else()
find_package(Threads REQUIRED)
@@ -170,9 +174,8 @@ if(NOT BELL_DISABLE_CODECS)
# AAC-LC codec
if(BELL_CODEC_AAC)
file(GLOB LIBHELIX_AAC_SOURCES "external/libhelix-aac/*.c")
list(APPEND LIBHELIX_SOURCES ${LIBHELIX_AAC_SOURCES})
list(APPEND EXTERNAL_INCLUDES "external/libhelix-aac")
add_subdirectory(external/opencore-aacdec)
list(APPEND EXTRA_LIBS opencore-aacdec)
list(APPEND SOURCES "${AUDIO_CODEC_DIR}/AACDecoder.cpp")
list(APPEND CODEC_FLAGS "-DBELL_CODEC_AAC")
endif()
@@ -303,6 +306,7 @@ if(NOT BELL_DISABLE_WEBSERVER)
list(APPEND EXTRA_INCLUDES "external/civetweb/include")
else()
list(REMOVE_ITEM SOURCES "${IO_DIR}/BellHTTPServer.cpp")
list(REMOVE_ITEM SOURCES "${IO_DIR}/MGStreamAdapter.cpp")
endif()
add_library(bell STATIC ${SOURCES})
@@ -345,3 +349,4 @@ endif()
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "SunOS")
target_compile_definitions(bell PUBLIC PB_NO_STATIC_ASSERT)
endif()

View File

@@ -1,14 +1,22 @@
#include <memory.h>
#include <atomic>
#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <type_traits>
#include <vector>
#include "AudioCodecs.h"
#include "AudioContainers.h"
#include "BellHTTPServer.h"
#include "BellTask.h"
#include "CentralAudioBuffer.h"
#include "Compressor.h"
#include "DecoderGlobals.h"
#include "EncodedAudioStream.h"
#include "HTTPClient.h"
#include "PortAudioSink.h"
#include "StreamInfo.h"
#define DEBUG_LEVEL 4
#include <BellDSP.h>
#include <BellLogger.h>
@@ -33,8 +41,8 @@ class AudioPlayer : bell::Task {
auto chunk = audioBuffer->readChunk();
if (chunk != nullptr && chunk->pcmSize > 0) {
this->dsp->process(chunk->pcmData, chunk->pcmSize, 2, 44100,
bell::BitWidth::BW_16);
// this->dsp->process(chunk->pcmData, chunk->pcmSize, 2, 44100,
// bell::BitWidth::BW_16);
this->audioSink->feedPCMFrames(chunk->pcmData, chunk->pcmSize);
}
@@ -45,9 +53,51 @@ class AudioPlayer : bell::Task {
int main() {
bell::setDefaultLogger();
bell::createDecoders();
size_t size = sizeof(void*);
audioBuffer = std::make_shared<bell::CentralAudioBuffer>(512);
auto task = AudioPlayer();
auto url = "http://193.222.135.71/378";
// std::ifstream file("aactest.aac", std::ios::binary);
BELL_LOG(info, "cock", "Published?");
auto req = bell::HTTPClient::get(url);
auto container = AudioContainers::guessAudioContainer(req->stream());
auto codec = AudioCodecs::getCodec(container.get());
uint32_t dataLen;
while (true) {
uint8_t* data = codec->decode(container.get(), dataLen);
if (!data) {
std::cout << "data invalid" << std::endl;
continue;
}
size_t toWrite = dataLen;
while (toWrite > 0) {
toWrite -= audioBuffer->writePCM(data + dataLen - toWrite, toWrite, 0);
}
// std::cout << dataLen << std::endl;
}
// return 0;
// std::vector<uint8_t> frameData(1024 * 10);
// /*
// while (true) {
// size_t bytes =audioStream->decodeFrame(frameData.data());
// std::cout << bytes <<std::endl;
// size_t toWrite = bytes;
// if (!isPaused) {
// while (toWrite > 0) {
// toWrite -= audioBuffer->writePCM(frameData.data() + bytes - toWrite,
// toWrite, 0);
// }
// }
// }*/
return 0;
}
}

View File

@@ -1,213 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aaccommon.h,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* aaccommon.h - implementation-independent API's, datatypes, and definitions
**************************************************************************************/
#ifndef _AACCOMMON_H
#define _AACCOMMON_H
#ifdef ESP8266
# include "pgmspace.h"
#elif defined(ESP_PLATFORM) && __has_include(<pgm_space.h>)
# include <pgm_space.h>
#else
# define PROGMEM
# define pgm_read_byte(addr) (*(const unsigned char *)(addr))
# define pgm_read_word(addr) (*(const unsigned short *)(addr))
#endif
// Can't fit in ESP8266 RAM
#ifndef ESP8266
#define AAC_ENABLE_SBR 1
#endif
#pragma GCC optimize ("O3")
#include "aacdec.h"
#include "statname.h"
/* 12-bit syncword */
#define SYNCWORDH 0xff
#define SYNCWORDL 0xf0
#define MAX_NCHANS_ELEM 2 /* max number of channels in any single bitstream element (SCE,CPE,CCE,LFE) */
#define ADTS_HEADER_BYTES 7
#define NUM_SAMPLE_RATES 12
#define NUM_DEF_CHAN_MAPS 8
#define NUM_ELEMENTS 8
#define MAX_NUM_PCE_ADIF 16
#define MAX_WIN_GROUPS 8
#define MAX_SFB_SHORT 15
#define MAX_SF_BANDS (MAX_SFB_SHORT*MAX_WIN_GROUPS) /* worst case = 15 sfb's * 8 windows for short block */
#define MAX_MS_MASK_BYTES ((MAX_SF_BANDS + 7) >> 3)
#define MAX_PRED_SFB 41
#define MAX_TNS_FILTERS 8
#define MAX_TNS_COEFS 60
#define MAX_TNS_ORDER 20
#define MAX_PULSES 4
#define MAX_GAIN_BANDS 3
#define MAX_GAIN_WIN 8
#define MAX_GAIN_ADJUST 7
#define NSAMPS_LONG 1024
#define NSAMPS_SHORT 128
#define NUM_SYN_ID_BITS 3
#define NUM_INST_TAG_BITS 4
#define EXT_SBR_DATA 0x0d
#define EXT_SBR_DATA_CRC 0x0e
#define IS_ADIF(p) ((p)[0] == 'A' && (p)[1] == 'D' && (p)[2] == 'I' && (p)[3] == 'F')
#define GET_ELE_ID(p) ((AACElementID)(*(p) >> (8-NUM_SYN_ID_BITS)))
/* AAC file format */
enum {
AAC_FF_Unknown = 0, /* should be 0 on init */
AAC_FF_ADTS = 1,
AAC_FF_ADIF = 2,
AAC_FF_RAW = 3
};
/* syntactic element type */
enum {
AAC_ID_INVALID = -1,
AAC_ID_SCE = 0,
AAC_ID_CPE = 1,
AAC_ID_CCE = 2,
AAC_ID_LFE = 3,
AAC_ID_DSE = 4,
AAC_ID_PCE = 5,
AAC_ID_FIL = 6,
AAC_ID_END = 7
};
typedef struct _AACDecInfo {
/* pointers to platform-specific state information */
void *psInfoBase; /* baseline MPEG-4 LC decoding */
void *psInfoSBR; /* MPEG-4 SBR decoding */
/* raw decoded data, before rounding to 16-bit PCM (for postprocessing such as SBR) */
void *rawSampleBuf[AAC_MAX_NCHANS];
int rawSampleBytes;
int rawSampleFBits;
/* fill data (can be used for processing SBR or other extensions) */
unsigned char *fillBuf;
int fillCount;
int fillExtType;
/* block information */
int prevBlockID;
int currBlockID;
int currInstTag;
int sbDeinterleaveReqd[MAX_NCHANS_ELEM];
int adtsBlocksLeft;
/* user-accessible info */
int bitRate;
int nChans;
int sampRate;
int profile;
int format;
int sbrEnabled;
int tnsUsed;
int pnsUsed;
int frameCount;
} AACDecInfo;
/* decoder functions which must be implemented for each platform */
AACDecInfo *AllocateBuffers(void);
AACDecInfo *AllocateBuffersPre(void **space, int *len);
void FreeBuffers(AACDecInfo *aacDecInfo);
void ClearBuffer(void *buf, int nBytes);
int UnpackADTSHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail);
int GetADTSChannelMapping(AACDecInfo *aacDecInfo, unsigned char *buf, int bitOffset, int bitsAvail);
int UnpackADIFHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail);
int SetRawBlockParams(AACDecInfo *aacDecInfo, int copyLast, int nChans, int sampRate, int profile);
int PrepareRawBlock(AACDecInfo *aacDecInfo);
int FlushCodec(AACDecInfo *aacDecInfo);
int DecodeNextElement(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail);
int DecodeNoiselessData(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail, int ch);
int Dequantize(AACDecInfo *aacDecInfo, int ch);
int StereoProcess(AACDecInfo *aacDecInfo);
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch);
int PNS(AACDecInfo *aacDecInfo, int ch);
int TNSFilter(AACDecInfo *aacDecInfo, int ch);
int IMDCT(AACDecInfo *aacDecInfo, int ch, int chBase, short *outbuf);
/* SBR specific functions */
int InitSBR(AACDecInfo *aacDecInfo);
int InitSBRPre(AACDecInfo *aacDecInfo, void **ptr, int *sz);
void FreeSBR(AACDecInfo *aacDecInfo);
int DecodeSBRBitstream(AACDecInfo *aacDecInfo, int chBase);
int DecodeSBRData(AACDecInfo *aacDecInfo, int chBase, short *outbuf);
int FlushCodecSBR(AACDecInfo *aacDecInfo);
/* aactabs.c - global ROM tables */
extern const int sampRateTab[NUM_SAMPLE_RATES];
extern const int predSFBMax[NUM_SAMPLE_RATES];
extern const int channelMapTab[NUM_DEF_CHAN_MAPS];
extern const int elementNumChans[NUM_ELEMENTS];
extern const unsigned /*char*/ int sfBandTotalShort[NUM_SAMPLE_RATES];
extern const unsigned /*char*/ int sfBandTotalLong[NUM_SAMPLE_RATES];
extern const int sfBandTabShortOffset[NUM_SAMPLE_RATES];
extern const /*short*/ int sfBandTabShort[76];
extern const int sfBandTabLongOffset[NUM_SAMPLE_RATES];
extern const /*short*/ int sfBandTabLong[325];
extern const int tnsMaxBandsShortOffset[AAC_NUM_PROFILES];
extern const unsigned /*char*/ int tnsMaxBandsShort[2*NUM_SAMPLE_RATES];
extern const unsigned /*char*/ int tnsMaxOrderShort[AAC_NUM_PROFILES];
extern const int tnsMaxBandsLongOffset[AAC_NUM_PROFILES];
extern const unsigned /*char*/ int tnsMaxBandsLong[2*NUM_SAMPLE_RATES];
extern const unsigned /*char*/ int tnsMaxOrderLong[AAC_NUM_PROFILES];
#endif /* _AACCOMMON_H */

View File

@@ -1,476 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aacdec.c,v 1.1 2005/02/26 01:47:31 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* aacdec.c - platform-independent top level decoder API
**************************************************************************************/
#include "aaccommon.h"
//#include "profile.h"
#define PROFILE_START(x)
#define PROFILE_END()
/**************************************************************************************
* Function: AACInitDecoder
*
* Description: allocate memory for platform-specific data
* clear all the user-accessible fields
* initialize SBR decoder if enabled
*
* Inputs: none
*
* Outputs: none
*
* Return: handle to AAC decoder instance, 0 if malloc fails
**************************************************************************************/
HAACDecoder AACInitDecoder(void)
{
AACDecInfo *aacDecInfo;
aacDecInfo = AllocateBuffers();
if (!aacDecInfo)
return 0;
#ifdef AAC_ENABLE_SBR
if (InitSBR(aacDecInfo)) {
AACFreeDecoder(aacDecInfo);
return 0;
}
#endif
return (HAACDecoder)aacDecInfo;
}
HAACDecoder AACInitDecoderPre(void *ptr, int sz)
{
AACDecInfo *aacDecInfo;
aacDecInfo = AllocateBuffersPre(&ptr, &sz);
if (!aacDecInfo)
return 0;
#ifdef AAC_ENABLE_SBR
if (InitSBRPre(aacDecInfo, &ptr, &sz)) {
return 0;
}
#endif
return (HAACDecoder)aacDecInfo;
}
/**************************************************************************************
* Function: AACFreeDecoder
*
* Description: free platform-specific data allocated by AACInitDecoder
* free SBR decoder if enabled
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
*
* Outputs: none
*
* Return: none
**************************************************************************************/
void AACFreeDecoder(HAACDecoder hAACDecoder)
{
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo)
return;
#ifdef AAC_ENABLE_SBR
FreeSBR(aacDecInfo);
#endif
FreeBuffers(aacDecInfo);
}
/**************************************************************************************
* Function: AACFindSyncWord
*
* Description: locate the next byte-alinged sync word in the raw AAC stream
*
* Inputs: buffer to search for sync word
* max number of bytes to search in buffer
*
* Outputs: none
*
* Return: offset to first sync word (bytes from start of buf)
* -1 if sync not found after searching nBytes
**************************************************************************************/
int AACFindSyncWord(unsigned char *buf, int nBytes)
{
int i;
/* find byte-aligned syncword (12 bits = 0xFFF) */
for (i = 0; i < nBytes - 1; i++) {
if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL )
return i;
}
return -1;
}
/**************************************************************************************
* Function: AACGetLastFrameInfo
*
* Description: get info about last AAC frame decoded (number of samples decoded,
* sample rate, bit rate, etc.)
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
* pointer to AACFrameInfo struct
*
* Outputs: filled-in AACFrameInfo struct
*
* Return: none
*
* Notes: call this right after calling AACDecode()
**************************************************************************************/
void AACGetLastFrameInfo(HAACDecoder hAACDecoder, AACFrameInfo *aacFrameInfo)
{
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo) {
aacFrameInfo->bitRate = 0;
aacFrameInfo->nChans = 0;
aacFrameInfo->sampRateCore = 0;
aacFrameInfo->sampRateOut = 0;
aacFrameInfo->bitsPerSample = 0;
aacFrameInfo->outputSamps = 0;
aacFrameInfo->profile = 0;
aacFrameInfo->tnsUsed = 0;
aacFrameInfo->pnsUsed = 0;
} else {
aacFrameInfo->bitRate = aacDecInfo->bitRate;
aacFrameInfo->nChans = aacDecInfo->nChans;
aacFrameInfo->sampRateCore = aacDecInfo->sampRate;
aacFrameInfo->sampRateOut = aacDecInfo->sampRate * (aacDecInfo->sbrEnabled ? 2 : 1);
aacFrameInfo->bitsPerSample = 16;
aacFrameInfo->outputSamps = aacDecInfo->nChans * AAC_MAX_NSAMPS * (aacDecInfo->sbrEnabled ? 2 : 1);
aacFrameInfo->profile = aacDecInfo->profile;
aacFrameInfo->tnsUsed = aacDecInfo->tnsUsed;
aacFrameInfo->pnsUsed = aacDecInfo->pnsUsed;
}
}
/**************************************************************************************
* Function: AACSetRawBlockParams
*
* Description: set internal state variables for decoding a stream of raw data blocks
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
* flag indicating source of parameters
* AACFrameInfo struct, with the members nChans, sampRate, and profile
* optionally filled-in
*
* Outputs: updated codec state
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: if copyLast == 1, then the codec sets up its internal state (for
* decoding raw blocks) based on previously-decoded ADTS header info
* if copyLast == 0, then the codec uses the values passed in
* aacFrameInfo to configure its internal state (useful when the
* source is MP4 format, for example)
**************************************************************************************/
int AACSetRawBlockParams(HAACDecoder hAACDecoder, int copyLast, AACFrameInfo *aacFrameInfo)
{
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
aacDecInfo->format = AAC_FF_RAW;
if (copyLast)
return SetRawBlockParams(aacDecInfo, 1, 0, 0, 0);
else
return SetRawBlockParams(aacDecInfo, 0, aacFrameInfo->nChans, aacFrameInfo->sampRateCore, aacFrameInfo->profile);
}
/**************************************************************************************
* Function: AACFlushCodec
*
* Description: flush internal codec state (after seeking, for example)
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int AACFlushCodec(HAACDecoder hAACDecoder)
{
int ch;
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* reset common state variables which change per-frame
* don't touch state variables which are (usually) constant for entire clip
* (nChans, sampRate, profile, format, sbrEnabled)
*/
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
for (ch = 0; ch < MAX_NCHANS_ELEM; ch++)
aacDecInfo->sbDeinterleaveReqd[ch] = 0;
aacDecInfo->adtsBlocksLeft = 0;
aacDecInfo->tnsUsed = 0;
aacDecInfo->pnsUsed = 0;
/* reset internal codec state (flush overlap buffers, etc.) */
FlushCodec(aacDecInfo);
#ifdef AAC_ENABLE_SBR
FlushCodecSBR(aacDecInfo);
#endif
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: AACDecode
*
* Description: decode AAC frame
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
* double pointer to buffer of AAC data
* pointer to number of valid bytes remaining in inbuf
* pointer to outbuf, big enough to hold one frame of decoded PCM samples
* (outbuf must be double-sized if SBR enabled)
*
* Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo
* number of output samples = 1024 per channel (2048 if SBR enabled)
* updated inbuf pointer
* updated bytesLeft
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: inbuf pointer and bytesLeft are not updated until whole frame is
* successfully decoded, so if ERR_AAC_INDATA_UNDERFLOW is returned
* just call AACDecode again with more data in inbuf
**************************************************************************************/
int AACDecode(HAACDecoder hAACDecoder, unsigned char **inbuf, int *bytesLeft, short *outbuf)
{
int err, offset, bitOffset, bitsAvail;
int ch, baseChan, elementChans;
unsigned char *inptr;
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
#ifdef AAC_ENABLE_SBR
int baseChanSBR, elementChansSBR;
#endif
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* make local copies (see "Notes" above) */
inptr = *inbuf;
bitOffset = 0;
bitsAvail = (*bytesLeft) << 3;
/* first time through figure out what the file format is */
if (aacDecInfo->format == AAC_FF_Unknown) {
if (bitsAvail < 32)
return ERR_AAC_INDATA_UNDERFLOW;
if (IS_ADIF(inptr)) {
/* unpack ADIF header */
aacDecInfo->format = AAC_FF_ADIF;
err = UnpackADIFHeader(aacDecInfo, &inptr, &bitOffset, &bitsAvail);
if (err)
return err;
} else {
/* assume ADTS by default */
aacDecInfo->format = AAC_FF_ADTS;
}
}
/* if ADTS, search for start of next frame */
if (aacDecInfo->format == AAC_FF_ADTS) {
/* can have 1-4 raw data blocks per ADTS frame (header only present for first one) */
if (aacDecInfo->adtsBlocksLeft == 0) {
offset = AACFindSyncWord(inptr, bitsAvail >> 3);
if (offset < 0)
return ERR_AAC_INDATA_UNDERFLOW;
inptr += offset;
bitsAvail -= (offset << 3);
err = UnpackADTSHeader(aacDecInfo, &inptr, &bitOffset, &bitsAvail);
if (err)
return err;
if (aacDecInfo->nChans == -1) {
/* figure out implicit channel mapping if necessary */
err = GetADTSChannelMapping(aacDecInfo, inptr, bitOffset, bitsAvail);
if (err)
return err;
}
}
aacDecInfo->adtsBlocksLeft--;
} else if (aacDecInfo->format == AAC_FF_RAW) {
err = PrepareRawBlock(aacDecInfo);
if (err)
return err;
}
/* check for valid number of channels */
if (aacDecInfo->nChans > AAC_MAX_NCHANS || aacDecInfo->nChans <= 0)
return ERR_AAC_NCHANS_TOO_HIGH;
/* will be set later if active in this frame */
aacDecInfo->tnsUsed = 0;
aacDecInfo->pnsUsed = 0;
bitOffset = 0;
baseChan = 0;
#ifdef AAC_ENABLE_SBR
baseChanSBR = 0;
#endif
do {
/* parse next syntactic element */
err = DecodeNextElement(aacDecInfo, &inptr, &bitOffset, &bitsAvail);
if (err)
return err;
elementChans = elementNumChans[aacDecInfo->currBlockID];
if (baseChan + elementChans > AAC_MAX_NCHANS)
return ERR_AAC_NCHANS_TOO_HIGH;
/* noiseless decoder and dequantizer */
for (ch = 0; ch < elementChans; ch++) {
PROFILE_START("noiseless decoder");
err = DecodeNoiselessData(aacDecInfo, &inptr, &bitOffset, &bitsAvail, ch);
PROFILE_END();
if (err)
return err;
PROFILE_START("dequant");
if (Dequantize(aacDecInfo, ch))
return ERR_AAC_DEQUANT;
PROFILE_END();
}
PROFILE_START("mid-side and intensity stereo");
/* mid-side and intensity stereo */
if (aacDecInfo->currBlockID == AAC_ID_CPE) {
if (StereoProcess(aacDecInfo))
return ERR_AAC_STEREO_PROCESS;
}
PROFILE_END();
/* PNS, TNS, inverse transform */
for (ch = 0; ch < elementChans; ch++) {
PROFILE_START("PNS");
if (PNS(aacDecInfo, ch))
return ERR_AAC_PNS;
PROFILE_END();
if (aacDecInfo->sbDeinterleaveReqd[ch]) {
/* deinterleave short blocks, if required */
if (DeinterleaveShortBlocks(aacDecInfo, ch))
return ERR_AAC_SHORT_BLOCK_DEINT;
aacDecInfo->sbDeinterleaveReqd[ch] = 0;
}
PROFILE_START("TNS");
if (TNSFilter(aacDecInfo, ch))
return ERR_AAC_TNS;
PROFILE_END();
PROFILE_START("IMDCT");
if (IMDCT(aacDecInfo, ch, baseChan + ch, outbuf))
return ERR_AAC_IMDCT;
PROFILE_END();
}
#ifdef AAC_ENABLE_SBR
if (aacDecInfo->sbrEnabled && (aacDecInfo->currBlockID == AAC_ID_FIL || aacDecInfo->currBlockID == AAC_ID_LFE)) {
if (aacDecInfo->currBlockID == AAC_ID_LFE)
elementChansSBR = elementNumChans[AAC_ID_LFE];
else if (aacDecInfo->currBlockID == AAC_ID_FIL && (aacDecInfo->prevBlockID == AAC_ID_SCE || aacDecInfo->prevBlockID == AAC_ID_CPE))
elementChansSBR = elementNumChans[aacDecInfo->prevBlockID];
else
elementChansSBR = 0;
if (baseChanSBR + elementChansSBR > AAC_MAX_NCHANS)
return ERR_AAC_SBR_NCHANS_TOO_HIGH;
/* parse SBR extension data if present (contained in a fill element) */
if (DecodeSBRBitstream(aacDecInfo, baseChanSBR))
return ERR_AAC_SBR_BITSTREAM;
/* apply SBR */
if (DecodeSBRData(aacDecInfo, baseChanSBR, outbuf))
return ERR_AAC_SBR_DATA;
baseChanSBR += elementChansSBR;
}
#endif
baseChan += elementChans;
} while (aacDecInfo->currBlockID != AAC_ID_END);
/* byte align after each raw_data_block */
if (bitOffset) {
inptr++;
bitsAvail -= (8-bitOffset);
bitOffset = 0;
if (bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
}
/* update pointers */
aacDecInfo->frameCount++;
*bytesLeft -= (inptr - *inbuf);
*inbuf = inptr;
return ERR_AAC_NONE;
}

View File

@@ -1,175 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aacdec.h,v 1.8 2005/11/10 00:15:08 margotm 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
*
* aacdec.h - public C API for AAC decoder
**************************************************************************************/
#ifndef _AACDEC_H
#define _AACDEC_H
#if defined(_WIN32) && !defined(_WIN32_WCE)
#
#elif defined(_WIN32) && defined(_WIN32_WCE) && defined(ARM)
#
#elif defined(_WIN32) && defined(WINCE_EMULATOR)
#
#elif defined (__arm) && defined (__ARMCC_VERSION)
#
#elif defined(_SYMBIAN) && defined(__WINS__)
#
#elif defined(__GNUC__) && defined(__arm__)
#
#elif defined(__GNUC__) && defined(__i386__)
#
#elif defined(__APPLE__)
#
#elif defined(__GNUC__) && defined(__amd64__)
#
#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__))
#
#elif defined(_OPENWAVE_SIMULATOR) || defined(_OPENWAVE_ARMULATOR)
#
#elif defined(_SOLARIS) && !defined(__GNUC__)
#
#elif defined(ESP_PLATFORM)
#
#else
#error No platform defined. See valid options in aacdec.h
#endif
#ifndef USE_DEFAULT_STDLIB
#define USE_DEFAULT_STDLIB
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* according to spec (13818-7 section 8.2.2, 14496-3 section 4.5.3)
* max size of input buffer =
* 6144 bits = 768 bytes per SCE or CCE-I
* 12288 bits = 1536 bytes per CPE
* 0 bits = 0 bytes per CCE-D (uses bits from the SCE/CPE/CCE-I it is coupled to)
*/
#ifndef AAC_MAX_NCHANS /* if max channels isn't set in makefile, */
#define AAC_MAX_NCHANS 2 /* set to default max number of channels */
#endif
#define AAC_MAX_NSAMPS 1024
#define AAC_MAINBUF_SIZE (768 * AAC_MAX_NCHANS)
#define AAC_NUM_PROFILES 3
#define AAC_PROFILE_MP 0
#define AAC_PROFILE_LC 1
#define AAC_PROFILE_SSR 2
/* define these to enable decoder features */
#if defined(HELIX_FEATURE_AUDIO_CODEC_AAC_SBR)
#define AAC_ENABLE_SBR
#endif // HELIX_FEATURE_AUDIO_CODEC_AAC_SBR.
#define AAC_ENABLE_MPEG4
enum {
ERR_AAC_NONE = 0,
ERR_AAC_INDATA_UNDERFLOW = -1,
ERR_AAC_NULL_POINTER = -2,
ERR_AAC_INVALID_ADTS_HEADER = -3,
ERR_AAC_INVALID_ADIF_HEADER = -4,
ERR_AAC_INVALID_FRAME = -5,
ERR_AAC_MPEG4_UNSUPPORTED = -6,
ERR_AAC_CHANNEL_MAP = -7,
ERR_AAC_SYNTAX_ELEMENT = -8,
ERR_AAC_DEQUANT = -9,
ERR_AAC_STEREO_PROCESS = -10,
ERR_AAC_PNS = -11,
ERR_AAC_SHORT_BLOCK_DEINT = -12,
ERR_AAC_TNS = -13,
ERR_AAC_IMDCT = -14,
ERR_AAC_NCHANS_TOO_HIGH = -15,
ERR_AAC_SBR_INIT = -16,
ERR_AAC_SBR_BITSTREAM = -17,
ERR_AAC_SBR_DATA = -18,
ERR_AAC_SBR_PCM_FORMAT = -19,
ERR_AAC_SBR_NCHANS_TOO_HIGH = -20,
ERR_AAC_SBR_SINGLERATE_UNSUPPORTED = -21,
ERR_AAC_RAWBLOCK_PARAMS = -22,
ERR_AAC_UNKNOWN = -9999
};
typedef struct _AACFrameInfo {
int bitRate;
int nChans;
int sampRateCore;
int sampRateOut;
int bitsPerSample;
int outputSamps;
int profile;
int tnsUsed;
int pnsUsed;
} AACFrameInfo;
typedef void *HAACDecoder;
/* public C API */
HAACDecoder AACInitDecoder(void);
HAACDecoder AACInitDecoderPre(void *ptr, int sz);
void AACFreeDecoder(HAACDecoder hAACDecoder);
int AACDecode(HAACDecoder hAACDecoder, unsigned char **inbuf, int *bytesLeft, short *outbuf);
int AACFindSyncWord(unsigned char *buf, int nBytes);
void AACGetLastFrameInfo(HAACDecoder hAACDecoder, AACFrameInfo *aacFrameInfo);
int AACSetRawBlockParams(HAACDecoder hAACDecoder, int copyLast, AACFrameInfo *aacFrameInfo);
int AACFlushCodec(HAACDecoder hAACDecoder);
#ifdef HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT
int AACInitTrigtabsFloat(void);
void AACFreeTrigtabsFloat(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _AACDEC_H */

View File

@@ -1,157 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aactabs.c,v 1.1 2005/02/26 01:47:31 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* aactabs.c - platform-independent tables for AAC decoder (global, read-only)
**************************************************************************************/
#include "aaccommon.h"
/* sample rates (table 4.5.1) */
const int sampRateTab[NUM_SAMPLE_RATES] PROGMEM = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000
};
/* max scalefactor band for prediction (main profile only) */
const int predSFBMax[NUM_SAMPLE_RATES] PROGMEM = {
33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34
};
/* channel mapping (table 1.6.3.4) (-1 = unknown, so need to determine mapping based on rules in 8.5.1) */
const int channelMapTab[NUM_DEF_CHAN_MAPS] PROGMEM = {
-1, 1, 2, 3, 4, 5, 6, 8
};
/* number of channels in each element (SCE, CPE, etc.)
* see AACElementID in aaccommon.h
*/
const int elementNumChans[NUM_ELEMENTS] PROGMEM = {
1, 2, 0, 1, 0, 0, 0, 0
};
/* total number of scale factor bands in one window */
const unsigned int /*char*/ sfBandTotalShort[NUM_SAMPLE_RATES] PROGMEM = {
12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15
};
const unsigned int /*char*/ sfBandTotalLong[NUM_SAMPLE_RATES] PROGMEM = {
41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40
};
/* scale factor band tables */
const int sfBandTabShortOffset[NUM_SAMPLE_RATES] PROGMEM = {0, 0, 0, 13, 13, 13, 28, 28, 44, 44, 44, 60};
const /*short*/ int sfBandTabShort[76] PROGMEM = {
/* short block 64, 88, 96 kHz [13] (tables 4.5.24, 4.5.26) */
0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128,
/* short block 32, 44, 48 kHz [15] (table 4.5.15) */
0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128,
/* short block 22, 24 kHz [16] (table 4.5.22) */
0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128,
/* short block 11, 12, 16 kHz [16] (table 4.5.20) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, 108, 128,
/* short block 8 kHz [16] (table 4.5.18) */
0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88, 108, 128
};
const int sfBandTabLongOffset[NUM_SAMPLE_RATES] PROGMEM = {0, 0, 42, 90, 90, 140, 192, 192, 240, 240, 240, 284};
const /*short*/ int sfBandTabLong[325] PROGMEM = {
/* long block 88, 96 kHz [42] (table 4.5.25) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212,
240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024,
/* long block 64 kHz [48] (table 4.5.13) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64,
72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, 344, 384,
424, 464, 504, 544, 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024,
/* long block 44, 48 kHz [50] (table 4.5.14) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88,
96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448,
480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024,
/* long block 32 kHz [52] (table 4.5.16) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88, 96,
108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512,
544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024,
/* long block 22, 24 kHz [48] (table 4.5.21) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 76,
84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, 220, 240, 260, 284,
308, 336, 364, 396, 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024,
/* long block 11, 12, 16 kHz [44] (table 4.5.19) */
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124,
136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, 368,
396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024,
/* long block 8 kHz [41] (table 4.5.17) */
0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156,
172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420,
448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024
};
/* TNS max bands (table 4.139) and max order (table 4.138) */
const int tnsMaxBandsShortOffset[AAC_NUM_PROFILES] PROGMEM = {0, 0, 12};
const unsigned /*char*/ int tnsMaxBandsShort[2*NUM_SAMPLE_RATES] PROGMEM = {
9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, /* short block, Main/LC */
7, 7, 7, 6, 6, 6, 7, 7, 8, 8, 8, 7 /* short block, SSR */
};
const unsigned /*char*/ int tnsMaxOrderShort[AAC_NUM_PROFILES] PROGMEM = {7, 7, 7};
const int tnsMaxBandsLongOffset[AAC_NUM_PROFILES] PROGMEM = {0, 0, 12};
const unsigned int /*char*/ tnsMaxBandsLong[2*NUM_SAMPLE_RATES] PROGMEM = {
31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39, /* long block, Main/LC */
28, 28, 27, 26, 26, 26, 29, 29, 23, 23, 23, 19, /* long block, SSR */
};
const unsigned /*char*/ int tnsMaxOrderLong[AAC_NUM_PROFILES] PROGMEM = {20, 12, 12};

View File

@@ -1,728 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: assembly.h,v 1.7 2005/11/10 00:04:40 margotm 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
*
* assembly.h - inline assembly language functions and prototypes
*
* MULSHIFT32(x, y) signed multiply of two 32-bit integers (x and y),
* returns top 32-bits of 64-bit result
* CLIPTOSHORT(x) convert 32-bit integer to 16-bit short,
* clipping to [-32768, 32767]
* FASTABS(x) branchless absolute value of signed integer x
* CLZ(x) count leading zeros on signed integer x
* MADD64(sum64, x, y) 64-bit multiply accumulate: sum64 += (x*y)
**************************************************************************************/
#ifndef _ASSEMBLY_H
#define _ASSEMBLY_H
/* toolchain: MSFT Visual C++
* target architecture: x86
*/
#if (defined (_WIN32) && !defined (_WIN32_WCE)) || (defined (__WINS__) && defined (_SYMBIAN)) || (defined (WINCE_EMULATOR)) || (defined (_OPENWAVE_SIMULATOR))
#pragma warning( disable : 4035 ) /* complains about inline asm not returning a value */
static __inline int MULSHIFT32(int x, int y)
{
__asm {
mov eax, x
imul y
mov eax, edx
}
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
#ifdef __CW32__
typedef long long Word64;
#else
typedef __int64 Word64;
#endif
typedef union _U64 {
Word64 w64;
struct {
/* x86 = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
/* returns 64-bit value in [edx:eax] */
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
#if (defined (_SYMBIAN_61_) || defined (_SYMBIAN_70_)) && defined (__WINS__) && !defined (__CW32__)
/* Workaround for the Symbian emulator because of non existing longlong.lib and
* hence __allmul not defined. */
__asm {
mov eax, x
imul y
add dword ptr sum64, eax
adc dword ptr sum64 + 4, edx
}
#else
sum64 += (Word64)x * (Word64)y;
#endif
return sum64;
}
/* toolchain: MSFT Embedded Visual C++
* target architecture: ARM v.4 and above (require 'M' type processor for 32x32->64 multiplier)
*/
#elif defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
/* implemented in asmfunc.s */
#ifdef __cplusplus
extern "C" {
#endif
typedef __int64 Word64;
typedef union _U64 {
Word64 w64;
struct {
/* ARM WinCE = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
/* manual name mangling for just this platform (must match labels in .s file) */
#define MULSHIFT32 raac_MULSHIFT32
#define MADD64 raac_MADD64
int MULSHIFT32(int x, int y);
Word64 MADD64(Word64 sum64, int x, int y);
#ifdef __cplusplus
}
#endif
/* toolchain: ARM ADS or RealView
* target architecture: ARM v.4 and above (requires 'M' type processor for 32x32->64 multiplier)
*/
#elif defined (XXX__arm) && defined (__ARMCC_VERSION)
static __inline int MULSHIFT32(int x, int y)
{
/* rules for smull RdLo, RdHi, Rm, Rs:
* RdHi != Rm
* RdLo != Rm
* RdHi != RdLo
*/
int zlow;
__asm {
smull zlow,y,x,y
}
return y;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
/* ARM code would look like this, but do NOT use inline asm in ADS for this,
because you can't safely use the status register flags intermixed with C code
__asm {
mov numZeros, #1
tst x, 0xffff0000
addeq numZeros, numZeros, #16
moveq x, x, lsl #16
tst x, 0xff000000
addeq numZeros, numZeros, #8
moveq x, x, lsl #8
tst x, 0xf0000000
addeq numZeros, numZeros, #4
moveq x, x, lsl #4
tst x, 0xc0000000
addeq numZeros, numZeros, #2
moveq x, x, lsl #2
sub numZeros, numZeros, x, lsr #31
}
*/
/* reference:
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
*/
}
typedef __int64 Word64;
typedef union _U64 {
Word64 w64;
struct {
/* ARM ADS = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
U64 u;
u.w64 = sum64;
__asm {
smlal u.r.lo32, u.r.hi32, x, y
}
return u.w64;
}
/* toolchain: ARM gcc
* target architecture: ARM v.4 and above (requires 'M' type processor for 32x32->64 multiplier)
*/
#elif defined(__GNUC__) && defined(XXXX__arm__)
static inline int MULSHIFT32(int x, int y)
{
int zlow;
asm ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y) : "cc");
return y;
}
/*
static inline short CLIPTOSHORT(int x)
{
int sign;
// clip to [-32768, 32767] //
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
*/
static inline short CLIPTOSHORT(int x)
{
asm ("ssat %0, #16, %1" : "=r" (x) : "r" (x));
return x;
}
/* From coder.h, ORIGINAL:
clip to [-2^n, 2^n-1], valid range of n = [1, 30]
//TODO (FB) Is there a better way ?
*/
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (n)) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
/* From coder.h, ORIGINAL:
do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit)
*/
//TODO (FB) Is there a better way ?
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
#define FASTABS(x) abs(x) //FB
#define CLZ(x) __builtin_clz(x) //FB
//Reverse byte order (16 bit) //FB
static inline unsigned int REV16( unsigned int value)
{
asm ("rev16 %0, %1" : "=r" (value) : "r" (value) );
return(value);
}
//Reverse byte order (32 bit) //FB
static inline unsigned int REV32( unsigned int value)
{
asm ("rev %0, %1" : "=r" (value) : "r" (value) );
return(value);
}
typedef long long Word64;
typedef union _U64 {
Word64 w64;
struct {
/* little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static inline Word64 MADD64(Word64 sum64, int x, int y)
{
U64 u;
u.w64 = sum64;
asm ("smlal %0,%1,%2,%3" : "+&r" (u.r.lo32), "+&r" (u.r.hi32) : "r" (x), "r" (y) : "cc");
return u.w64;
}
/* toolchain: x86 gcc
* target architecture: x86
*/
#elif defined(__APPLE__) || defined(__GNUC__) && (defined(__i386__) || defined(__amd64__)) || (defined (_SOLARIS) && !defined (__GNUC__) && defined(_SOLARISX86))
typedef long long Word64;
static __inline__ int MULSHIFT32(int x, int y)
{
int z;
z = (Word64)x * (Word64)y >> 32;
return z;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
typedef union _U64 {
Word64 w64;
struct {
/* x86 = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
#elif defined(__arm__)
typedef long long Word64;
typedef union _U64 {
Word64 w64;
struct {
/* x86 = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
#if defined(ARM7DI)
static __inline int MULSHIFT32(int x, int y) {
return x * y;
}
#else
static __inline int MULSHIFT32(int x, int y)
{
/* important rules for smull RdLo, RdHi, Rm, Rs:
* RdHi and Rm can't be the same register
* RdLo and Rm can't be the same register
* RdHi and RdLo can't be the same register
* Note: Rs determines early termination (leading sign bits) so if you want to specify
* which operand is Rs, put it in the SECOND argument (y)
* For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter
* which one is returned. (If this were a function call, returning y (R1) would
* require an extra "mov r0, r1")
*/
int zlow;
__asm__ volatile ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y)) ;
return y;
}
#endif
static __inline int FASTABS(int x)
{
int t=0; /*Really is not necessary to initialiaze only to avoid warning*/
__asm__ volatile (
"eor %0,%2,%2, asr #31;"
"sub %0,%1,%2, asr #31;"
: "=&r" (t)
: "0" (t), "r" (x)
);
return t;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
#elif defined(ESP_PLATFORM) || defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__)) || (defined (_SOLARIS) && !defined (__GNUC__) && !defined (_SOLARISX86))
typedef long long Word64;
static __inline__ int MULSHIFT32(int x, int y)
{
int z;
z = (Word64)x * (Word64)y >> 32;
return z;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
typedef union _U64 {
Word64 w64;
struct {
#ifdef __XTENSA__
unsigned int lo32;
signed int hi32;
#else
/* PowerPC = big endian */
signed int hi32;
unsigned int lo32;
#endif
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
/* From coder.h, ORIGINAL:
clip to [-2^n, 2^n-1], valid range of n = [1, 30]
//TODO (FB) Is there a better way ?
*/
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (n)) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
/* From coder.h, ORIGINAL:
do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit)
*/
//TODO (FB) Is there a better way ?
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
//#define FASTABS(x) abs(x) //FB
//#define CLZ(x) __builtin_clz(x) //FB
#else
#error Unsupported platform in assembly.h
#endif /* platforms */
#ifndef CLIP_2N
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (n)) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
#endif
#ifndef CLIP_2N_SHIFT
/* From coder.h, ORIGINAL:
do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit)
*/
//TODO (FB) Is there a better way ?
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
#endif
#endif /* _ASSEMBLY_H */

View File

@@ -1,261 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: bitstream.c,v 1.2 2005/09/27 20:31:11 jrecker 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
*
* bitstream.c - bitstream parsing functions
**************************************************************************************/
#include "bitstream.h"
/**************************************************************************************
* Function: SetBitstreamPointer
*
* Description: initialize bitstream reader
*
* Inputs: pointer to BitStreamInfo struct
* number of bytes in bitstream
* pointer to byte-aligned buffer of data to read from
*
* Outputs: initialized bitstream info struct
*
* Return: none
**************************************************************************************/
void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf)
{
/* init bitstream */
bsi->bytePtr = buf;
bsi->iCache = 0; /* 4-byte unsigned int */
bsi->cachedBits = 0; /* i.e. zero bits in cache */
bsi->nBytes = nBytes;
}
/**************************************************************************************
* Function: RefillBitstreamCache
*
* Description: read new data from bitstream buffer into 32-bit cache
*
* Inputs: pointer to initialized BitStreamInfo struct
*
* Outputs: updated bitstream info struct
*
* Return: none
*
* Notes: only call when iCache is completely drained (resets bitOffset to 0)
* always loads 4 new bytes except when bsi->nBytes < 4 (end of buffer)
* stores data as big-endian in cache, regardless of machine endian-ness
**************************************************************************************/
//Optimized for REV16, REV32 (FB)
static __inline void RefillBitstreamCache(BitStreamInfo *bsi)
{
int nBytes = bsi->nBytes;
if (nBytes >= 4) {
/* optimize for common case, independent of machine endian-ness */
bsi->iCache = (*bsi->bytePtr++) << 24;
bsi->iCache |= (*bsi->bytePtr++) << 16;
bsi->iCache |= (*bsi->bytePtr++) << 8;
bsi->iCache |= (*bsi->bytePtr++);
bsi->cachedBits = 32;
bsi->nBytes -= 4;
} else {
bsi->iCache = 0;
while (nBytes--) {
bsi->iCache |= (*bsi->bytePtr++);
bsi->iCache <<= 8;
}
bsi->iCache <<= ((3 - bsi->nBytes)*8);
bsi->cachedBits = 8*bsi->nBytes;
bsi->nBytes = 0;
}
}
/**************************************************************************************
* Function: GetBits
*
* Description: get bits from bitstream, advance bitstream pointer
*
* Inputs: pointer to initialized BitStreamInfo struct
* number of bits to get from bitstream
*
* Outputs: updated bitstream info struct
*
* Return: the next nBits bits of data from bitstream buffer
*
* Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f
* for speed, does not indicate error if you overrun bit buffer
* if nBits == 0, returns 0
**************************************************************************************/
unsigned int GetBits(BitStreamInfo *bsi, int nBits)
{
unsigned int data, lowBits;
nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */
data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */
data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */
bsi->iCache <<= nBits; /* left-justify cache */
bsi->cachedBits -= nBits; /* how many bits have we drawn from the cache so far */
/* if we cross an int boundary, refill the cache */
if (bsi->cachedBits < 0) {
lowBits = -bsi->cachedBits;
RefillBitstreamCache(bsi);
data |= bsi->iCache >> (32 - lowBits); /* get the low-order bits */
bsi->cachedBits -= lowBits; /* how many bits have we drawn from the cache so far */
bsi->iCache <<= lowBits; /* left-justify cache */
}
return data;
}
/**************************************************************************************
* Function: GetBitsNoAdvance
*
* Description: get bits from bitstream, do not advance bitstream pointer
*
* Inputs: pointer to initialized BitStreamInfo struct
* number of bits to get from bitstream
*
* Outputs: none (state of BitStreamInfo struct left unchanged)
*
* Return: the next nBits bits of data from bitstream buffer
*
* Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f
* for speed, does not indicate error if you overrun bit buffer
* if nBits == 0, returns 0
**************************************************************************************/
unsigned int GetBitsNoAdvance(BitStreamInfo *bsi, int nBits)
{
unsigned char *buf;
unsigned int data, iCache;
signed int lowBits;
nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */
data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */
data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */
lowBits = nBits - bsi->cachedBits; /* how many bits do we have left to read */
/* if we cross an int boundary, read next bytes in buffer */
if (lowBits > 0) {
iCache = 0;
buf = bsi->bytePtr;
while (lowBits > 0) {
iCache <<= 8;
if (buf < bsi->bytePtr + bsi->nBytes)
iCache |= (unsigned int)*buf++;
lowBits -= 8;
}
lowBits = -lowBits;
data |= iCache >> lowBits;
}
return data;
}
/**************************************************************************************
* Function: AdvanceBitstream
*
* Description: move bitstream pointer ahead
*
* Inputs: pointer to initialized BitStreamInfo struct
* number of bits to advance bitstream
*
* Outputs: updated bitstream info struct
*
* Return: none
*
* Notes: generally used following GetBitsNoAdvance(bsi, maxBits)
**************************************************************************************/
void AdvanceBitstream(BitStreamInfo *bsi, int nBits)
{
nBits &= 0x1f;
if (nBits > bsi->cachedBits) {
nBits -= bsi->cachedBits;
RefillBitstreamCache(bsi);
}
bsi->iCache <<= nBits;
bsi->cachedBits -= nBits;
}
/**************************************************************************************
* Function: CalcBitsUsed
*
* Description: calculate how many bits have been read from bitstream
*
* Inputs: pointer to initialized BitStreamInfo struct
* pointer to start of bitstream buffer
* bit offset into first byte of startBuf (0-7)
*
* Outputs: none
*
* Return: number of bits read from bitstream, as offset from startBuf:startOffset
**************************************************************************************/
int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset)
{
int bitsUsed;
bitsUsed = (bsi->bytePtr - startBuf) * 8;
bitsUsed -= bsi->cachedBits;
bitsUsed -= startOffset;
return bitsUsed;
}
/**************************************************************************************
* Function: ByteAlignBitstream
*
* Description: bump bitstream pointer to start of next byte
*
* Inputs: pointer to initialized BitStreamInfo struct
*
* Outputs: byte-aligned bitstream BitStreamInfo struct
*
* Return: none
*
* Notes: if bitstream is already byte-aligned, do nothing
**************************************************************************************/
void ByteAlignBitstream(BitStreamInfo *bsi)
{
int offset;
offset = bsi->cachedBits & 0x07;
AdvanceBitstream(bsi, offset);
}

View File

@@ -1,74 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: bitstream.h,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* bitstream.h - definitions of bitstream handling functions
**************************************************************************************/
#ifndef _BITSTREAM_H
#define _BITSTREAM_H
#include "aaccommon.h"
/* additional external symbols to name-mangle for static linking */
#define SetBitstreamPointer STATNAME(SetBitstreamPointer)
#define GetBits STATNAME(GetBits)
#define GetBitsNoAdvance STATNAME(GetBitsNoAdvance)
#define AdvanceBitstream STATNAME(AdvanceBitstream)
#define CalcBitsUsed STATNAME(CalcBitsUsed)
#define ByteAlignBitstream STATNAME(ByteAlignBitstream)
typedef struct _BitStreamInfo {
unsigned char *bytePtr;
unsigned int iCache;
int cachedBits;
int nBytes;
} BitStreamInfo;
/* bitstream.c */
void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf);
unsigned int GetBits(BitStreamInfo *bsi, int nBits);
unsigned int GetBitsNoAdvance(BitStreamInfo *bsi, int nBits);
void AdvanceBitstream(BitStreamInfo *bsi, int nBits);
int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset);
void ByteAlignBitstream(BitStreamInfo *bsi);
#endif /* _BITSTREAM_H */

View File

@@ -1,165 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: buffers.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* buffers.c - allocation and deallocation of internal AAC decoder buffers
**************************************************************************************/
#if defined(USE_DEFAULT_STDLIB) || defined(ESP_PLATFORM)
#include <stdlib.h>
#else
#include "hlxclib/stdlib.h"
#endif
#include "coder.h"
/**************************************************************************************
* Function: ClearBuffer
*
* Description: fill buffer with 0's
*
* Inputs: pointer to buffer
* number of bytes to fill with 0
*
* Outputs: cleared buffer
*
* Return: none
*
* Notes: slow, platform-independent equivalent to memset(buf, 0, nBytes)
**************************************************************************************/
#include <string.h>
void ClearBuffer(void *buf, int nBytes)
{
/* int i;
unsigned char *cbuf = (unsigned char *)buf;
for (i = 0; i < nBytes; i++)
cbuf[i] = 0;
return;
*/
memset(buf, 0, nBytes);
}
/**************************************************************************************
* Function: AllocateBuffers
*
* Description: allocate all the memory needed for the AAC decoder
*
* Inputs: none
*
* Outputs: none
*
* Return: pointer to AACDecInfo structure, cleared to all 0's (except for
* pointer to platform-specific data structure)
*
* Notes: if one or more mallocs fail, function frees any buffers already
* allocated before returning
**************************************************************************************/
AACDecInfo *AllocateBuffers(void)
{
AACDecInfo *aacDecInfo;
aacDecInfo = (AACDecInfo *)malloc(sizeof(AACDecInfo));
if (!aacDecInfo)
return 0;
ClearBuffer(aacDecInfo, sizeof(AACDecInfo));
aacDecInfo->psInfoBase = malloc(sizeof(PSInfoBase));
if (!aacDecInfo->psInfoBase) {
FreeBuffers(aacDecInfo);
return 0;
}
ClearBuffer(aacDecInfo->psInfoBase, sizeof(PSInfoBase));
return aacDecInfo;
}
AACDecInfo *AllocateBuffersPre(void **ptr, int *sz)
{
AACDecInfo *aacDecInfo;
char *p = (char*)*ptr;
aacDecInfo = (AACDecInfo *)p;
p += (sizeof(AACDecInfo) +7 ) & ~7;
*sz -= (sizeof(AACDecInfo) +7 ) & ~7;
if (*sz < 0)
return 0;
ClearBuffer(aacDecInfo, sizeof(AACDecInfo));
aacDecInfo->psInfoBase = (PSInfoBase*)p;
p += (sizeof(PSInfoBase) + 7) & ~7;
*sz -= (sizeof(PSInfoBase) + 7) & ~7;
if (*sz <0) {
return 0;
}
ClearBuffer(aacDecInfo->psInfoBase, sizeof(PSInfoBase));
*ptr = p;
return aacDecInfo;
}
#ifndef SAFE_FREE
#define SAFE_FREE(x) {if (x) free(x); (x) = 0;} /* helper macro */
#endif
/**************************************************************************************
* Function: FreeBuffers
*
* Description: frees all the memory used by the AAC decoder
*
* Inputs: pointer to initialized AACDecInfo structure
*
* Outputs: none
*
* Return: none
*
* Notes: safe to call even if some buffers were not allocated (uses SAFE_FREE)
**************************************************************************************/
void FreeBuffers(AACDecInfo *aacDecInfo)
{
if (!aacDecInfo)
return;
SAFE_FREE(aacDecInfo->psInfoBase);
SAFE_FREE(aacDecInfo);
}

View File

@@ -1,373 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: coder.h,v 1.2 2005/06/27 21:06:00 gwright 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
*
* coder.h - definitions of platform-specific data structures, functions, and tables
**************************************************************************************/
#ifndef _CODER_H
#define _CODER_H
#include "aaccommon.h"
#include "bitstream.h"
#ifndef ASSERT
#if defined(_WIN32) && defined(_M_IX86) && (defined (_DEBUG) || defined (REL_ENABLE_ASSERTS))
#define ASSERT(x) if (!(x)) __asm int 3;
#else
#define ASSERT(x) /* do nothing */
#endif
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#define NWINDOWS_LONG 1
#define NWINDOWS_SHORT 8
#define DATA_BUF_SIZE 510 /* max count = 255 + 255 */
#define FILL_BUF_SIZE 269 /* max count = 15 + 255 - 1*/
#define ADIF_COPYID_SIZE 9
#define MAX_COMMENT_BYTES 255
#define MAX_NUM_FCE 15
#define MAX_NUM_SCE 15
#define MAX_NUM_BCE 15
#define MAX_NUM_LCE 3
#define MAX_NUM_ADE 7
#define MAX_NUM_CCE 15
#define CHAN_ELEM_IS_CPE(x) (((x) & 0x10) >> 4) /* bit 4 = SCE/CPE flag */
#define CHAN_ELEM_GET_TAG(x) (((x) & 0x0f) >> 0) /* bits 3-0 = instance tag */
#define CHAN_ELEM_SET_CPE(x) (((x) & 0x01) << 4) /* bit 4 = SCE/CPE flag */
#define CHAN_ELEM_SET_TAG(x) (((x) & 0x0f) << 0) /* bits 3-0 = instance tag */
#define MAX_HUFF_BITS 20
#define HUFFTAB_SPEC_OFFSET 1
/* do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit) */
/*
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
*/
/* clip to [-2^n, 2^n-1], valid range of n = [1, 30] */
/*
#define CLIP_2N(val, n) { \
if ((val) >> 31 != (val) >> (n)) \
(val) = ((val) >> 31) ^ ((1 << (n)) - 1); \
}
*/
#define SF_DQ_OFFSET 15
#define FBITS_OUT_DQ 20
#define FBITS_OUT_DQ_OFF (FBITS_OUT_DQ - SF_DQ_OFFSET) /* number of fraction bits out of dequant, including 2^15 bias */
#define FBITS_IN_IMDCT FBITS_OUT_DQ_OFF /* number of fraction bits into IMDCT */
#define GBITS_IN_DCT4 4 /* min guard bits in for DCT4 */
#define FBITS_LOST_DCT4 1 /* number of fraction bits lost (>> out) in DCT-IV */
#define FBITS_LOST_WND 1 /* number of fraction bits lost (>> out) in synthesis window (neg = gain frac bits) */
#define FBITS_LOST_IMDCT (FBITS_LOST_DCT4 + FBITS_LOST_WND)
#define FBITS_OUT_IMDCT (FBITS_IN_IMDCT - FBITS_LOST_IMDCT)
#define NUM_IMDCT_SIZES 2
/* additional external symbols to name-mangle for static linking */
#define DecodeProgramConfigElement STATNAME(DecodeProgramConfigElement)
#define DecodeHuffmanScalar STATNAME(DecodeHuffmanScalar)
#define DecodeSpectrumLong STATNAME(DecodeSpectrumLong)
#define DecodeSpectrumShort STATNAME(DecodeSpectrumShort)
#define DecodeICSInfo STATNAME(DecodeICSInfo)
#define DCT4 STATNAME(DCT4)
#define R4FFT STATNAME(R4FFT)
#define DecWindowOverlapNoClip STATNAME(DecWindowOverlapNoClip)
#define DecWindowOverlapLongStartNoClip STATNAME(DecWindowOverlapLongStartNoClip)
#define DecWindowOverlapLongStopNoClip STATNAME(DecWindowOverlapLongStopNoClip)
#define DecWindowOverlapShortNoClip STATNAME(DecWindowOverlapShortNoClip)
#define huffTabSpecInfo STATNAME(huffTabSpecInfo)
#define huffTabSpec STATNAME(huffTabSpec)
#define huffTabScaleFactInfo STATNAME(huffTabScaleFactInfo)
#define huffTabScaleFact STATNAME(huffTabScaleFact)
#define cos4sin4tab STATNAME(cos4sin4tab)
#define cos4sin4tabOffset STATNAME(cos4sin4tabOffset)
#define cos1sin1tab STATNAME(cos1sin1tab)
#define sinWindow STATNAME(sinWindow)
#define sinWindowOffset STATNAME(sinWindowOffset)
#define kbdWindow STATNAME(kbdWindow)
#define kbdWindowOffset STATNAME(kbdWindowOffset)
#define bitrevtab STATNAME(bitrevtab)
#define bitrevtabOffset STATNAME(bitrevtabOffset)
#define uniqueIDTab STATNAME(uniqueIDTab)
#define twidTabEven STATNAME(twidTabEven)
#define twidTabOdd STATNAME(twidTabOdd)
typedef struct _HuffInfo {
int maxBits; /* number of bits in longest codeword */
unsigned /*char*/ int count[MAX_HUFF_BITS]; /* count[i] = number of codes with length i+1 bits */
int offset; /* offset into symbol table */
} HuffInfo;
typedef struct _PulseInfo {
unsigned char pulseDataPresent;
unsigned char numPulse;
unsigned char startSFB;
unsigned char offset[MAX_PULSES];
unsigned char amp[MAX_PULSES];
} PulseInfo;
typedef struct _TNSInfo {
unsigned char tnsDataPresent;
unsigned char numFilt[MAX_TNS_FILTERS]; /* max 1 filter each for 8 short windows, or 3 filters for 1 long window */
unsigned char coefRes[MAX_TNS_FILTERS];
unsigned char length[MAX_TNS_FILTERS];
unsigned char order[MAX_TNS_FILTERS];
unsigned char dir[MAX_TNS_FILTERS];
signed char coef[MAX_TNS_COEFS]; /* max 3 filters * 20 coefs for 1 long window, or 1 filter * 7 coefs for each of 8 short windows */
} TNSInfo;
typedef struct _GainControlInfo {
unsigned char gainControlDataPresent;
unsigned char maxBand;
unsigned char adjNum[MAX_GAIN_BANDS][MAX_GAIN_WIN];
unsigned char alevCode[MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST];
unsigned char alocCode[MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST];
} GainControlInfo;
typedef struct _ICSInfo {
unsigned char icsResBit;
unsigned char winSequence;
unsigned char winShape;
unsigned char maxSFB;
unsigned char sfGroup;
unsigned char predictorDataPresent;
unsigned char predictorReset;
unsigned char predictorResetGroupNum;
unsigned char predictionUsed[MAX_PRED_SFB];
unsigned char numWinGroup;
unsigned char winGroupLen[MAX_WIN_GROUPS];
} ICSInfo;
typedef struct _ADTSHeader {
/* fixed */
unsigned char id; /* MPEG bit - should be 1 */
unsigned char layer; /* MPEG layer - should be 0 */
unsigned char protectBit; /* 0 = CRC word follows, 1 = no CRC word */
unsigned char profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
unsigned char sampRateIdx; /* sample rate index range = [0, 11] */
unsigned char privateBit; /* ignore */
unsigned char channelConfig; /* 0 = implicit, >0 = use default table */
unsigned char origCopy; /* 0 = copy, 1 = original */
unsigned char home; /* ignore */
/* variable */
unsigned char copyBit; /* 1 bit of the 72-bit copyright ID (transmitted as 1 bit per frame) */
unsigned char copyStart; /* 1 = this bit starts the 72-bit ID, 0 = it does not */
int frameLength; /* length of frame */
int bufferFull; /* number of 32-bit words left in enc buffer, 0x7FF = VBR */
unsigned char numRawDataBlocks; /* number of raw data blocks in frame */
/* CRC */
int crcCheckWord; /* 16-bit CRC check word (present if protectBit == 0) */
} ADTSHeader;
typedef struct _ADIFHeader {
unsigned char copyBit; /* 0 = no copyright ID, 1 = 72-bit copyright ID follows immediately */
unsigned char origCopy; /* 0 = copy, 1 = original */
unsigned char home; /* ignore */
unsigned char bsType; /* bitstream type: 0 = CBR, 1 = VBR */
int bitRate; /* bitRate: CBR = bits/sec, VBR = peak bits/frame, 0 = unknown */
unsigned char numPCE; /* number of program config elements (max = 16) */
int bufferFull; /* bits left in bit reservoir */
unsigned char copyID[ADIF_COPYID_SIZE]; /* optional 72-bit copyright ID */
} ADIFHeader;
/* sizeof(ProgConfigElement) = 82 bytes (if KEEP_PCE_COMMENTS not defined) */
typedef struct _ProgConfigElement {
unsigned char elemInstTag; /* element instance tag */
unsigned char profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
unsigned char sampRateIdx; /* sample rate index range = [0, 11] */
unsigned char numFCE; /* number of front channel elements (max = 15) */
unsigned char numSCE; /* number of side channel elements (max = 15) */
unsigned char numBCE; /* number of back channel elements (max = 15) */
unsigned char numLCE; /* number of LFE channel elements (max = 3) */
unsigned char numADE; /* number of associated data elements (max = 7) */
unsigned char numCCE; /* number of valid channel coupling elements (max = 15) */
unsigned char monoMixdown; /* mono mixdown: bit 4 = present flag, bits 3-0 = element number */
unsigned char stereoMixdown; /* stereo mixdown: bit 4 = present flag, bits 3-0 = element number */
unsigned char matrixMixdown; /* matrix mixdown: bit 4 = present flag, bit 3 = unused,
bits 2-1 = index, bit 0 = pseudo-surround enable */
unsigned char fce[MAX_NUM_FCE]; /* front element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
unsigned char sce[MAX_NUM_SCE]; /* side element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
unsigned char bce[MAX_NUM_BCE]; /* back element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
unsigned char lce[MAX_NUM_LCE]; /* instance tag for LFE elements */
unsigned char ade[MAX_NUM_ADE]; /* instance tag for ADE elements */
unsigned char cce[MAX_NUM_BCE]; /* channel coupling elements: bit 4 = switching flag, bits 3-0 = inst tag */
#ifdef KEEP_PCE_COMMENTS
/* make this optional - if not enabled, decoder will just skip comments */
unsigned char commentBytes;
unsigned char commentField[MAX_COMMENT_BYTES];
#endif
} ProgConfigElement;
/* state info struct for baseline (MPEG-4 LC) decoding */
typedef struct _PSInfoBase {
/* header information */
ADTSHeader fhADTS;
ADIFHeader fhADIF;
ProgConfigElement pce[MAX_NUM_PCE_ADIF];
int dataCount;
unsigned char dataBuf[DATA_BUF_SIZE];
int fillCount;
unsigned char fillBuf[FILL_BUF_SIZE];
/* state information which is the same throughout whole frame */
int nChans;
int useImpChanMap;
int sampRateIdx;
/* state information which can be overwritten by subsequent elements within frame */
ICSInfo icsInfo[MAX_NCHANS_ELEM];
int commonWin;
short scaleFactors[MAX_NCHANS_ELEM][MAX_SF_BANDS];
unsigned char sfbCodeBook[MAX_NCHANS_ELEM][MAX_SF_BANDS];
int msMaskPresent;
unsigned char msMaskBits[MAX_MS_MASK_BYTES];
int pnsUsed[MAX_NCHANS_ELEM];
int pnsLastVal;
int intensityUsed[MAX_NCHANS_ELEM];
PulseInfo pulseInfo[MAX_NCHANS_ELEM];
TNSInfo tnsInfo[MAX_NCHANS_ELEM];
int tnsLPCBuf[MAX_TNS_ORDER];
int tnsWorkBuf[MAX_TNS_ORDER];
GainControlInfo gainControlInfo[MAX_NCHANS_ELEM];
int gbCurrent[MAX_NCHANS_ELEM];
int coef[MAX_NCHANS_ELEM][AAC_MAX_NSAMPS];
#ifdef AAC_ENABLE_SBR
int sbrWorkBuf[MAX_NCHANS_ELEM][AAC_MAX_NSAMPS];
#endif
/* state information which must be saved for each element and used in next frame */
int overlap[AAC_MAX_NCHANS][AAC_MAX_NSAMPS];
int prevWinShape[AAC_MAX_NCHANS];
} PSInfoBase;
/* private implementation-specific functions */
/* decelmnt.c */
int DecodeProgramConfigElement(ProgConfigElement *pce, BitStreamInfo *bsi);
/* huffman.c */
int DecodeHuffmanScalar(const signed short *huffTab, const HuffInfo *huffTabInfo, unsigned int bitBuf, signed int *val);
void DecodeSpectrumLong(PSInfoBase *psi, BitStreamInfo *bsi, int ch);
void DecodeSpectrumShort(PSInfoBase *psi, BitStreamInfo *bsi, int ch);
/* noiseless.c */
void DecodeICSInfo(BitStreamInfo *bsi, ICSInfo *icsInfo, int sampRateIdx);
/* dct4.c */
void DCT4(int tabidx, int *coef, int gb);
/* fft.c */
void R4FFT(int tabidx, int *x);
/* sbrimdct.c */
void DecWindowOverlapNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStartNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStopNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapShortNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
/* hufftabs.c */
extern const HuffInfo huffTabSpecInfo[11];
extern const signed short huffTabSpec[1241];
extern const HuffInfo huffTabScaleFactInfo;
extern const signed short huffTabScaleFact[121];
/* trigtabs.c */
extern const int cos4sin4tabOffset[NUM_IMDCT_SIZES];
extern const int sinWindowOffset[NUM_IMDCT_SIZES];
extern const int kbdWindowOffset[NUM_IMDCT_SIZES];
extern const unsigned char bitrevtab[17 + 129];
extern const int bitrevtabOffset[NUM_IMDCT_SIZES];
#ifdef HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT
/* trigtabs_fltgen.c */
extern int cos4sin4tab[128 + 1024];
extern int cos1sin1tab[514];
extern int sinWindow[128 + 1024];
extern int kbdWindow[128 + 1024];
extern int twidTabEven[4*6 + 16*6 + 64*6];
extern int twidTabOdd[8*6 + 32*6 + 128*6];
#else
/* trigtabs.c */
extern const int cos4sin4tab[128 + 1024];
extern const int cos1sin1tab[514];
extern const int sinWindow[128 + 1024];
extern const int kbdWindow[128 + 1024];
extern const int twidTabEven[4*6 + 16*6 + 64*6];
extern const int twidTabOdd[8*6 + 32*6 + 128*6];
#endif
#endif /* _CODER_H */

View File

@@ -1,337 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: dct4.c,v 1.1 2005/02/26 01:47:34 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* dct4.c - optimized DCT-IV
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
static const int nmdctTab[NUM_IMDCT_SIZES] PROGMEM = {128, 1024};
static const int postSkip[NUM_IMDCT_SIZES] PROGMEM = {15, 1};
/**************************************************************************************
* Function: PreMultiply
*
* Description: pre-twiddle stage of DCT4
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out, gains 5 (short) or 8 (long) frac bits
* i.e. gains 2-7= -5 int bits (short) or 2-10 = -8 int bits (long)
* normalization by -1/N is rolled into tables here (see trigtabs.c)
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
static void PreMultiply(int tabidx, int *zbuf1)
{
int i, nmdct, ar1, ai1, ar2, ai2, z1, z2;
int t, cms2, cps2a, sin2a, cps2b, sin2b;
int *zbuf2;
const int *csptr;
nmdct = nmdctTab[tabidx];
zbuf2 = zbuf1 + nmdct - 1;
csptr = cos4sin4tab + cos4sin4tabOffset[tabidx];
/* whole thing should fit in registers - verify that compiler does this */
for (i = nmdct >> 2; i != 0; i--) {
/* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin) */
cps2a = *csptr++;
sin2a = *csptr++;
cps2b = *csptr++;
sin2b = *csptr++;
ar1 = *(zbuf1 + 0);
ai2 = *(zbuf1 + 1);
ai1 = *(zbuf2 + 0);
ar2 = *(zbuf2 - 1);
/* gain 2 ints bit from MULSHIFT32 by Q30, but drop 7 or 10 int bits from table scaling of 1/M
* max per-sample gain (ignoring implicit scaling) = MAX(sin(angle)+cos(angle)) = 1.414
* i.e. gain 1 GB since worst case is sin(angle) = cos(angle) = 0.707 (Q30), gain 2 from
* extra sign bits, and eat one in adding
*/
t = MULSHIFT32(sin2a, ar1 + ai1);
z2 = MULSHIFT32(cps2a, ai1) - t;
cms2 = cps2a - 2*sin2a;
z1 = MULSHIFT32(cms2, ar1) + t;
*zbuf1++ = z1; /* cos*ar1 + sin*ai1 */
*zbuf1++ = z2; /* cos*ai1 - sin*ar1 */
t = MULSHIFT32(sin2b, ar2 + ai2);
z2 = MULSHIFT32(cps2b, ai2) - t;
cms2 = cps2b - 2*sin2b;
z1 = MULSHIFT32(cms2, ar2) + t;
*zbuf2-- = z2; /* cos*ai2 - sin*ar2 */
*zbuf2-- = z1; /* cos*ar2 + sin*ai2 */
}
}
/**************************************************************************************
* Function: PostMultiply
*
* Description: post-twiddle stage of DCT4
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out - gains 2 int bits
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
static void PostMultiply(int tabidx, int *fft1)
{
int i, nmdct, ar1, ai1, ar2, ai2, skipFactor;
int t, cms2, cps2, sin2;
int *fft2;
const int *csptr;
nmdct = nmdctTab[tabidx];
csptr = cos1sin1tab;
skipFactor = postSkip[tabidx];
fft2 = fft1 + nmdct - 1;
/* load coeffs for first pass
* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin)
*/
cps2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
cms2 = cps2 - 2*sin2;
for (i = nmdct >> 2; i != 0; i--) {
ar1 = *(fft1 + 0);
ai1 = *(fft1 + 1);
ar2 = *(fft2 - 1);
ai2 = *(fft2 + 0);
/* gain 2 ints bit from MULSHIFT32 by Q30
* max per-sample gain = MAX(sin(angle)+cos(angle)) = 1.414
* i.e. gain 1 GB since worst case is sin(angle) = cos(angle) = 0.707 (Q30), gain 2 from
* extra sign bits, and eat one in adding
*/
t = MULSHIFT32(sin2, ar1 + ai1);
*fft2-- = t - MULSHIFT32(cps2, ai1); /* sin*ar1 - cos*ai1 */
*fft1++ = t + MULSHIFT32(cms2, ar1); /* cos*ar1 + sin*ai1 */
cps2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
ai2 = -ai2;
t = MULSHIFT32(sin2, ar2 + ai2);
*fft2-- = t - MULSHIFT32(cps2, ai2); /* sin*ar1 - cos*ai1 */
cms2 = cps2 - 2*sin2;
*fft1++ = t + MULSHIFT32(cms2, ar2); /* cos*ar1 + sin*ai1 */
}
}
/**************************************************************************************
* Function: PreMultiplyRescale
*
* Description: pre-twiddle stage of DCT4, with rescaling for extra guard bits
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
* number of guard bits to add to input before processing
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: see notes on PreMultiply(), above
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void PreMultiplyRescale(int tabidx, int *zbuf1, int es)
{
int i, nmdct, ar1, ai1, ar2, ai2, z1, z2;
int t, cms2, cps2a, sin2a, cps2b, sin2b;
int *zbuf2;
const int *csptr;
nmdct = nmdctTab[tabidx];
zbuf2 = zbuf1 + nmdct - 1;
csptr = cos4sin4tab + cos4sin4tabOffset[tabidx];
/* whole thing should fit in registers - verify that compiler does this */
for (i = nmdct >> 2; i != 0; i--) {
/* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin) */
cps2a = *csptr++;
sin2a = *csptr++;
cps2b = *csptr++;
sin2b = *csptr++;
ar1 = *(zbuf1 + 0) >> es;
ai1 = *(zbuf2 + 0) >> es;
ai2 = *(zbuf1 + 1) >> es;
t = MULSHIFT32(sin2a, ar1 + ai1);
z2 = MULSHIFT32(cps2a, ai1) - t;
cms2 = cps2a - 2*sin2a;
z1 = MULSHIFT32(cms2, ar1) + t;
*zbuf1++ = z1;
*zbuf1++ = z2;
ar2 = *(zbuf2 - 1) >> es; /* do here to free up register used for es */
t = MULSHIFT32(sin2b, ar2 + ai2);
z2 = MULSHIFT32(cps2b, ai2) - t;
cms2 = cps2b - 2*sin2b;
z1 = MULSHIFT32(cms2, ar2) + t;
*zbuf2-- = z2;
*zbuf2-- = z1;
}
}
/**************************************************************************************
* Function: PostMultiplyRescale
*
* Description: post-twiddle stage of DCT4, with rescaling for extra guard bits
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
* number of guard bits to remove from output
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: clips output to [-2^30, 2^30 - 1], guaranteeing at least 1 guard bit
* see notes on PostMultiply(), above
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void PostMultiplyRescale(int tabidx, int *fft1, int es)
{
int i, nmdct, ar1, ai1, ar2, ai2, skipFactor, z;
int t, cs2, sin2;
int *fft2;
const int *csptr;
nmdct = nmdctTab[tabidx];
csptr = cos1sin1tab;
skipFactor = postSkip[tabidx];
fft2 = fft1 + nmdct - 1;
/* load coeffs for first pass
* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin)
*/
cs2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
for (i = nmdct >> 2; i != 0; i--) {
ar1 = *(fft1 + 0);
ai1 = *(fft1 + 1);
ai2 = *(fft2 + 0);
t = MULSHIFT32(sin2, ar1 + ai1);
z = t - MULSHIFT32(cs2, ai1);
CLIP_2N_SHIFT(z, es);
*fft2-- = z;
cs2 -= 2*sin2;
z = t + MULSHIFT32(cs2, ar1);
CLIP_2N_SHIFT(z, es);
*fft1++ = z;
cs2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
ar2 = *fft2;
ai2 = -ai2;
t = MULSHIFT32(sin2, ar2 + ai2);
z = t - MULSHIFT32(cs2, ai2);
CLIP_2N_SHIFT(z, es);
*fft2-- = z;
cs2 -= 2*sin2;
z = t + MULSHIFT32(cs2, ar2);
CLIP_2N_SHIFT(z, es);
*fft1++ = z;
cs2 += 2*sin2;
}
}
/**************************************************************************************
* Function: DCT4
*
* Description: type-IV DCT
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
* number of guard bits in the input buffer
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: operates in-place
* if number of guard bits in input is < GBITS_IN_DCT4, the input is
* scaled (>>) before the DCT4 and rescaled (<<, with clipping) after
* the DCT4 (rare)
* the output has FBITS_LOST_DCT4 fewer fraction bits than the input
* the output will always have at least 1 guard bit (GBITS_IN_DCT4 >= 4)
* int bits gained per stage (PreMul + FFT + PostMul)
* short blocks = (-5 + 4 + 2) = 1 total
* long blocks = (-8 + 7 + 2) = 1 total
**************************************************************************************/
void DCT4(int tabidx, int *coef, int gb)
{
int es;
/* fast in-place DCT-IV - adds guard bits if necessary */
if (gb < GBITS_IN_DCT4) {
es = GBITS_IN_DCT4 - gb;
PreMultiplyRescale(tabidx, coef, es);
R4FFT(tabidx, coef);
PostMultiplyRescale(tabidx, coef, es);
} else {
PreMultiply(tabidx, coef);
R4FFT(tabidx, coef);
PostMultiply(tabidx, coef);
}
}

View File

@@ -1,425 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: decelmnt.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* decelmnt.c - syntactic element decoding
**************************************************************************************/
#include "coder.h"
/**************************************************************************************
* Function: DecodeSingleChannelElement
*
* Description: decode one SCE
*
* Inputs: BitStreamInfo struct pointing to start of SCE (14496-3, table 4.4.4)
*
* Outputs: updated element instance tag
*
* Return: 0 if successful, -1 if error
*
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
**************************************************************************************/
static int DecodeSingleChannelElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
/* read instance tag */
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
return 0;
}
/**************************************************************************************
* Function: DecodeChannelPairElement
*
* Description: decode one CPE
*
* Inputs: BitStreamInfo struct pointing to start of CPE (14496-3, table 4.4.5)
*
* Outputs: updated element instance tag
* updated commonWin
* updated ICS info, if commonWin == 1
* updated mid-side stereo info, if commonWin == 1
*
* Return: 0 if successful, -1 if error
*
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
**************************************************************************************/
static int DecodeChannelPairElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
int sfb, gp, maskOffset;
unsigned char currBit, *maskPtr;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = psi->icsInfo;
/* read instance tag */
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
/* read common window flag and mid-side info (if present)
* store msMask bits in psi->msMaskBits[] as follows:
* long blocks - pack bits for each SFB in range [0, maxSFB) starting with lsb of msMaskBits[0]
* short blocks - pack bits for each SFB in range [0, maxSFB), for each group [0, 7]
* msMaskPresent = 0 means no M/S coding
* = 1 means psi->msMaskBits contains 1 bit per SFB to toggle M/S coding
* = 2 means all SFB's are M/S coded (so psi->msMaskBits is not needed)
*/
psi->commonWin = GetBits(bsi, 1);
if (psi->commonWin) {
DecodeICSInfo(bsi, icsInfo, psi->sampRateIdx);
psi->msMaskPresent = GetBits(bsi, 2);
if (psi->msMaskPresent == 1) {
maskPtr = psi->msMaskBits;
*maskPtr = 0;
maskOffset = 0;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
currBit = (unsigned char)GetBits(bsi, 1);
*maskPtr |= currBit << maskOffset;
if (++maskOffset == 8) {
maskPtr++;
*maskPtr = 0;
maskOffset = 0;
}
}
}
}
}
return 0;
}
/**************************************************************************************
* Function: DecodeLFEChannelElement
*
* Description: decode one LFE
*
* Inputs: BitStreamInfo struct pointing to start of LFE (14496-3, table 4.4.9)
*
* Outputs: updated element instance tag
*
* Return: 0 if successful, -1 if error
*
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
**************************************************************************************/
static int DecodeLFEChannelElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
/* read instance tag */
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
return 0;
}
/**************************************************************************************
* Function: DecodeDataStreamElement
*
* Description: decode one DSE
*
* Inputs: BitStreamInfo struct pointing to start of DSE (14496-3, table 4.4.10)
*
* Outputs: updated element instance tag
* filled in data stream buffer
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
static int DecodeDataStreamElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
unsigned int byteAlign, dataCount;
unsigned char *dataBuf;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
byteAlign = GetBits(bsi, 1);
dataCount = GetBits(bsi, 8);
if (dataCount == 255)
dataCount += GetBits(bsi, 8);
if (byteAlign)
ByteAlignBitstream(bsi);
psi->dataCount = dataCount;
dataBuf = psi->dataBuf;
while (dataCount--)
*dataBuf++ = GetBits(bsi, 8);
return 0;
}
/**************************************************************************************
* Function: DecodeProgramConfigElement
*
* Description: decode one PCE
*
* Inputs: BitStreamInfo struct pointing to start of PCE (14496-3, table 4.4.2)
*
* Outputs: filled-in ProgConfigElement struct
* updated BitStreamInfo struct
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: #define KEEP_PCE_COMMENTS to save the comment field of the PCE
* (otherwise we just skip it in the bitstream, to save memory)
**************************************************************************************/
int DecodeProgramConfigElement(ProgConfigElement *pce, BitStreamInfo *bsi)
{
int i;
pce->elemInstTag = GetBits(bsi, 4);
pce->profile = GetBits(bsi, 2);
pce->sampRateIdx = GetBits(bsi, 4);
pce->numFCE = GetBits(bsi, 4);
pce->numSCE = GetBits(bsi, 4);
pce->numBCE = GetBits(bsi, 4);
pce->numLCE = GetBits(bsi, 2);
pce->numADE = GetBits(bsi, 3);
pce->numCCE = GetBits(bsi, 4);
pce->monoMixdown = GetBits(bsi, 1) << 4; /* present flag */
if (pce->monoMixdown)
pce->monoMixdown |= GetBits(bsi, 4); /* element number */
pce->stereoMixdown = GetBits(bsi, 1) << 4; /* present flag */
if (pce->stereoMixdown)
pce->stereoMixdown |= GetBits(bsi, 4); /* element number */
pce->matrixMixdown = GetBits(bsi, 1) << 4; /* present flag */
if (pce->matrixMixdown) {
pce->matrixMixdown |= GetBits(bsi, 2) << 1; /* index */
pce->matrixMixdown |= GetBits(bsi, 1); /* pseudo-surround enable */
}
for (i = 0; i < pce->numFCE; i++) {
pce->fce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
pce->fce[i] |= GetBits(bsi, 4); /* tag select */
}
for (i = 0; i < pce->numSCE; i++) {
pce->sce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
pce->sce[i] |= GetBits(bsi, 4); /* tag select */
}
for (i = 0; i < pce->numBCE; i++) {
pce->bce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
pce->bce[i] |= GetBits(bsi, 4); /* tag select */
}
for (i = 0; i < pce->numLCE; i++)
pce->lce[i] = GetBits(bsi, 4); /* tag select */
for (i = 0; i < pce->numADE; i++)
pce->ade[i] = GetBits(bsi, 4); /* tag select */
for (i = 0; i < pce->numCCE; i++) {
pce->cce[i] = GetBits(bsi, 1) << 4; /* independent/dependent flag */
pce->cce[i] |= GetBits(bsi, 4); /* tag select */
}
ByteAlignBitstream(bsi);
#ifdef KEEP_PCE_COMMENTS
pce->commentBytes = GetBits(bsi, 8);
for (i = 0; i < pce->commentBytes; i++)
pce->commentField[i] = GetBits(bsi, 8);
#else
/* eat comment bytes and throw away */
i = GetBits(bsi, 8);
while (i--)
GetBits(bsi, 8);
#endif
return 0;
}
/**************************************************************************************
* Function: DecodeFillElement
*
* Description: decode one fill element
*
* Inputs: BitStreamInfo struct pointing to start of fill element
* (14496-3, table 4.4.11)
*
* Outputs: updated element instance tag
* unpacked extension payload
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
static int DecodeFillElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
unsigned int fillCount;
unsigned char *fillBuf;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
fillCount = GetBits(bsi, 4);
if (fillCount == 15)
fillCount += (GetBits(bsi, 8) - 1);
psi->fillCount = fillCount;
fillBuf = psi->fillBuf;
while (fillCount--)
*fillBuf++ = GetBits(bsi, 8);
aacDecInfo->currInstTag = -1; /* fill elements don't have instance tag */
aacDecInfo->fillExtType = 0;
#ifdef AAC_ENABLE_SBR
/* check for SBR
* aacDecInfo->sbrEnabled is sticky (reset each raw_data_block), so for multichannel
* need to verify that all SCE/CPE/ICCE have valid SBR fill element following, and
* must upsample by 2 for LFE
*/
if (psi->fillCount > 0) {
aacDecInfo->fillExtType = (int)((psi->fillBuf[0] >> 4) & 0x0f);
if (aacDecInfo->fillExtType == EXT_SBR_DATA || aacDecInfo->fillExtType == EXT_SBR_DATA_CRC)
aacDecInfo->sbrEnabled = 1;
}
#endif
aacDecInfo->fillBuf = psi->fillBuf;
aacDecInfo->fillCount = psi->fillCount;
return 0;
}
/**************************************************************************************
* Function: DecodeNextElement
*
* Description: decode next syntactic element in AAC frame
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer containing next element
* pointer to bit offset
* pointer to number of valid bits remaining in buf
*
* Outputs: type of element decoded (aacDecInfo->currBlockID)
* type of element decoded last time (aacDecInfo->prevBlockID)
* updated aacDecInfo state, depending on which element was decoded
* updated buffer pointer
* updated bit offset
* updated number of available bits
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int DecodeNextElement(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail)
{
int err, bitsUsed;
PSInfoBase *psi;
BitStreamInfo bsi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* init bitstream reader */
SetBitstreamPointer(&bsi, (*bitsAvail + 7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
/* read element ID (save last ID for SBR purposes) */
aacDecInfo->prevBlockID = aacDecInfo->currBlockID;
aacDecInfo->currBlockID = GetBits(&bsi, NUM_SYN_ID_BITS);
/* set defaults (could be overwritten by DecodeXXXElement(), depending on currBlockID) */
psi->commonWin = 0;
err = 0;
switch (aacDecInfo->currBlockID) {
case AAC_ID_SCE:
err = DecodeSingleChannelElement(aacDecInfo, &bsi);
break;
case AAC_ID_CPE:
err = DecodeChannelPairElement(aacDecInfo, &bsi);
break;
case AAC_ID_CCE:
/* TODO - implement CCE decoding */
break;
case AAC_ID_LFE:
err = DecodeLFEChannelElement(aacDecInfo, &bsi);
break;
case AAC_ID_DSE:
err = DecodeDataStreamElement(aacDecInfo, &bsi);
break;
case AAC_ID_PCE:
err = DecodeProgramConfigElement(psi->pce + 0, &bsi);
break;
case AAC_ID_FIL:
err = DecodeFillElement(aacDecInfo, &bsi);
break;
case AAC_ID_END:
break;
}
if (err)
return ERR_AAC_SYNTAX_ELEMENT;
/* update bitstream reader */
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
*bitsAvail -= bitsUsed;
if (*bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
return ERR_AAC_NONE;
}

View File

@@ -1,373 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: dequant.c,v 1.2 2005/05/20 18:05:41 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* dequant.c - transform coefficient dequantization and short-block deinterleaving
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define SF_OFFSET 100
/* pow(2, i/4.0) for i = [0,1,2,3], format = Q30 */
static const int pow14[4] PROGMEM = {
0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65
};
/* pow(2, i/4.0) * pow(j, 4.0/3.0) for i = [0,1,2,3], j = [0,1,2,...,15]
* format = Q28 for j = [0-3], Q25 for j = [4-15]
*/
static const int pow43_14[4][16] PROGMEM = {
{
0x00000000, 0x10000000, 0x285145f3, 0x453a5cdb, /* Q28 */
0x0cb2ff53, 0x111989d6, 0x15ce31c8, 0x1ac7f203, /* Q25 */
0x20000000, 0x257106b9, 0x2b16b4a3, 0x30ed74b4, /* Q25 */
0x36f23fa5, 0x3d227bd3, 0x437be656, 0x49fc823c, /* Q25 */
},
{
0x00000000, 0x1306fe0a, 0x2ff221af, 0x52538f52,
0x0f1a1bf4, 0x1455ccc2, 0x19ee62a8, 0x1fd92396,
0x260dfc14, 0x2c8694d8, 0x333dcb29, 0x3a2f5c7a,
0x4157aed5, 0x48b3aaa3, 0x50409f76, 0x57fc3010,
},
{
0x00000000, 0x16a09e66, 0x39047c0f, 0x61e734aa,
0x11f59ac4, 0x182ec633, 0x1ed66a45, 0x25dfc55a,
0x2d413ccd, 0x34f3462d, 0x3cefc603, 0x4531ab69,
0x4db4adf8, 0x56752054, 0x5f6fcfcd, 0x68a1eca1,
},
{
0x00000000, 0x1ae89f99, 0x43ce3e4b, 0x746d57b2,
0x155b8109, 0x1cc21cdc, 0x24ac1839, 0x2d0a479e,
0x35d13f33, 0x3ef80748, 0x48775c93, 0x524938cd,
0x5c68841d, 0x66d0df0a, 0x717e7bfe, 0x7c6e0305,
},
};
/* pow(j, 4.0 / 3.0) for j = [16,17,18,...,63], format = Q23 */
static const int pow43[48] PROGMEM = {
0x1428a2fa, 0x15db1bd6, 0x1796302c, 0x19598d85,
0x1b24e8bb, 0x1cf7fcfa, 0x1ed28af2, 0x20b4582a,
0x229d2e6e, 0x248cdb55, 0x26832fda, 0x28800000,
0x2a832287, 0x2c8c70a8, 0x2e9bc5d8, 0x30b0ff99,
0x32cbfd4a, 0x34eca001, 0x3712ca62, 0x393e6088,
0x3b6f47e0, 0x3da56717, 0x3fe0a5fc, 0x4220ed72,
0x44662758, 0x46b03e7c, 0x48ff1e87, 0x4b52b3f3,
0x4daaebfd, 0x5007b497, 0x5268fc62, 0x54ceb29c,
0x5738c721, 0x59a72a59, 0x5c19cd35, 0x5e90a129,
0x610b9821, 0x638aa47f, 0x660db90f, 0x6894c90b,
0x6b1fc80c, 0x6daeaa0d, 0x70416360, 0x72d7e8b0,
0x75722ef9, 0x78102b85, 0x7ab1d3ec, 0x7d571e09,
};
/* sqrt(0.5), format = Q31 */
#define SQRTHALF 0x5a82799a
/* Minimax polynomial approximation to pow(x, 4/3), over the range
* poly43lo: x = [0.5, 0.7071]
* poly43hi: x = [0.7071, 1.0]
*
* Relative error < 1E-7
* Coefs are scaled by 4, 2, 1, 0.5, 0.25
*/
//fb
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
static const int poly43lo[5] PROGMEM = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 };
static const int poly43hi[5] PROGMEM = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 };
#pragma GCC diagnostic pop
/* pow2exp[i] = pow(2, i*4/3) exponent */
static const int pow2exp[8] PROGMEM = { 14, 13, 11, 10, 9, 7, 6, 5 };
/* pow2exp[i] = pow(2, i*4/3) fraction */
static const int pow2frac[8] PROGMEM = {
0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94,
0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6
};
/**************************************************************************************
* Function: DequantBlock
*
* Description: dequantize one block of transform coefficients (in-place)
*
* Inputs: quantized transform coefficients, range = [0, 8191]
* number of samples to dequantize
* scalefactor for this block of data, range = [0, 256]
*
* Outputs: dequantized transform coefficients in Q(FBITS_OUT_DQ_OFF)
*
* Return: guard bit mask (OR of abs value of all dequantized coefs)
*
* Notes: applies dequant formula y = pow(x, 4.0/3.0) * pow(2, (scale - 100)/4.0)
* * pow(2, FBITS_OUT_DQ_OFF)
* clips outputs to Q(FBITS_OUT_DQ_OFF)
* output has no minimum number of guard bits
**************************************************************************************/
static int DequantBlock(int *inbuf, int nSamps, int scale)
{
int iSamp, scalef, scalei, x, y, gbMask, shift, tab4[4];
const int *tab16, *coef;
if (nSamps <= 0)
return 0;
scale -= SF_OFFSET; /* new range = [-100, 156] */
/* with two's complement numbers, scalei/scalef factorization works for pos and neg values of scale:
* [+4...+7] >> 2 = +1, [ 0...+3] >> 2 = 0, [-4...-1] >> 2 = -1, [-8...-5] >> 2 = -2 ...
* (-1 & 0x3) = 3, (-2 & 0x3) = 2, (-3 & 0x3) = 1, (0 & 0x3) = 0
*
* Example: 2^(-5/4) = 2^(-1) * 2^(-1/4) = 2^-2 * 2^(3/4)
*/
tab16 = pow43_14[scale & 0x3];
scalef = pow14[scale & 0x3];
scalei = (scale >> 2) + FBITS_OUT_DQ_OFF;
/* cache first 4 values:
* tab16[j] = Q28 for j = [0,3]
* tab4[x] = x^(4.0/3.0) * 2^(0.25*scale), Q(FBITS_OUT_DQ_OFF)
*/
shift = 28 - scalei;
if (shift > 31) {
tab4[0] = tab4[1] = tab4[2] = tab4[3] = 0;
} else if (shift <= 0) {
shift = -shift;
if (shift > 31)
shift = 31;
for (x = 0; x < 4; x++) {
y = tab16[x];
if (y > (0x7fffffff >> shift))
y = 0x7fffffff; /* clip (rare) */
else
y <<= shift;
tab4[x] = y;
}
} else {
tab4[0] = 0;
tab4[1] = tab16[1] >> shift;
tab4[2] = tab16[2] >> shift;
tab4[3] = tab16[3] >> shift;
}
gbMask = 0;
do {
iSamp = *inbuf;
x = FASTABS(iSamp);
if (x < 4) {
y = tab4[x];
} else {
if (x < 16) {
/* result: y = Q25 (tab16 = Q25) */
y = tab16[x];
shift = 25 - scalei;
} else if (x < 64) {
/* result: y = Q21 (pow43tab[j] = Q23, scalef = Q30) */
y = pow43[x-16];
shift = 21 - scalei;
y = MULSHIFT32(y, scalef);
} else {
/* normalize to [0x40000000, 0x7fffffff]
* input x = [64, 8191] = [64, 2^13-1]
* ranges:
* shift = 7: 64 - 127
* shift = 6: 128 - 255
* shift = 5: 256 - 511
* shift = 4: 512 - 1023
* shift = 3: 1024 - 2047
* shift = 2: 2048 - 4095
* shift = 1: 4096 - 8191
*/
x <<= 17;
shift = 0;
if (x < 0x08000000)
x <<= 4, shift += 4;
if (x < 0x20000000)
x <<= 2, shift += 2;
if (x < 0x40000000)
x <<= 1, shift += 1;
coef = (x < SQRTHALF) ? poly43lo : poly43hi;
/* polynomial */
y = coef[0];
y = MULSHIFT32(y, x) + coef[1];
y = MULSHIFT32(y, x) + coef[2];
y = MULSHIFT32(y, x) + coef[3];
y = MULSHIFT32(y, x) + coef[4];
y = MULSHIFT32(y, pow2frac[shift]) << 3;
/* fractional scale
* result: y = Q21 (pow43tab[j] = Q23, scalef = Q30)
*/
y = MULSHIFT32(y, scalef); /* now y is Q24 */
shift = 24 - scalei - pow2exp[shift];
}
/* integer scale */
if (shift <= 0) {
shift = -shift;
if (shift > 31)
shift = 31;
if (y > (0x7fffffff >> shift))
y = 0x7fffffff; /* clip (rare) */
else
y <<= shift;
} else {
if (shift > 31)
shift = 31;
y >>= shift;
}
}
/* sign and store (gbMask used to count GB's) */
gbMask |= y;
/* apply sign */
iSamp >>= 31;
y ^= iSamp;
y -= iSamp;
*inbuf++ = y;
} while (--nSamps);
return gbMask;
}
/**************************************************************************************
* Function: Dequantize
*
* Description: dequantize all transform coefficients for one channel
*
* Inputs: valid AACDecInfo struct (including unpacked, quantized coefficients)
* index of current channel
*
* Outputs: dequantized coefficients, including short-block deinterleaving
* flags indicating if intensity and/or PNS is active
* minimum guard bit count for dequantized coefficients
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int Dequantize(AACDecInfo *aacDecInfo, int ch)
{
int gp, cb, sfb, win, width, nSamps, gbMask;
int *coef;
const int /*short*/ *sfbTab;
unsigned char *sfbCodeBook;
short *scaleFactors;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
if (icsInfo->winSequence == 2) {
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
nSamps = NSAMPS_SHORT;
} else {
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
nSamps = NSAMPS_LONG;
}
coef = psi->coef[ch];
sfbCodeBook = psi->sfbCodeBook[ch];
scaleFactors = psi->scaleFactors[ch];
psi->intensityUsed[ch] = 0;
psi->pnsUsed[ch] = 0;
gbMask = 0;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
/* dequantize one scalefactor band (not necessary if codebook is intensity or PNS)
* for zero codebook, still run dequantizer in case non-zero pulse data was added
*/
cb = (int)(sfbCodeBook[sfb]);
width = sfbTab[sfb+1] - sfbTab[sfb];
if (cb >= 0 && cb <= 11)
gbMask |= DequantBlock(coef, width, scaleFactors[sfb]);
else if (cb == 13)
psi->pnsUsed[ch] = 1;
else if (cb == 14 || cb == 15)
psi->intensityUsed[ch] = 1; /* should only happen if ch == 1 */
coef += width;
}
coef += (nSamps - sfbTab[icsInfo->maxSFB]);
}
sfbCodeBook += icsInfo->maxSFB;
scaleFactors += icsInfo->maxSFB;
}
aacDecInfo->pnsUsed |= psi->pnsUsed[ch]; /* set flag if PNS used for any channel */
/* calculate number of guard bits in dequantized data */
psi->gbCurrent[ch] = CLZ(gbMask) - 1;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: DeinterleaveShortBlocks
*
* Description: deinterleave transform coefficients in short blocks for one channel
*
* Inputs: valid AACDecInfo struct (including unpacked, quantized coefficients)
* index of current channel
*
* Outputs: deinterleaved coefficients (window groups into 8 separate windows)
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: only necessary if deinterleaving not part of Huffman decoding
**************************************************************************************/
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch)
{
(void)aacDecInfo;
(void)ch;
/* not used for this implementation - short block deinterleaving performed during Huffman decoding */
return ERR_AAC_NONE;
}

View File

@@ -1,393 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: fft.c,v 1.1 2005/02/26 01:47:34 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* fft.c - Ken's optimized radix-4 DIT FFT, optional radix-8 first pass for odd log2(N)
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define NUM_FFT_SIZES 2
static const int nfftTab[NUM_FFT_SIZES] PROGMEM ={64, 512};
static const int nfftlog2Tab[NUM_FFT_SIZES] PROGMEM = {6, 9};
#define SQRT1_2 0x5a82799a /* sqrt(1/2) in Q31 */
#define swapcplx(p0,p1) \
t = p0; t1 = *(&(p0)+1); p0 = p1; *(&(p0)+1) = *(&(p1)+1); p1 = t; *(&(p1)+1) = t1
/**************************************************************************************
* Function: BitReverse
*
* Description: Ken's fast in-place bit reverse, using super-small table
*
* Inputs: buffer of samples
* table index (for transform size)
*
* Outputs: bit-reversed samples in same buffer
*
* Return: none
**************************************************************************************/
/*__attribute__ ((section (".data"))) */ static void BitReverse(int *inout, int tabidx)
{
int *part0, *part1;
int a,b, t,t1;
const unsigned char* tab = bitrevtab + bitrevtabOffset[tabidx];
int nbits = nfftlog2Tab[tabidx];
part0 = inout;
part1 = inout + (1 << nbits);
while ((a = pgm_read_byte(tab++)) != 0) {
b = pgm_read_byte(tab++);
swapcplx(part0[4*a+0], part0[4*b+0]); /* 0xxx0 <-> 0yyy0 */
swapcplx(part0[4*a+2], part1[4*b+0]); /* 0xxx1 <-> 1yyy0 */
swapcplx(part1[4*a+0], part0[4*b+2]); /* 1xxx0 <-> 0yyy1 */
swapcplx(part1[4*a+2], part1[4*b+2]); /* 1xxx1 <-> 1yyy1 */
}
do {
swapcplx(part0[4*a+2], part1[4*a+0]); /* 0xxx1 <-> 1xxx0 */
} while ((a = pgm_read_byte(tab++)) != 0);
}
/**************************************************************************************
* Function: R4FirstPass
*
* Description: radix-4 trivial pass for decimation-in-time FFT
*
* Inputs: buffer of (bit-reversed) samples
* number of R4 butterflies per group (i.e. nfft / 4)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 2 guard bits, gains no integer bits,
* guard bits out = guard bits in - 2
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void R4FirstPass(int *x, int bg)
{
int ar, ai, br, bi, cr, ci, dr, di;
for (; bg != 0; bg--) {
ar = x[0] + x[2];
br = x[0] - x[2];
ai = x[1] + x[3];
bi = x[1] - x[3];
cr = x[4] + x[6];
dr = x[4] - x[6];
ci = x[5] + x[7];
di = x[5] - x[7];
/* max per-sample gain = 4.0 (adding 4 inputs together) */
x[0] = ar + cr;
x[4] = ar - cr;
x[1] = ai + ci;
x[5] = ai - ci;
x[2] = br + di;
x[6] = br - di;
x[3] = bi - dr;
x[7] = bi + dr;
x += 8;
}
}
/**************************************************************************************
* Function: R8FirstPass
*
* Description: radix-8 trivial pass for decimation-in-time FFT
*
* Inputs: buffer of (bit-reversed) samples
* number of R8 butterflies per group (i.e. nfft / 8)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 3 guard bits, gains 1 integer bit
* guard bits out = guard bits in - 3 (if inputs are full scale)
* or guard bits in - 2 (if inputs bounded to +/- sqrt(2)/2)
* see scaling comments in code
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void R8FirstPass(int *x, int bg)
{
int ar, ai, br, bi, cr, ci, dr, di;
int sr, si, tr, ti, ur, ui, vr, vi;
int wr, wi, xr, xi, yr, yi, zr, zi;
for (; bg != 0; bg--) {
ar = x[0] + x[2];
br = x[0] - x[2];
ai = x[1] + x[3];
bi = x[1] - x[3];
cr = x[4] + x[6];
dr = x[4] - x[6];
ci = x[5] + x[7];
di = x[5] - x[7];
sr = ar + cr;
ur = ar - cr;
si = ai + ci;
ui = ai - ci;
tr = br - di;
vr = br + di;
ti = bi + dr;
vi = bi - dr;
ar = x[ 8] + x[10];
br = x[ 8] - x[10];
ai = x[ 9] + x[11];
bi = x[ 9] - x[11];
cr = x[12] + x[14];
dr = x[12] - x[14];
ci = x[13] + x[15];
di = x[13] - x[15];
/* max gain of wr/wi/yr/yi vs input = 2
* (sum of 4 samples >> 1)
*/
wr = (ar + cr) >> 1;
yr = (ar - cr) >> 1;
wi = (ai + ci) >> 1;
yi = (ai - ci) >> 1;
/* max gain of output vs input = 4
* (sum of 4 samples >> 1 + sum of 4 samples >> 1)
*/
x[ 0] = (sr >> 1) + wr;
x[ 8] = (sr >> 1) - wr;
x[ 1] = (si >> 1) + wi;
x[ 9] = (si >> 1) - wi;
x[ 4] = (ur >> 1) + yi;
x[12] = (ur >> 1) - yi;
x[ 5] = (ui >> 1) - yr;
x[13] = (ui >> 1) + yr;
ar = br - di;
cr = br + di;
ai = bi + dr;
ci = bi - dr;
/* max gain of xr/xi/zr/zi vs input = 4*sqrt(2)/2 = 2*sqrt(2)
* (sum of 8 samples, multiply by sqrt(2)/2, implicit >> 1 from Q31)
*/
xr = MULSHIFT32(SQRT1_2, ar - ai);
xi = MULSHIFT32(SQRT1_2, ar + ai);
zr = MULSHIFT32(SQRT1_2, cr - ci);
zi = MULSHIFT32(SQRT1_2, cr + ci);
/* max gain of output vs input = (2 + 2*sqrt(2) ~= 4.83)
* (sum of 4 samples >> 1, plus xr/xi/zr/zi with gain of 2*sqrt(2))
* in absolute terms, we have max gain of appx 9.656 (4 + 0.707*8)
* but we also gain 1 int bit (from MULSHIFT32 or from explicit >> 1)
*/
x[ 6] = (tr >> 1) - xr;
x[14] = (tr >> 1) + xr;
x[ 7] = (ti >> 1) - xi;
x[15] = (ti >> 1) + xi;
x[ 2] = (vr >> 1) + zi;
x[10] = (vr >> 1) - zi;
x[ 3] = (vi >> 1) - zr;
x[11] = (vi >> 1) + zr;
x += 16;
}
}
/**************************************************************************************
* Function: R4Core
*
* Description: radix-4 pass for decimation-in-time FFT
*
* Inputs: buffer of samples
* number of R4 butterflies per group
* number of R4 groups per pass
* pointer to twiddle factors tables
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: gain 2 integer bits per pass (see scaling comments in code)
* min 1 GB in
* gbOut = gbIn - 1 (short block) or gbIn - 2 (long block)
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void R4Core(int *x, int bg, int gp, int *wtab)
{
int ar, ai, br, bi, cr, ci, dr, di, tr, ti;
int wd, ws, wi;
int i, j, step;
int *xptr, *wptr;
for (; bg != 0; gp <<= 2, bg >>= 2) {
step = 2*gp;
xptr = x;
/* max per-sample gain, per group < 1 + 3*sqrt(2) ~= 5.25 if inputs x are full-scale
* do 3 groups for long block, 2 groups for short block (gain 2 int bits per group)
*
* very conservative scaling:
* group 1: max gain = 5.25, int bits gained = 2, gb used = 1 (2^3 = 8)
* group 2: max gain = 5.25^2 = 27.6, int bits gained = 4, gb used = 1 (2^5 = 32)
* group 3: max gain = 5.25^3 = 144.7, int bits gained = 6, gb used = 2 (2^8 = 256)
*/
for (i = bg; i != 0; i--) {
wptr = wtab;
for (j = gp; j != 0; j--) {
ar = xptr[0];
ai = xptr[1];
xptr += step;
/* gain 2 int bits for br/bi, cr/ci, dr/di (MULSHIFT32 by Q30)
* gain 1 net GB
*/
ws = wptr[0];
wi = wptr[1];
br = xptr[0];
bi = xptr[1];
wd = ws + 2*wi;
tr = MULSHIFT32(wi, br + bi);
br = MULSHIFT32(wd, br) - tr; /* cos*br + sin*bi */
bi = MULSHIFT32(ws, bi) + tr; /* cos*bi - sin*br */
xptr += step;
ws = wptr[2];
wi = wptr[3];
cr = xptr[0];
ci = xptr[1];
wd = ws + 2*wi;
tr = MULSHIFT32(wi, cr + ci);
cr = MULSHIFT32(wd, cr) - tr;
ci = MULSHIFT32(ws, ci) + tr;
xptr += step;
ws = wptr[4];
wi = wptr[5];
dr = xptr[0];
di = xptr[1];
wd = ws + 2*wi;
tr = MULSHIFT32(wi, dr + di);
dr = MULSHIFT32(wd, dr) - tr;
di = MULSHIFT32(ws, di) + tr;
wptr += 6;
tr = ar;
ti = ai;
ar = (tr >> 2) - br;
ai = (ti >> 2) - bi;
br = (tr >> 2) + br;
bi = (ti >> 2) + bi;
tr = cr;
ti = ci;
cr = tr + dr;
ci = di - ti;
dr = tr - dr;
di = di + ti;
xptr[0] = ar + ci;
xptr[1] = ai + dr;
xptr -= step;
xptr[0] = br - cr;
xptr[1] = bi - di;
xptr -= step;
xptr[0] = ar - ci;
xptr[1] = ai - dr;
xptr -= step;
xptr[0] = br + cr;
xptr[1] = bi + di;
xptr += 2;
}
xptr += 3*step;
}
wtab += 3*step;
}
}
/**************************************************************************************
* Function: R4FFT
*
* Description: Ken's very fast in-place radix-4 decimation-in-time FFT
*
* Inputs: table index (for transform size)
* buffer of samples (non bit-reversed)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 5 guard bits in for nfft <= 512
* gbOut = gbIn - 4 (assuming input is from PreMultiply)
* gains log2(nfft) - 2 int bits total
* so gain 7 int bits (LONG), 4 int bits (SHORT)
**************************************************************************************/
void R4FFT(int tabidx, int *x)
{
int order = nfftlog2Tab[tabidx];
int nfft = nfftTab[tabidx];
/* decimation in time */
BitReverse(x, tabidx);
if (order & 0x1) {
/* long block: order = 9, nfft = 512 */
R8FirstPass(x, nfft >> 3); /* gain 1 int bit, lose 2 GB */
R4Core(x, nfft >> 5, 8, (int *)twidTabOdd); /* gain 6 int bits, lose 2 GB */
} else {
/* short block: order = 6, nfft = 64 */
R4FirstPass(x, nfft >> 2); /* gain 0 int bits, lose 2 GB */
R4Core(x, nfft >> 4, 4, (int *)twidTabEven); /* gain 4 int bits, lose 1 GB */
}
}

View File

@@ -1,496 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: filefmt.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* filefmt.c - ADIF and ADTS header decoding, raw block handling
**************************************************************************************/
#include "coder.h"
/**************************************************************************************
* Function: UnpackADTSHeader
*
* Description: parse the ADTS frame header and initialize decoder state
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer with complete ADTS frame header (byte aligned)
* header size = 7 bytes, plus 2 if CRC
*
* Outputs: filled in ADTS struct
* updated buffer pointer
* updated bit offset
* updated number of available bits
*
* Return: 0 if successful, error code (< 0) if error
*
* TODO: test CRC
* verify that fixed fields don't change between frames
**************************************************************************************/
int UnpackADTSHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail)
{
int bitsUsed;
PSInfoBase *psi;
BitStreamInfo bsi;
ADTSHeader *fhADTS;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
fhADTS = &(psi->fhADTS);
/* init bitstream reader */
SetBitstreamPointer(&bsi, (*bitsAvail + 7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
/* verify that first 12 bits of header are syncword */
if (GetBits(&bsi, 12) != 0x0fff) {
return ERR_AAC_INVALID_ADTS_HEADER;
}
/* fixed fields - should not change from frame to frame */
fhADTS->id = GetBits(&bsi, 1);
fhADTS->layer = GetBits(&bsi, 2);
fhADTS->protectBit = GetBits(&bsi, 1);
fhADTS->profile = GetBits(&bsi, 2);
fhADTS->sampRateIdx = GetBits(&bsi, 4);
fhADTS->privateBit = GetBits(&bsi, 1);
fhADTS->channelConfig = GetBits(&bsi, 3);
fhADTS->origCopy = GetBits(&bsi, 1);
fhADTS->home = GetBits(&bsi, 1);
/* variable fields - can change from frame to frame */
fhADTS->copyBit = GetBits(&bsi, 1);
fhADTS->copyStart = GetBits(&bsi, 1);
fhADTS->frameLength = GetBits(&bsi, 13);
fhADTS->bufferFull = GetBits(&bsi, 11);
fhADTS->numRawDataBlocks = GetBits(&bsi, 2) + 1;
/* note - MPEG4 spec, correction 1 changes how CRC is handled when protectBit == 0 and numRawDataBlocks > 1 */
if (fhADTS->protectBit == 0)
fhADTS->crcCheckWord = GetBits(&bsi, 16);
/* byte align */
ByteAlignBitstream(&bsi); /* should always be aligned anyway */
/* check validity of header */
if (fhADTS->layer != 0 || fhADTS->profile != AAC_PROFILE_LC ||
fhADTS->sampRateIdx >= NUM_SAMPLE_RATES || fhADTS->channelConfig >= NUM_DEF_CHAN_MAPS)
return ERR_AAC_INVALID_ADTS_HEADER;
#ifndef AAC_ENABLE_MPEG4
if (fhADTS->id != 1)
return ERR_AAC_MPEG4_UNSUPPORTED;
#endif
/* update codec info */
psi->sampRateIdx = fhADTS->sampRateIdx;
if (!psi->useImpChanMap)
psi->nChans = channelMapTab[fhADTS->channelConfig];
/* syntactic element fields will be read from bitstream for each element */
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
/* fill in user-accessible data (TODO - calc bitrate, handle tricky channel config cases) */
aacDecInfo->bitRate = 0;
aacDecInfo->nChans = psi->nChans;
aacDecInfo->sampRate = sampRateTab[psi->sampRateIdx];
aacDecInfo->profile = fhADTS->profile;
aacDecInfo->sbrEnabled = 0;
aacDecInfo->adtsBlocksLeft = fhADTS->numRawDataBlocks;
/* update bitstream reader */
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
*bitsAvail -= bitsUsed ;
if (*bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: GetADTSChannelMapping
*
* Description: determine the number of channels from implicit mapping rules
*
* Inputs: valid AACDecInfo struct
* pointer to start of raw_data_block
* bit offset
* bits available
*
* Outputs: updated number of channels
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: calculates total number of channels using rules in 14496-3, 4.5.1.2.1
* does not attempt to deduce speaker geometry
**************************************************************************************/
int GetADTSChannelMapping(AACDecInfo *aacDecInfo, unsigned char *buf, int bitOffset, int bitsAvail)
{
int ch, nChans, elementChans, err;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
nChans = 0;
do {
/* parse next syntactic element */
err = DecodeNextElement(aacDecInfo, &buf, &bitOffset, &bitsAvail);
if (err)
return err;
elementChans = elementNumChans[aacDecInfo->currBlockID];
nChans += elementChans;
for (ch = 0; ch < elementChans; ch++) {
err = DecodeNoiselessData(aacDecInfo, &buf, &bitOffset, &bitsAvail, ch);
if (err)
return err;
}
} while (aacDecInfo->currBlockID != AAC_ID_END);
if (nChans <= 0)
return ERR_AAC_CHANNEL_MAP;
/* update number of channels in codec state and user-accessible info structs */
psi->nChans = nChans;
aacDecInfo->nChans = psi->nChans;
psi->useImpChanMap = 1;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: GetNumChannelsADIF
*
* Description: get number of channels from program config elements in an ADIF file
*
* Inputs: array of filled-in program config element structures
* number of PCE's
*
* Outputs: none
*
* Return: total number of channels in file
* -1 if error (invalid number of PCE's or unsupported mode)
**************************************************************************************/
static int GetNumChannelsADIF(ProgConfigElement *fhPCE, int nPCE)
{
int i, j, nChans;
if (nPCE < 1 || nPCE > MAX_NUM_PCE_ADIF)
return -1;
nChans = 0;
for (i = 0; i < nPCE; i++) {
/* for now: only support LC, no channel coupling */
if (fhPCE[i].profile != AAC_PROFILE_LC || fhPCE[i].numCCE > 0)
return -1;
/* add up number of channels in all channel elements (assume all single-channel) */
nChans += fhPCE[i].numFCE;
nChans += fhPCE[i].numSCE;
nChans += fhPCE[i].numBCE;
nChans += fhPCE[i].numLCE;
/* add one more for every element which is a channel pair */
for (j = 0; j < fhPCE[i].numFCE; j++) {
if (CHAN_ELEM_IS_CPE(fhPCE[i].fce[j]))
nChans++;
}
for (j = 0; j < fhPCE[i].numSCE; j++) {
if (CHAN_ELEM_IS_CPE(fhPCE[i].sce[j]))
nChans++;
}
for (j = 0; j < fhPCE[i].numBCE; j++) {
if (CHAN_ELEM_IS_CPE(fhPCE[i].bce[j]))
nChans++;
}
}
return nChans;
}
/**************************************************************************************
* Function: GetSampleRateIdxADIF
*
* Description: get sampling rate index from program config elements in an ADIF file
*
* Inputs: array of filled-in program config element structures
* number of PCE's
*
* Outputs: none
*
* Return: sample rate of file
* -1 if error (invalid number of PCE's or sample rate mismatch)
**************************************************************************************/
static int GetSampleRateIdxADIF(ProgConfigElement *fhPCE, int nPCE)
{
int i, idx;
if (nPCE < 1 || nPCE > MAX_NUM_PCE_ADIF)
return -1;
/* make sure all PCE's have the same sample rate */
idx = fhPCE[0].sampRateIdx;
for (i = 1; i < nPCE; i++) {
if (fhPCE[i].sampRateIdx != idx)
return -1;
}
return idx;
}
/**************************************************************************************
* Function: UnpackADIFHeader
*
* Description: parse the ADIF file header and initialize decoder state
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer with complete ADIF header
* (starting at 'A' in 'ADIF' tag)
* pointer to bit offset
* pointer to number of valid bits remaining in inbuf
*
* Outputs: filled-in ADIF struct
* updated buffer pointer
* updated bit offset
* updated number of available bits
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int UnpackADIFHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail)
{
int i, bitsUsed;
PSInfoBase *psi;
BitStreamInfo bsi;
ADIFHeader *fhADIF;
ProgConfigElement *pce;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* init bitstream reader */
SetBitstreamPointer(&bsi, (*bitsAvail + 7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
/* unpack ADIF file header */
fhADIF = &(psi->fhADIF);
pce = psi->pce;
/* verify that first 32 bits of header are "ADIF" */
if (GetBits(&bsi, 8) != 'A' || GetBits(&bsi, 8) != 'D' || GetBits(&bsi, 8) != 'I' || GetBits(&bsi, 8) != 'F')
return ERR_AAC_INVALID_ADIF_HEADER;
/* read ADIF header fields */
fhADIF->copyBit = GetBits(&bsi, 1);
if (fhADIF->copyBit) {
for (i = 0; i < ADIF_COPYID_SIZE; i++)
fhADIF->copyID[i] = GetBits(&bsi, 8);
}
fhADIF->origCopy = GetBits(&bsi, 1);
fhADIF->home = GetBits(&bsi, 1);
fhADIF->bsType = GetBits(&bsi, 1);
fhADIF->bitRate = GetBits(&bsi, 23);
fhADIF->numPCE = GetBits(&bsi, 4) + 1; /* add 1 (so range = [1, 16]) */
if (fhADIF->bsType == 0)
fhADIF->bufferFull = GetBits(&bsi, 20);
/* parse all program config elements */
for (i = 0; i < fhADIF->numPCE; i++)
DecodeProgramConfigElement(pce + i, &bsi);
/* byte align */
ByteAlignBitstream(&bsi);
/* update codec info */
psi->nChans = GetNumChannelsADIF(pce, fhADIF->numPCE);
psi->sampRateIdx = GetSampleRateIdxADIF(pce, fhADIF->numPCE);
/* check validity of header */
if (psi->nChans < 0 || psi->sampRateIdx < 0 || psi->sampRateIdx >= NUM_SAMPLE_RATES)
return ERR_AAC_INVALID_ADIF_HEADER;
/* syntactic element fields will be read from bitstream for each element */
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
/* fill in user-accessible data */
aacDecInfo->bitRate = 0;
aacDecInfo->nChans = psi->nChans;
aacDecInfo->sampRate = sampRateTab[psi->sampRateIdx];
aacDecInfo->profile = pce[0].profile;
aacDecInfo->sbrEnabled = 0;
/* update bitstream reader */
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
*bitsAvail -= bitsUsed ;
if (*bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: SetRawBlockParams
*
* Description: set internal state variables for decoding a stream of raw data blocks
*
* Inputs: valid AACDecInfo struct
* flag indicating source of parameters (from previous headers or passed
* explicitly by caller)
* number of channels
* sample rate
* profile ID
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: if copyLast == 1, then psi->nChans, psi->sampRateIdx, and
* aacDecInfo->profile are not changed (it's assumed that we already
* set them, such as by a previous call to UnpackADTSHeader())
* if copyLast == 0, then the parameters we passed in are used instead
**************************************************************************************/
int SetRawBlockParams(AACDecInfo *aacDecInfo, int copyLast, int nChans, int sampRate, int profile)
{
int idx;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
if (!copyLast) {
aacDecInfo->profile = profile;
psi->nChans = nChans;
for (idx = 0; idx < NUM_SAMPLE_RATES; idx++) {
if (sampRate == sampRateTab[idx]) {
psi->sampRateIdx = idx;
break;
}
}
if (idx == NUM_SAMPLE_RATES)
return ERR_AAC_INVALID_FRAME;
}
aacDecInfo->nChans = psi->nChans;
aacDecInfo->sampRate = sampRateTab[psi->sampRateIdx];
/* check validity of header */
if (psi->sampRateIdx >= NUM_SAMPLE_RATES || psi->sampRateIdx < 0 || aacDecInfo->profile != AAC_PROFILE_LC)
return ERR_AAC_RAWBLOCK_PARAMS;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: PrepareRawBlock
*
* Description: reset per-block state variables for raw blocks (no ADTS/ADIF headers)
*
* Inputs: valid AACDecInfo struct
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int PrepareRawBlock(AACDecInfo *aacDecInfo)
{
// PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
// psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* syntactic element fields will be read from bitstream for each element */
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
/* fill in user-accessible data */
aacDecInfo->bitRate = 0;
aacDecInfo->sbrEnabled = 0;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: FlushCodec
*
* Description: flush internal codec state (after seeking, for example)
*
* Inputs: valid AACDecInfo struct
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: only need to clear data which is persistent between frames
* (such as overlap buffer)
**************************************************************************************/
int FlushCodec(AACDecInfo *aacDecInfo)
{
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
ClearBuffer(psi->overlap, AAC_MAX_NCHANS * AAC_MAX_NSAMPS * sizeof(int));
ClearBuffer(psi->prevWinShape, AAC_MAX_NCHANS * sizeof(int));
return ERR_AAC_NONE;
}

View File

@@ -1,415 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: huffman.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
*
* huffman.c - Huffman decoding
**************************************************************************************/
#include "coder.h"
/**************************************************************************************
* Function: DecodeHuffmanScalar
*
* Description: decode one Huffman symbol from bitstream
*
* Inputs: pointers to Huffman table and info struct
* left-aligned bit buffer with >= huffTabInfo->maxBits bits
*
* Outputs: decoded symbol in *val
*
* Return: number of bits in symbol
*
* Notes: assumes canonical Huffman codes:
* first CW always 0, we have "count" CW's of length "nBits" bits
* starting CW for codes of length nBits+1 =
* (startCW[nBits] + count[nBits]) << 1
* if there are no codes at nBits, then we just keep << 1 each time
* (since count[nBits] = 0)
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ int DecodeHuffmanScalar(const signed short *huffTab, const HuffInfo *huffTabInfo, unsigned int bitBuf, signed int *val)
{
unsigned int count, start, shift, t;
const unsigned /*char*/ int *countPtr;
const signed short *map;
map = huffTab + huffTabInfo->offset;
countPtr = huffTabInfo->count;
start = 0;
count = 0;
shift = 32;
do {
start += count;
start <<= 1;
map += count;
count = *countPtr++;
shift--;
t = (bitBuf >> shift) - start;
} while (t >= count);
*val = (signed int)pgm_read_word(&map[t]);
return (countPtr - huffTabInfo->count);
}
#define APPLY_SIGN(v, s) {(v) ^= ((signed int)(s) >> 31); (v) -= ((signed int)(s) >> 31);}
#define GET_QUAD_SIGNBITS(v) (((unsigned int)(v) << 17) >> 29) /* bits 14-12, unsigned */
#define GET_QUAD_W(v) (((signed int)(v) << 20) >> 29) /* bits 11-9, sign-extend */
#define GET_QUAD_X(v) (((signed int)(v) << 23) >> 29) /* bits 8-6, sign-extend */
#define GET_QUAD_Y(v) (((signed int)(v) << 26) >> 29) /* bits 5-3, sign-extend */
#define GET_QUAD_Z(v) (((signed int)(v) << 29) >> 29) /* bits 2-0, sign-extend */
#define GET_PAIR_SIGNBITS(v) (((unsigned int)(v) << 20) >> 30) /* bits 11-10, unsigned */
#define GET_PAIR_Y(v) (((signed int)(v) << 22) >> 27) /* bits 9-5, sign-extend */
#define GET_PAIR_Z(v) (((signed int)(v) << 27) >> 27) /* bits 4-0, sign-extend */
#define GET_ESC_SIGNBITS(v) (((unsigned int)(v) << 18) >> 30) /* bits 13-12, unsigned */
#define GET_ESC_Y(v) (((signed int)(v) << 20) >> 26) /* bits 11-6, sign-extend */
#define GET_ESC_Z(v) (((signed int)(v) << 26) >> 26) /* bits 5-0, sign-extend */
/**************************************************************************************
* Function: UnpackZeros
*
* Description: fill a section of coefficients with zeros
*
* Inputs: number of coefficients
*
* Outputs: nVals zeros, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 4 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
static void UnpackZeros(int nVals, int *coef)
{
while (nVals > 0) {
*coef++ = 0;
*coef++ = 0;
*coef++ = 0;
*coef++ = 0;
nVals -= 4;
}
}
/**************************************************************************************
* Function: UnpackQuads
*
* Description: decode a section of 4-way vector Huffman coded coefficients
*
* Inputs BitStreamInfo struct pointing to start of codewords for this section
* index of Huffman codebook
* number of coefficients
*
* Outputs: nVals coefficients, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 4 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void UnpackQuads(BitStreamInfo *bsi, int cb, int nVals, int *coef)
{
int w, x, y, z, maxBits, nCodeBits, nSignBits, val;
unsigned int bitBuf;
maxBits = huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET].maxBits + 4;
while (nVals > 0) {
/* decode quad */
bitBuf = GetBitsNoAdvance(bsi, maxBits) << (32 - maxBits);
nCodeBits = DecodeHuffmanScalar(huffTabSpec, &huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET], bitBuf, &val);
w = GET_QUAD_W(val);
x = GET_QUAD_X(val);
y = GET_QUAD_Y(val);
z = GET_QUAD_Z(val);
bitBuf <<= nCodeBits;
nSignBits = (int)GET_QUAD_SIGNBITS(val);
AdvanceBitstream(bsi, nCodeBits + nSignBits);
if (nSignBits) {
if (w) {APPLY_SIGN(w, bitBuf); bitBuf <<= 1;}
if (x) {APPLY_SIGN(x, bitBuf); bitBuf <<= 1;}
if (y) {APPLY_SIGN(y, bitBuf); bitBuf <<= 1;}
if (z) {APPLY_SIGN(z, bitBuf); bitBuf <<= 1;}
}
*coef++ = w; *coef++ = x; *coef++ = y; *coef++ = z;
nVals -= 4;
}
}
/**************************************************************************************
* Function: UnpackPairsNoEsc
*
* Description: decode a section of 2-way vector Huffman coded coefficients,
* using non-esc tables (5 through 10)
*
* Inputs BitStreamInfo struct pointing to start of codewords for this section
* index of Huffman codebook (must not be the escape codebook)
* number of coefficients
*
* Outputs: nVals coefficients, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 2 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void UnpackPairsNoEsc(BitStreamInfo *bsi, int cb, int nVals, int *coef)
{
int y, z, maxBits, nCodeBits, nSignBits, val;
unsigned int bitBuf;
maxBits = huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET].maxBits + 2;
while (nVals > 0) {
/* decode pair */
bitBuf = GetBitsNoAdvance(bsi, maxBits) << (32 - maxBits);
nCodeBits = DecodeHuffmanScalar(huffTabSpec, &huffTabSpecInfo[cb-HUFFTAB_SPEC_OFFSET], bitBuf, &val);
y = GET_PAIR_Y(val);
z = GET_PAIR_Z(val);
bitBuf <<= nCodeBits;
nSignBits = GET_PAIR_SIGNBITS(val);
AdvanceBitstream(bsi, nCodeBits + nSignBits);
if (nSignBits) {
if (y) {APPLY_SIGN(y, bitBuf); bitBuf <<= 1;}
if (z) {APPLY_SIGN(z, bitBuf); bitBuf <<= 1;}
}
*coef++ = y; *coef++ = z;
nVals -= 2;
}
}
/**************************************************************************************
* Function: UnpackPairsEsc
*
* Description: decode a section of 2-way vector Huffman coded coefficients,
* using esc table (11)
*
* Inputs BitStreamInfo struct pointing to start of codewords for this section
* index of Huffman codebook (must be the escape codebook)
* number of coefficients
*
* Outputs: nVals coefficients, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 2 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void UnpackPairsEsc(BitStreamInfo *bsi, int cb, int nVals, int *coef)
{
int y, z, maxBits, nCodeBits, nSignBits, n, val;
unsigned int bitBuf;
maxBits = huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET].maxBits + 2;
while (nVals > 0) {
/* decode pair with escape value */
bitBuf = GetBitsNoAdvance(bsi, maxBits) << (32 - maxBits);
nCodeBits = DecodeHuffmanScalar(huffTabSpec, &huffTabSpecInfo[cb-HUFFTAB_SPEC_OFFSET], bitBuf, &val);
y = GET_ESC_Y(val);
z = GET_ESC_Z(val);
bitBuf <<= nCodeBits;
nSignBits = GET_ESC_SIGNBITS(val);
AdvanceBitstream(bsi, nCodeBits + nSignBits);
if (y == 16) {
n = 4;
while (GetBits(bsi, 1) == 1)
n++;
y = (1 << n) + GetBits(bsi, n);
}
if (z == 16) {
n = 4;
while (GetBits(bsi, 1) == 1)
n++;
z = (1 << n) + GetBits(bsi, n);
}
if (nSignBits) {
if (y) {APPLY_SIGN(y, bitBuf); bitBuf <<= 1;}
if (z) {APPLY_SIGN(z, bitBuf); bitBuf <<= 1;}
}
*coef++ = y; *coef++ = z;
nVals -= 2;
}
}
/**************************************************************************************
* Function: DecodeSpectrumLong
*
* Description: decode transform coefficients for frame with one long block
*
* Inputs: platform specific info struct
* BitStreamInfo struct pointing to start of spectral data
* (14496-3, table 4.4.29)
* index of current channel
*
* Outputs: decoded, quantized coefficients for this channel
*
* Return: none
*
* Notes: adds in pulse data if present
* fills coefficient buffer with zeros in any region not coded with
* codebook in range [1, 11] (including sfb's above sfbMax)
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ void DecodeSpectrumLong(PSInfoBase *psi, BitStreamInfo *bsi, int ch)
{
int i, sfb, cb, nVals, offset;
const /*short*/ int *sfbTab;
unsigned char *sfbCodeBook;
int *coef;
ICSInfo *icsInfo;
PulseInfo *pi;
coef = psi->coef[ch];
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
/* decode long block */
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
sfbCodeBook = psi->sfbCodeBook[ch];
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
cb = *sfbCodeBook++;
nVals = sfbTab[sfb+1] - sfbTab[sfb];
if (cb == 0)
UnpackZeros(nVals, coef);
else if (cb <= 4)
UnpackQuads(bsi, cb, nVals, coef);
else if (cb <= 10)
UnpackPairsNoEsc(bsi, cb, nVals, coef);
else if (cb == 11)
UnpackPairsEsc(bsi, cb, nVals, coef);
else
UnpackZeros(nVals, coef);
coef += nVals;
}
/* fill with zeros above maxSFB */
nVals = NSAMPS_LONG - sfbTab[sfb];
UnpackZeros(nVals, coef);
/* add pulse data, if present */
pi = &psi->pulseInfo[ch];
if (pi->pulseDataPresent) {
coef = psi->coef[ch];
offset = sfbTab[pi->startSFB];
for (i = 0; i < pi->numPulse; i++) {
offset += pi->offset[i];
if (coef[offset] > 0)
coef[offset] += pi->amp[i];
else
coef[offset] -= pi->amp[i];
}
ASSERT(offset < NSAMPS_LONG);
}
}
/**************************************************************************************
* Function: DecodeSpectrumShort
*
* Description: decode transform coefficients for frame with eight short blocks
*
* Inputs: platform specific info struct
* BitStreamInfo struct pointing to start of spectral data
* (14496-3, table 4.4.29)
* index of current channel
*
* Outputs: decoded, quantized coefficients for this channel
*
* Return: none
*
* Notes: fills coefficient buffer with zeros in any region not coded with
* codebook in range [1, 11] (including sfb's above sfbMax)
* deinterleaves window groups into 8 windows
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ void DecodeSpectrumShort(PSInfoBase *psi, BitStreamInfo *bsi, int ch)
{
int gp, cb, nVals=0, win, offset, sfb;
const /*short*/ int *sfbTab;
unsigned char *sfbCodeBook;
int *coef;
ICSInfo *icsInfo;
coef = psi->coef[ch];
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
/* decode short blocks, deinterleaving in-place */
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
sfbCodeBook = psi->sfbCodeBook[ch];
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
nVals = sfbTab[sfb+1] - sfbTab[sfb];
cb = *sfbCodeBook++;
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
offset = win*NSAMPS_SHORT;
if (cb == 0)
UnpackZeros(nVals, coef + offset);
else if (cb <= 4)
UnpackQuads(bsi, cb, nVals, coef + offset);
else if (cb <= 10)
UnpackPairsNoEsc(bsi, cb, nVals, coef + offset);
else if (cb == 11)
UnpackPairsEsc(bsi, cb, nVals, coef + offset);
else
UnpackZeros(nVals, coef + offset);
}
coef += nVals;
}
/* fill with zeros above maxSFB */
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
offset = win*NSAMPS_SHORT;
nVals = NSAMPS_SHORT - sfbTab[sfb];
UnpackZeros(nVals, coef + offset);
}
coef += nVals;
coef += (icsInfo->winGroupLen[gp] - 1)*NSAMPS_SHORT;
}
ASSERT(coef == psi->coef[ch] + NSAMPS_LONG);
}

View File

@@ -1,177 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: hufftabs.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* hufftabs.c - Huffman symbol tables
**************************************************************************************/
#include "coder.h"
const HuffInfo huffTabSpecInfo[11] PROGMEM = {
/* table 0 not used */
{11, { 1, 0, 0, 0, 8, 0, 24, 0, 24, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
{ 9, { 0, 0, 1, 1, 7, 24, 15, 19, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 81},
{16, { 1, 0, 0, 4, 2, 6, 3, 5, 15, 15, 8, 9, 3, 3, 5, 2, 0, 0, 0, 0}, 162},
{12, { 0, 0, 0, 10, 6, 0, 9, 21, 8, 14, 11, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 243},
{13, { 1, 0, 0, 4, 4, 0, 4, 12, 12, 12, 18, 10, 4, 0, 0, 0, 0, 0, 0, 0}, 324},
{11, { 0, 0, 0, 9, 0, 16, 13, 8, 23, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 405},
{12, { 1, 0, 2, 1, 0, 4, 5, 10, 14, 15, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 486},
{10, { 0, 0, 1, 5, 7, 10, 14, 15, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 550},
{15, { 1, 0, 2, 1, 0, 4, 3, 8, 11, 20, 31, 38, 32, 14, 4, 0, 0, 0, 0, 0}, 614},
{12, { 0, 0, 0, 3, 8, 14, 17, 25, 31, 41, 22, 8, 0, 0, 0, 0, 0, 0, 0, 0}, 783},
{12, { 0, 0, 0, 2, 6, 7, 16, 59, 55, 95, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 952},
};
const signed short huffTabSpec[1241] PROGMEM = {
/* spectrum table 1 [81] (signed) */
0x0000, 0x0200, 0x0e00, 0x0007, 0x0040, 0x0001, 0x0038, 0x0008, 0x01c0, 0x03c0, 0x0e40, 0x0039, 0x0078, 0x01c8, 0x000f, 0x0240,
0x003f, 0x0fc0, 0x01f8, 0x0238, 0x0047, 0x0e08, 0x0009, 0x0208, 0x01c1, 0x0048, 0x0041, 0x0e38, 0x0201, 0x0e07, 0x0207, 0x0e01,
0x01c7, 0x0278, 0x0e78, 0x03c8, 0x004f, 0x0079, 0x01c9, 0x01cf, 0x03f8, 0x0239, 0x007f, 0x0e48, 0x0e0f, 0x0fc8, 0x01f9, 0x03c1,
0x03c7, 0x0e47, 0x0ff8, 0x01ff, 0x0049, 0x020f, 0x0241, 0x0e41, 0x0248, 0x0fc1, 0x0e3f, 0x0247, 0x023f, 0x0e39, 0x0fc7, 0x0e09,
0x0209, 0x03cf, 0x0e79, 0x0e4f, 0x03f9, 0x0249, 0x0fc9, 0x027f, 0x0fcf, 0x0fff, 0x0279, 0x03c9, 0x0e49, 0x0e7f, 0x0ff9, 0x03ff,
0x024f,
/* spectrum table 2 [81] (signed) */
0x0000, 0x0200, 0x0e00, 0x0001, 0x0038, 0x0007, 0x01c0, 0x0008, 0x0040, 0x01c8, 0x0e40, 0x0078, 0x000f, 0x0047, 0x0039, 0x0e07,
0x03c0, 0x0238, 0x0fc0, 0x003f, 0x0208, 0x0201, 0x01c1, 0x0e08, 0x0041, 0x01f8, 0x0e01, 0x01c7, 0x0e38, 0x0240, 0x0048, 0x0009,
0x0207, 0x0079, 0x0239, 0x0e78, 0x01cf, 0x03c8, 0x0247, 0x0209, 0x0e48, 0x01f9, 0x0248, 0x0e0f, 0x0ff8, 0x0e39, 0x03f8, 0x0278,
0x03c1, 0x0e47, 0x0fc8, 0x0e09, 0x0fc1, 0x0fc7, 0x01ff, 0x020f, 0x023f, 0x007f, 0x0049, 0x0e41, 0x0e3f, 0x004f, 0x03c7, 0x01c9,
0x0241, 0x03cf, 0x0e79, 0x03f9, 0x0fff, 0x0e4f, 0x0e49, 0x0249, 0x0fcf, 0x03c9, 0x0e7f, 0x0fc9, 0x027f, 0x03ff, 0x0ff9, 0x0279,
0x024f,
/* spectrum table 3 [81] (unsigned) */
0x0000, 0x1200, 0x1001, 0x1040, 0x1008, 0x2240, 0x2009, 0x2048, 0x2041, 0x2208, 0x3049, 0x2201, 0x3248, 0x4249, 0x3209, 0x3241,
0x1400, 0x1002, 0x200a, 0x2440, 0x3288, 0x2011, 0x3051, 0x2280, 0x304a, 0x3448, 0x1010, 0x2088, 0x2050, 0x1080, 0x2042, 0x2408,
0x4289, 0x3089, 0x3250, 0x4251, 0x3281, 0x2210, 0x3211, 0x2081, 0x4449, 0x424a, 0x3441, 0x320a, 0x2012, 0x3052, 0x3488, 0x3290,
0x2202, 0x2401, 0x3091, 0x2480, 0x4291, 0x3242, 0x3409, 0x4252, 0x4489, 0x2090, 0x308a, 0x3212, 0x3481, 0x3450, 0x3490, 0x3092,
0x4491, 0x4451, 0x428a, 0x4292, 0x2082, 0x2410, 0x3282, 0x3411, 0x444a, 0x3442, 0x4492, 0x448a, 0x4452, 0x340a, 0x2402, 0x3482,
0x3412,
/* spectrum table 4 [81] (unsigned) */
0x4249, 0x3049, 0x3241, 0x3248, 0x3209, 0x1200, 0x2240, 0x0000, 0x2009, 0x2208, 0x2201, 0x2048, 0x1001, 0x2041, 0x1008, 0x1040,
0x4449, 0x4251, 0x4289, 0x424a, 0x3448, 0x3441, 0x3288, 0x3409, 0x3051, 0x304a, 0x3250, 0x3089, 0x320a, 0x3281, 0x3242, 0x3211,
0x2440, 0x2408, 0x2280, 0x2401, 0x2042, 0x2088, 0x200a, 0x2050, 0x2081, 0x2202, 0x2011, 0x2210, 0x1400, 0x1002, 0x1080, 0x1010,
0x4291, 0x4489, 0x4451, 0x4252, 0x428a, 0x444a, 0x3290, 0x3488, 0x3450, 0x3091, 0x3052, 0x3481, 0x308a, 0x3411, 0x3212, 0x4491,
0x3282, 0x340a, 0x3442, 0x4292, 0x4452, 0x448a, 0x2090, 0x2480, 0x2012, 0x2410, 0x2082, 0x2402, 0x4492, 0x3092, 0x3490, 0x3482,
0x3412,
/* spectrum table 5 [81] (signed) */
0x0000, 0x03e0, 0x0020, 0x0001, 0x001f, 0x003f, 0x03e1, 0x03ff, 0x0021, 0x03c0, 0x0002, 0x0040, 0x001e, 0x03df, 0x0041, 0x03fe,
0x0022, 0x03c1, 0x005f, 0x03e2, 0x003e, 0x03a0, 0x0060, 0x001d, 0x0003, 0x03bf, 0x0023, 0x0061, 0x03fd, 0x03a1, 0x007f, 0x003d,
0x03e3, 0x03c2, 0x0042, 0x03de, 0x005e, 0x03be, 0x007e, 0x03c3, 0x005d, 0x0062, 0x0043, 0x03a2, 0x03dd, 0x001c, 0x0380, 0x0081,
0x0080, 0x039f, 0x0004, 0x009f, 0x03fc, 0x0024, 0x03e4, 0x0381, 0x003c, 0x007d, 0x03bd, 0x03a3, 0x03c4, 0x039e, 0x0082, 0x005c,
0x0044, 0x0063, 0x0382, 0x03dc, 0x009e, 0x007c, 0x039d, 0x0383, 0x0064, 0x03a4, 0x0083, 0x009d, 0x03bc, 0x009c, 0x0384, 0x0084,
0x039c,
/* spectrum table 6 [81] (signed) */
0x0000, 0x0020, 0x001f, 0x0001, 0x03e0, 0x0021, 0x03e1, 0x003f, 0x03ff, 0x005f, 0x0041, 0x03c1, 0x03df, 0x03c0, 0x03e2, 0x0040,
0x003e, 0x0022, 0x001e, 0x03fe, 0x0002, 0x005e, 0x03c2, 0x03de, 0x0042, 0x03a1, 0x0061, 0x007f, 0x03e3, 0x03bf, 0x0023, 0x003d,
0x03fd, 0x0060, 0x03a0, 0x001d, 0x0003, 0x0062, 0x03be, 0x03c3, 0x0043, 0x007e, 0x005d, 0x03dd, 0x03a2, 0x0063, 0x007d, 0x03bd,
0x03a3, 0x003c, 0x03fc, 0x0081, 0x0381, 0x039f, 0x0024, 0x009f, 0x03e4, 0x001c, 0x0382, 0x039e, 0x0044, 0x03dc, 0x0380, 0x0082,
0x009e, 0x03c4, 0x0080, 0x005c, 0x0004, 0x03bc, 0x03a4, 0x007c, 0x009d, 0x0064, 0x0083, 0x0383, 0x039d, 0x0084, 0x0384, 0x039c,
0x009c,
/* spectrum table 7 [64] (unsigned) */
0x0000, 0x0420, 0x0401, 0x0821, 0x0841, 0x0822, 0x0440, 0x0402, 0x0861, 0x0823, 0x0842, 0x0460, 0x0403, 0x0843, 0x0862, 0x0824,
0x0881, 0x0825, 0x08a1, 0x0863, 0x0844, 0x0404, 0x0480, 0x0882, 0x0845, 0x08a2, 0x0405, 0x08c1, 0x04a0, 0x0826, 0x0883, 0x0865,
0x0864, 0x08a3, 0x0846, 0x08c2, 0x0827, 0x0866, 0x0406, 0x04c0, 0x0884, 0x08e1, 0x0885, 0x08e2, 0x08a4, 0x08c3, 0x0847, 0x08e3,
0x08c4, 0x08a5, 0x0886, 0x0867, 0x04e0, 0x0407, 0x08c5, 0x08a6, 0x08e4, 0x0887, 0x08a7, 0x08e5, 0x08e6, 0x08c6, 0x08c7, 0x08e7,
/* spectrum table 8 [64] (unsigned) */
0x0821, 0x0841, 0x0420, 0x0822, 0x0401, 0x0842, 0x0000, 0x0440, 0x0402, 0x0861, 0x0823, 0x0862, 0x0843, 0x0863, 0x0881, 0x0824,
0x0882, 0x0844, 0x0460, 0x0403, 0x0883, 0x0864, 0x08a2, 0x08a1, 0x0845, 0x0825, 0x08a3, 0x0865, 0x0884, 0x08a4, 0x0404, 0x0885,
0x0480, 0x0846, 0x08c2, 0x08c1, 0x0826, 0x0866, 0x08c3, 0x08a5, 0x04a0, 0x08c4, 0x0405, 0x0886, 0x08e1, 0x08e2, 0x0847, 0x08c5,
0x08e3, 0x0827, 0x08a6, 0x0867, 0x08c6, 0x08e4, 0x04c0, 0x0887, 0x0406, 0x08e5, 0x08e6, 0x08c7, 0x08a7, 0x04e0, 0x0407, 0x08e7,
/* spectrum table 9 [169] (unsigned) */
0x0000, 0x0420, 0x0401, 0x0821, 0x0841, 0x0822, 0x0440, 0x0402, 0x0861, 0x0842, 0x0823, 0x0460, 0x0403, 0x0843, 0x0862, 0x0824,
0x0881, 0x0844, 0x0825, 0x0882, 0x0863, 0x0404, 0x0480, 0x08a1, 0x0845, 0x0826, 0x0864, 0x08a2, 0x08c1, 0x0883, 0x0405, 0x0846,
0x04a0, 0x0827, 0x0865, 0x0828, 0x0901, 0x0884, 0x08a3, 0x08c2, 0x08e1, 0x0406, 0x0902, 0x0848, 0x0866, 0x0847, 0x0885, 0x0921,
0x0829, 0x08e2, 0x04c0, 0x08a4, 0x08c3, 0x0903, 0x0407, 0x0922, 0x0868, 0x0886, 0x0867, 0x0408, 0x0941, 0x08c4, 0x0849, 0x08a5,
0x0500, 0x04e0, 0x08e3, 0x0942, 0x0923, 0x0904, 0x082a, 0x08e4, 0x08c5, 0x08a6, 0x0888, 0x0887, 0x0869, 0x0961, 0x08a8, 0x0520,
0x0905, 0x0943, 0x084a, 0x0409, 0x0962, 0x0924, 0x08c6, 0x0981, 0x0889, 0x0906, 0x082b, 0x0925, 0x0944, 0x08a7, 0x08e5, 0x084b,
0x082c, 0x0982, 0x0963, 0x086a, 0x08a9, 0x08c7, 0x0907, 0x0964, 0x040a, 0x08e6, 0x0983, 0x0540, 0x0945, 0x088a, 0x08c8, 0x084c,
0x0926, 0x0927, 0x088b, 0x0560, 0x08c9, 0x086b, 0x08aa, 0x0908, 0x08e8, 0x0985, 0x086c, 0x0965, 0x08e7, 0x0984, 0x0966, 0x0946,
0x088c, 0x08e9, 0x08ab, 0x040b, 0x0986, 0x08ca, 0x0580, 0x0947, 0x08ac, 0x08ea, 0x0928, 0x040c, 0x0967, 0x0909, 0x0929, 0x0948,
0x08eb, 0x0987, 0x08cb, 0x090b, 0x0968, 0x08ec, 0x08cc, 0x090a, 0x0949, 0x090c, 0x092a, 0x092b, 0x092c, 0x094b, 0x0989, 0x094a,
0x0969, 0x0988, 0x096a, 0x098a, 0x098b, 0x094c, 0x096b, 0x096c, 0x098c,
/* spectrum table 10 [169] (unsigned) */
0x0821, 0x0822, 0x0841, 0x0842, 0x0420, 0x0401, 0x0823, 0x0862, 0x0861, 0x0843, 0x0863, 0x0440, 0x0402, 0x0844, 0x0882, 0x0824,
0x0881, 0x0000, 0x0883, 0x0864, 0x0460, 0x0403, 0x0884, 0x0845, 0x08a2, 0x0825, 0x08a1, 0x08a3, 0x0865, 0x08a4, 0x0885, 0x08c2,
0x0846, 0x08c3, 0x0480, 0x08c1, 0x0404, 0x0826, 0x0866, 0x08a5, 0x08c4, 0x0886, 0x08c5, 0x08e2, 0x0867, 0x0847, 0x08a6, 0x0902,
0x08e3, 0x04a0, 0x08e1, 0x0405, 0x0901, 0x0827, 0x0903, 0x08e4, 0x0887, 0x0848, 0x08c6, 0x08e5, 0x0828, 0x0868, 0x0904, 0x0888,
0x08a7, 0x0905, 0x08a8, 0x08e6, 0x08c7, 0x0922, 0x04c0, 0x08c8, 0x0923, 0x0869, 0x0921, 0x0849, 0x0406, 0x0906, 0x0924, 0x0889,
0x0942, 0x0829, 0x08e7, 0x0907, 0x0925, 0x08e8, 0x0943, 0x08a9, 0x0944, 0x084a, 0x0941, 0x086a, 0x0926, 0x08c9, 0x0500, 0x088a,
0x04e0, 0x0962, 0x08e9, 0x0963, 0x0946, 0x082a, 0x0961, 0x0927, 0x0407, 0x0908, 0x0945, 0x086b, 0x08aa, 0x0909, 0x0965, 0x0408,
0x0964, 0x084b, 0x08ea, 0x08ca, 0x0947, 0x088b, 0x082b, 0x0982, 0x0928, 0x0983, 0x0966, 0x08ab, 0x0984, 0x0967, 0x0985, 0x086c,
0x08cb, 0x0520, 0x0948, 0x0540, 0x0981, 0x0409, 0x088c, 0x0929, 0x0986, 0x084c, 0x090a, 0x092a, 0x082c, 0x0968, 0x0987, 0x08eb,
0x08ac, 0x08cc, 0x0949, 0x090b, 0x0988, 0x040a, 0x08ec, 0x0560, 0x094a, 0x0969, 0x096a, 0x040b, 0x096b, 0x092b, 0x094b, 0x0580,
0x090c, 0x0989, 0x094c, 0x092c, 0x096c, 0x098b, 0x040c, 0x098a, 0x098c,
/* spectrum table 11 [289] (unsigned) */
0x0000, 0x2041, 0x2410, 0x1040, 0x1001, 0x2081, 0x2042, 0x2082, 0x2043, 0x20c1, 0x20c2, 0x1080, 0x2083, 0x1002, 0x20c3, 0x2101,
0x2044, 0x2102, 0x2084, 0x2103, 0x20c4, 0x10c0, 0x1003, 0x2141, 0x2142, 0x2085, 0x2104, 0x2045, 0x2143, 0x20c5, 0x2144, 0x2105,
0x2182, 0x2086, 0x2181, 0x2183, 0x20c6, 0x2046, 0x2110, 0x20d0, 0x2405, 0x2403, 0x2404, 0x2184, 0x2406, 0x1100, 0x2106, 0x1004,
0x2090, 0x2145, 0x2150, 0x2407, 0x2402, 0x2408, 0x2087, 0x21c2, 0x20c7, 0x2185, 0x2146, 0x2190, 0x240a, 0x21c3, 0x21c1, 0x2409,
0x21d0, 0x2050, 0x2047, 0x2107, 0x240b, 0x21c4, 0x240c, 0x2210, 0x2401, 0x2186, 0x2250, 0x2088, 0x2147, 0x2290, 0x240d, 0x2203,
0x2202, 0x20c8, 0x1140, 0x240e, 0x22d0, 0x21c5, 0x2108, 0x2187, 0x21c6, 0x1005, 0x2204, 0x240f, 0x2310, 0x2048, 0x2201, 0x2390,
0x2148, 0x2350, 0x20c9, 0x2205, 0x21c7, 0x2089, 0x2206, 0x2242, 0x2243, 0x23d0, 0x2109, 0x2188, 0x1180, 0x2244, 0x2149, 0x2207,
0x21c8, 0x2049, 0x2283, 0x1006, 0x2282, 0x2241, 0x2245, 0x210a, 0x208a, 0x2246, 0x20ca, 0x2189, 0x2284, 0x2208, 0x2285, 0x2247,
0x22c3, 0x204a, 0x11c0, 0x2286, 0x21c9, 0x20cb, 0x214a, 0x2281, 0x210b, 0x22c2, 0x2342, 0x218a, 0x2343, 0x208b, 0x1400, 0x214b,
0x22c5, 0x22c4, 0x2248, 0x21ca, 0x2209, 0x1010, 0x210d, 0x1007, 0x20cd, 0x22c6, 0x2341, 0x2344, 0x2303, 0x208d, 0x2345, 0x220a,
0x218b, 0x2288, 0x2287, 0x2382, 0x2304, 0x204b, 0x210c, 0x22c1, 0x20cc, 0x204d, 0x2302, 0x21cb, 0x20ce, 0x214c, 0x214d, 0x2384,
0x210e, 0x22c7, 0x2383, 0x2305, 0x2346, 0x2306, 0x1200, 0x22c8, 0x208c, 0x2249, 0x2385, 0x218d, 0x228a, 0x23c2, 0x220b, 0x224a,
0x2386, 0x2289, 0x214e, 0x22c9, 0x2381, 0x208e, 0x218c, 0x204c, 0x2348, 0x1008, 0x2347, 0x21cc, 0x2307, 0x21cd, 0x23c3, 0x2301,
0x218e, 0x208f, 0x23c5, 0x23c4, 0x204e, 0x224b, 0x210f, 0x2387, 0x220d, 0x2349, 0x220c, 0x214f, 0x20cf, 0x228b, 0x22ca, 0x2308,
0x23c6, 0x23c7, 0x220e, 0x23c1, 0x21ce, 0x1240, 0x1009, 0x224d, 0x224c, 0x2309, 0x2388, 0x228d, 0x2389, 0x230a, 0x218f, 0x21cf,
0x224e, 0x23c8, 0x22cb, 0x22ce, 0x204f, 0x228c, 0x228e, 0x234b, 0x234a, 0x22cd, 0x22cc, 0x220f, 0x238b, 0x234c, 0x230d, 0x23c9,
0x238a, 0x1280, 0x230b, 0x224f, 0x100a, 0x230c, 0x12c0, 0x230e, 0x228f, 0x234d, 0x100d, 0x238c, 0x23ca, 0x23cb, 0x22cf, 0x238d,
0x1340, 0x100b, 0x234e, 0x23cc, 0x23cd, 0x230f, 0x1380, 0x238e, 0x234f, 0x1300, 0x238f, 0x100e, 0x100c, 0x23ce, 0x13c0, 0x100f,
0x23cf,
};
const HuffInfo huffTabScaleFactInfo PROGMEM =
{19, { 1, 0, 1, 3, 2, 4, 3, 5, 4, 6, 6, 6, 5, 8, 4, 7, 3, 7, 46, 0}, 0};
/* note - includes offset of -60 (4.6.2.3 in spec) */
const signed short huffTabScaleFact[121] PROGMEM = {
/* scale factor table [121] */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, 6, -6, 7, -7, 8,
-8, 9, -9, 10, -10, -11, 11, 12, -12, 13, -13, 14, -14, 16, 15, 17,
18, -15, -17, -16, 19, -18, -19, 20, -20, 21, -21, 22, -22, 23, -23, -25,
25, -27, -24, -26, 24, -28, 27, 29, -30, -29, 26, -31, -34, -33, -32, -36,
28, -35, -38, -37, 30, -39, -41, -57, -59, -58, -60, 38, 39, 40, 41, 42,
57, 37, 31, 32, 33, 34, 35, 36, 44, 51, 52, 53, 54, 55, 56, 50,
45, 46, 47, 48, 49, 58, -54, -52, -51, -50, -55, 43, 60, 59, -56, -53,
-45, -44, -42, -40, -43, -49, -48, -46, -47,
};

View File

@@ -1,589 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: imdct.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* imdct.c - inverse MDCT
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define RND_VAL (1 << (FBITS_OUT_IMDCT-1))
#ifndef AAC_ENABLE_SBR
/**************************************************************************************
* Function: DecWindowOverlap
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence LONG-LONG
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data")))*/ static void DecWindowOverlap(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
pcm1 = pcm0 + (1024 - 1) * nChans;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
if (winTypeCurr == winTypePrev) {
/* cut window loads in half since current and overlap sections use same symmetric window */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
} else {
/* different windows for current and overlap parts - should still fit in registers on ARM w/o stack spill */
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
}
/**************************************************************************************
* Function: DecWindowOverlapLongStart
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence LONG-START
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data")))*/ static void DecWindowOverlapLongStart(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
pcm1 = pcm0 + (1024 - 1) * nChans;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
in = *buf1--;
*over1-- = 0; /* Wn = 0 for n = (2047, 2046, ... 1600) */
*over0++ = in >> 1; /* Wn = 1 for n = (1024, 1025, ... 1471) */
} while (--i);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++; /* W[0], W[1], ... --> W[255], W[254], ... */
w1 = *wndCurr++; /* W[127], W[126], ... --> W[128], W[129], ... */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* Wn = short window for n = (1599, 1598, ... , 1536) */
*over0++ = MULSHIFT32(w1, in); /* Wn = short window for n = (1472, 1473, ... , 1535) */
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapLongStop
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence LONG-STOP
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data")))*/ static void DecWindowOverlapLongStop(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
pcm1 = pcm0 + (1024 - 1) * nChans;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
/* Wn = 0 for n = (0, 1, ... 447) */
/* Wn = 1 for n = (576, 577, ... 1023) */
in = *buf0++;
f1 = in >> 1; /* scale since skipping multiply by Q31 */
in = *over0;
*pcm0 = CLIPTOSHORT( (in + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (--i);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapShort
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence EIGHT-SHORT (does all 8 short blocks)
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data"))) */ static void DecWindowOverlapShort(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* pcm[0-447] = 0 + overlap[0-447] */
i = 448;
do {
f0 = *over0++;
f1 = *over0++;
*pcm0 = CLIPTOSHORT( (f0 + RND_VAL) >> FBITS_OUT_IMDCT ); pcm0 += nChans;
*pcm0 = CLIPTOSHORT( (f1 + RND_VAL) >> FBITS_OUT_IMDCT ); pcm0 += nChans;
i -= 2;
} while (i);
/* pcm[448-575] = Wp[0-127] * block0[0-127] + overlap[448-575] */
pcm1 = pcm0 + (128 - 1) * nChans;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
/* save over0/over1 for next short block, in the slots just vacated */
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
/* pcm[576-703] = Wc[128-255] * block0[128-255] + Wc[0-127] * block1[0-127] + overlap[576-703]
* pcm[704-831] = Wc[128-255] * block1[128-255] + Wc[0-127] * block2[0-127] + overlap[704-831]
* pcm[832-959] = Wc[128-255] * block2[128-255] + Wc[0-127] * block3[0-127] + overlap[832-959]
*/
for (i = 0; i < 3; i++) {
pcm0 += 64 * nChans;
pcm1 = pcm0 + (128 - 1) * nChans;
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 - 128); /* from last short block */
in += *(over0 + 0); /* from last full frame */
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *(over1 - 128); /* from last short block */
in += *(over1 + 0); /* from last full frame */
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
/* save over0/over1 for next short block, in the slots just vacated */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* pcm[960-1023] = Wc[128-191] * block3[128-191] + Wc[0-63] * block4[0-63] + overlap[960-1023]
* over[0-63] = Wc[192-255] * block3[192-255] + Wc[64-127] * block4[64-127]
*/
pcm0 += 64 * nChans;
over0 -= 832; /* points at overlap[64] */
over1 = over0 + 128 - 1; /* points at overlap[191] */
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 + 768); /* from last short block */
in += *(over0 + 896); /* from last full frame */
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *(over1 + 768); /* from last short block */
*(over1 - 128) = in + f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* save in overlap[128-191] */
*over0++ = MULSHIFT32(w1, in); /* save in overlap[64-127] */
} while (over0 < over1);
/* over0 now points at overlap[128] */
/* over[64-191] = Wc[128-255] * block4[128-255] + Wc[0-127] * block5[0-127]
* over[192-319] = Wc[128-255] * block5[128-255] + Wc[0-127] * block6[0-127]
* over[320-447] = Wc[128-255] * block6[128-255] + Wc[0-127] * block7[0-127]
* over[448-576] = Wc[128-255] * block7[128-255]
*/
for (i = 0; i < 3; i++) {
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
/* from last short block */
*(over0 - 128) -= f0;
*(over1 - 128)+= f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* over[576-1024] = 0 */
i = 448;
over0 += 64;
do {
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
i -= 4;
} while (i);
}
#endif /* !AAC_ENABLE_SBR */
/**************************************************************************************
* Function: IMDCT
*
* Description: inverse transform and convert to 16-bit PCM
*
* Inputs: valid AACDecInfo struct
* index of current channel (0 for SCE/LFE, 0 or 1 for CPE)
* output channel (range = [0, nChans-1])
*
* Outputs: complete frame of decoded PCM, after inverse transform
*
* Return: 0 if successful, -1 if error
*
* Notes: If AAC_ENABLE_SBR is defined at compile time then window + overlap
* does NOT clip to 16-bit PCM and does NOT interleave channels
* If AAC_ENABLE_SBR is NOT defined at compile time, then window + overlap
* does clip to 16-bit PCM and interleaves channels
* If SBR is enabled at compile time, but we don't know whether it is
* actually used for this frame (e.g. the first frame of a stream),
* we need to produce both clipped 16-bit PCM in outbuf AND
* unclipped 32-bit PCM in the SBR input buffer. In this case we make
* a separate pass over the 32-bit PCM to produce 16-bit PCM output.
* This inflicts a slight performance hit when decoding non-SBR files.
**************************************************************************************/
int IMDCT(AACDecInfo *aacDecInfo, int ch, int chOut, short *outbuf)
{
int i;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
outbuf += chOut;
/* optimized type-IV DCT (operates inplace) */
if (icsInfo->winSequence == 2) {
/* 8 short blocks */
for (i = 0; i < 8; i++)
DCT4(0, psi->coef[ch] + i*128, psi->gbCurrent[ch]);
} else {
/* 1 long block */
DCT4(1, psi->coef[ch], psi->gbCurrent[ch]);
}
#ifdef AAC_ENABLE_SBR
/* window, overlap-add, don't clip to short (send to SBR decoder)
* store the decoded 32-bit samples in top half (second AAC_MAX_NSAMPS samples) of coef buffer
*/
if (icsInfo->winSequence == 0)
DecWindowOverlapNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 1)
DecWindowOverlapLongStartNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 2)
DecWindowOverlapShortNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 3)
DecWindowOverlapLongStopNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
if (!aacDecInfo->sbrEnabled) {
for (i = 0; i < AAC_MAX_NSAMPS; i++) {
*outbuf = CLIPTOSHORT((psi->sbrWorkBuf[ch][i] + RND_VAL) >> FBITS_OUT_IMDCT);
outbuf += aacDecInfo->nChans;
}
}
aacDecInfo->rawSampleBuf[ch] = psi->sbrWorkBuf[ch];
aacDecInfo->rawSampleBytes = sizeof(int);
aacDecInfo->rawSampleFBits = FBITS_OUT_IMDCT;
#else
/* window, overlap-add, round to PCM - optimized for each window sequence */
if (icsInfo->winSequence == 0)
DecWindowOverlap(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 1)
DecWindowOverlapLongStart(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 2)
DecWindowOverlapShort(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 3)
DecWindowOverlapLongStop(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
aacDecInfo->rawSampleBuf[ch] = 0;
aacDecInfo->rawSampleBytes = 0;
aacDecInfo->rawSampleFBits = 0;
#endif
psi->prevWinShape[chOut] = icsInfo->winShape;
return 0;
}

View File

@@ -1,213 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aaccommon.h,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* aaccommon.h - implementation-independent API's, datatypes, and definitions
**************************************************************************************/
#ifndef _AACCOMMON_H
#define _AACCOMMON_H
#ifdef ESP8266
# include "pgmspace.h"
#elif defined(ESP_PLATFORM) && __has_include(<pgm_space.h>)
# include <pgm_space.h>
#else
# define PROGMEM
# define pgm_read_byte(addr) (*(const unsigned char *)(addr))
# define pgm_read_word(addr) (*(const unsigned short *)(addr))
#endif
// Can't fit in ESP8266 RAM
#ifndef ESP8266
#define AAC_ENABLE_SBR 1
#endif
#pragma GCC optimize ("O3")
#include "aacdec.h"
#include "statname.h"
/* 12-bit syncword */
#define SYNCWORDH 0xff
#define SYNCWORDL 0xf0
#define MAX_NCHANS_ELEM 2 /* max number of channels in any single bitstream element (SCE,CPE,CCE,LFE) */
#define ADTS_HEADER_BYTES 7
#define NUM_SAMPLE_RATES 12
#define NUM_DEF_CHAN_MAPS 8
#define NUM_ELEMENTS 8
#define MAX_NUM_PCE_ADIF 16
#define MAX_WIN_GROUPS 8
#define MAX_SFB_SHORT 15
#define MAX_SF_BANDS (MAX_SFB_SHORT*MAX_WIN_GROUPS) /* worst case = 15 sfb's * 8 windows for short block */
#define MAX_MS_MASK_BYTES ((MAX_SF_BANDS + 7) >> 3)
#define MAX_PRED_SFB 41
#define MAX_TNS_FILTERS 8
#define MAX_TNS_COEFS 60
#define MAX_TNS_ORDER 20
#define MAX_PULSES 4
#define MAX_GAIN_BANDS 3
#define MAX_GAIN_WIN 8
#define MAX_GAIN_ADJUST 7
#define NSAMPS_LONG 1024
#define NSAMPS_SHORT 128
#define NUM_SYN_ID_BITS 3
#define NUM_INST_TAG_BITS 4
#define EXT_SBR_DATA 0x0d
#define EXT_SBR_DATA_CRC 0x0e
#define IS_ADIF(p) ((p)[0] == 'A' && (p)[1] == 'D' && (p)[2] == 'I' && (p)[3] == 'F')
#define GET_ELE_ID(p) ((AACElementID)(*(p) >> (8-NUM_SYN_ID_BITS)))
/* AAC file format */
enum {
AAC_FF_Unknown = 0, /* should be 0 on init */
AAC_FF_ADTS = 1,
AAC_FF_ADIF = 2,
AAC_FF_RAW = 3
};
/* syntactic element type */
enum {
AAC_ID_INVALID = -1,
AAC_ID_SCE = 0,
AAC_ID_CPE = 1,
AAC_ID_CCE = 2,
AAC_ID_LFE = 3,
AAC_ID_DSE = 4,
AAC_ID_PCE = 5,
AAC_ID_FIL = 6,
AAC_ID_END = 7
};
typedef struct _AACDecInfo {
/* pointers to platform-specific state information */
void *psInfoBase; /* baseline MPEG-4 LC decoding */
void *psInfoSBR; /* MPEG-4 SBR decoding */
/* raw decoded data, before rounding to 16-bit PCM (for postprocessing such as SBR) */
void *rawSampleBuf[AAC_MAX_NCHANS];
int rawSampleBytes;
int rawSampleFBits;
/* fill data (can be used for processing SBR or other extensions) */
unsigned char *fillBuf;
int fillCount;
int fillExtType;
/* block information */
int prevBlockID;
int currBlockID;
int currInstTag;
int sbDeinterleaveReqd[MAX_NCHANS_ELEM];
int adtsBlocksLeft;
/* user-accessible info */
int bitRate;
int nChans;
int sampRate;
int profile;
int format;
int sbrEnabled;
int tnsUsed;
int pnsUsed;
int frameCount;
} AACDecInfo;
/* decoder functions which must be implemented for each platform */
AACDecInfo *AllocateBuffers(void);
AACDecInfo *AllocateBuffersPre(void **space, int *len);
void FreeBuffers(AACDecInfo *aacDecInfo);
void ClearBuffer(void *buf, int nBytes);
int UnpackADTSHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail);
int GetADTSChannelMapping(AACDecInfo *aacDecInfo, unsigned char *buf, int bitOffset, int bitsAvail);
int UnpackADIFHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail);
int SetRawBlockParams(AACDecInfo *aacDecInfo, int copyLast, int nChans, int sampRate, int profile);
int PrepareRawBlock(AACDecInfo *aacDecInfo);
int FlushCodec(AACDecInfo *aacDecInfo);
int DecodeNextElement(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail);
int DecodeNoiselessData(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail, int ch);
int Dequantize(AACDecInfo *aacDecInfo, int ch);
int StereoProcess(AACDecInfo *aacDecInfo);
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch);
int PNS(AACDecInfo *aacDecInfo, int ch);
int TNSFilter(AACDecInfo *aacDecInfo, int ch);
int IMDCT(AACDecInfo *aacDecInfo, int ch, int chBase, short *outbuf);
/* SBR specific functions */
int InitSBR(AACDecInfo *aacDecInfo);
int InitSBRPre(AACDecInfo *aacDecInfo, void **ptr, int *sz);
void FreeSBR(AACDecInfo *aacDecInfo);
int DecodeSBRBitstream(AACDecInfo *aacDecInfo, int chBase);
int DecodeSBRData(AACDecInfo *aacDecInfo, int chBase, short *outbuf);
int FlushCodecSBR(AACDecInfo *aacDecInfo);
/* aactabs.c - global ROM tables */
extern const int sampRateTab[NUM_SAMPLE_RATES];
extern const int predSFBMax[NUM_SAMPLE_RATES];
extern const int channelMapTab[NUM_DEF_CHAN_MAPS];
extern const int elementNumChans[NUM_ELEMENTS];
extern const unsigned /*char*/ int sfBandTotalShort[NUM_SAMPLE_RATES];
extern const unsigned /*char*/ int sfBandTotalLong[NUM_SAMPLE_RATES];
extern const int sfBandTabShortOffset[NUM_SAMPLE_RATES];
extern const /*short*/ int sfBandTabShort[76];
extern const int sfBandTabLongOffset[NUM_SAMPLE_RATES];
extern const /*short*/ int sfBandTabLong[325];
extern const int tnsMaxBandsShortOffset[AAC_NUM_PROFILES];
extern const unsigned /*char*/ int tnsMaxBandsShort[2*NUM_SAMPLE_RATES];
extern const unsigned /*char*/ int tnsMaxOrderShort[AAC_NUM_PROFILES];
extern const int tnsMaxBandsLongOffset[AAC_NUM_PROFILES];
extern const unsigned /*char*/ int tnsMaxBandsLong[2*NUM_SAMPLE_RATES];
extern const unsigned /*char*/ int tnsMaxOrderLong[AAC_NUM_PROFILES];
#endif /* _AACCOMMON_H */

View File

@@ -1,476 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aacdec.c,v 1.1 2005/02/26 01:47:31 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* aacdec.c - platform-independent top level decoder API
**************************************************************************************/
#include "aaccommon.h"
//#include "profile.h"
#define PROFILE_START(x)
#define PROFILE_END()
/**************************************************************************************
* Function: AACInitDecoder
*
* Description: allocate memory for platform-specific data
* clear all the user-accessible fields
* initialize SBR decoder if enabled
*
* Inputs: none
*
* Outputs: none
*
* Return: handle to AAC decoder instance, 0 if malloc fails
**************************************************************************************/
HAACDecoder AACInitDecoder(void)
{
AACDecInfo *aacDecInfo;
aacDecInfo = AllocateBuffers();
if (!aacDecInfo)
return 0;
#ifdef AAC_ENABLE_SBR
if (InitSBR(aacDecInfo)) {
AACFreeDecoder(aacDecInfo);
return 0;
}
#endif
return (HAACDecoder)aacDecInfo;
}
HAACDecoder AACInitDecoderPre(void *ptr, int sz)
{
AACDecInfo *aacDecInfo;
aacDecInfo = AllocateBuffersPre(&ptr, &sz);
if (!aacDecInfo)
return 0;
#ifdef AAC_ENABLE_SBR
if (InitSBRPre(aacDecInfo, &ptr, &sz)) {
return 0;
}
#endif
return (HAACDecoder)aacDecInfo;
}
/**************************************************************************************
* Function: AACFreeDecoder
*
* Description: free platform-specific data allocated by AACInitDecoder
* free SBR decoder if enabled
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
*
* Outputs: none
*
* Return: none
**************************************************************************************/
void AACFreeDecoder(HAACDecoder hAACDecoder)
{
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo)
return;
#ifdef AAC_ENABLE_SBR
FreeSBR(aacDecInfo);
#endif
FreeBuffers(aacDecInfo);
}
/**************************************************************************************
* Function: AACFindSyncWord
*
* Description: locate the next byte-alinged sync word in the raw AAC stream
*
* Inputs: buffer to search for sync word
* max number of bytes to search in buffer
*
* Outputs: none
*
* Return: offset to first sync word (bytes from start of buf)
* -1 if sync not found after searching nBytes
**************************************************************************************/
int AACFindSyncWord(unsigned char *buf, int nBytes)
{
int i;
/* find byte-aligned syncword (12 bits = 0xFFF) */
for (i = 0; i < nBytes - 1; i++) {
if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL )
return i;
}
return -1;
}
/**************************************************************************************
* Function: AACGetLastFrameInfo
*
* Description: get info about last AAC frame decoded (number of samples decoded,
* sample rate, bit rate, etc.)
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
* pointer to AACFrameInfo struct
*
* Outputs: filled-in AACFrameInfo struct
*
* Return: none
*
* Notes: call this right after calling AACDecode()
**************************************************************************************/
void AACGetLastFrameInfo(HAACDecoder hAACDecoder, AACFrameInfo *aacFrameInfo)
{
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo) {
aacFrameInfo->bitRate = 0;
aacFrameInfo->nChans = 0;
aacFrameInfo->sampRateCore = 0;
aacFrameInfo->sampRateOut = 0;
aacFrameInfo->bitsPerSample = 0;
aacFrameInfo->outputSamps = 0;
aacFrameInfo->profile = 0;
aacFrameInfo->tnsUsed = 0;
aacFrameInfo->pnsUsed = 0;
} else {
aacFrameInfo->bitRate = aacDecInfo->bitRate;
aacFrameInfo->nChans = aacDecInfo->nChans;
aacFrameInfo->sampRateCore = aacDecInfo->sampRate;
aacFrameInfo->sampRateOut = aacDecInfo->sampRate * (aacDecInfo->sbrEnabled ? 2 : 1);
aacFrameInfo->bitsPerSample = 16;
aacFrameInfo->outputSamps = aacDecInfo->nChans * AAC_MAX_NSAMPS * (aacDecInfo->sbrEnabled ? 2 : 1);
aacFrameInfo->profile = aacDecInfo->profile;
aacFrameInfo->tnsUsed = aacDecInfo->tnsUsed;
aacFrameInfo->pnsUsed = aacDecInfo->pnsUsed;
}
}
/**************************************************************************************
* Function: AACSetRawBlockParams
*
* Description: set internal state variables for decoding a stream of raw data blocks
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
* flag indicating source of parameters
* AACFrameInfo struct, with the members nChans, sampRate, and profile
* optionally filled-in
*
* Outputs: updated codec state
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: if copyLast == 1, then the codec sets up its internal state (for
* decoding raw blocks) based on previously-decoded ADTS header info
* if copyLast == 0, then the codec uses the values passed in
* aacFrameInfo to configure its internal state (useful when the
* source is MP4 format, for example)
**************************************************************************************/
int AACSetRawBlockParams(HAACDecoder hAACDecoder, int copyLast, AACFrameInfo *aacFrameInfo)
{
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
aacDecInfo->format = AAC_FF_RAW;
if (copyLast)
return SetRawBlockParams(aacDecInfo, 1, 0, 0, 0);
else
return SetRawBlockParams(aacDecInfo, 0, aacFrameInfo->nChans, aacFrameInfo->sampRateCore, aacFrameInfo->profile);
}
/**************************************************************************************
* Function: AACFlushCodec
*
* Description: flush internal codec state (after seeking, for example)
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int AACFlushCodec(HAACDecoder hAACDecoder)
{
int ch;
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* reset common state variables which change per-frame
* don't touch state variables which are (usually) constant for entire clip
* (nChans, sampRate, profile, format, sbrEnabled)
*/
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
for (ch = 0; ch < MAX_NCHANS_ELEM; ch++)
aacDecInfo->sbDeinterleaveReqd[ch] = 0;
aacDecInfo->adtsBlocksLeft = 0;
aacDecInfo->tnsUsed = 0;
aacDecInfo->pnsUsed = 0;
/* reset internal codec state (flush overlap buffers, etc.) */
FlushCodec(aacDecInfo);
#ifdef AAC_ENABLE_SBR
FlushCodecSBR(aacDecInfo);
#endif
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: AACDecode
*
* Description: decode AAC frame
*
* Inputs: valid AAC decoder instance pointer (HAACDecoder)
* double pointer to buffer of AAC data
* pointer to number of valid bytes remaining in inbuf
* pointer to outbuf, big enough to hold one frame of decoded PCM samples
* (outbuf must be double-sized if SBR enabled)
*
* Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo
* number of output samples = 1024 per channel (2048 if SBR enabled)
* updated inbuf pointer
* updated bytesLeft
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: inbuf pointer and bytesLeft are not updated until whole frame is
* successfully decoded, so if ERR_AAC_INDATA_UNDERFLOW is returned
* just call AACDecode again with more data in inbuf
**************************************************************************************/
int AACDecode(HAACDecoder hAACDecoder, unsigned char **inbuf, int *bytesLeft, short *outbuf)
{
int err, offset, bitOffset, bitsAvail;
int ch, baseChan, elementChans;
unsigned char *inptr;
AACDecInfo *aacDecInfo = (AACDecInfo *)hAACDecoder;
#ifdef AAC_ENABLE_SBR
int baseChanSBR, elementChansSBR;
#endif
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* make local copies (see "Notes" above) */
inptr = *inbuf;
bitOffset = 0;
bitsAvail = (*bytesLeft) << 3;
/* first time through figure out what the file format is */
if (aacDecInfo->format == AAC_FF_Unknown) {
if (bitsAvail < 32)
return ERR_AAC_INDATA_UNDERFLOW;
if (IS_ADIF(inptr)) {
/* unpack ADIF header */
aacDecInfo->format = AAC_FF_ADIF;
err = UnpackADIFHeader(aacDecInfo, &inptr, &bitOffset, &bitsAvail);
if (err)
return err;
} else {
/* assume ADTS by default */
aacDecInfo->format = AAC_FF_ADTS;
}
}
/* if ADTS, search for start of next frame */
if (aacDecInfo->format == AAC_FF_ADTS) {
/* can have 1-4 raw data blocks per ADTS frame (header only present for first one) */
if (aacDecInfo->adtsBlocksLeft == 0) {
offset = AACFindSyncWord(inptr, bitsAvail >> 3);
if (offset < 0)
return ERR_AAC_INDATA_UNDERFLOW;
inptr += offset;
bitsAvail -= (offset << 3);
err = UnpackADTSHeader(aacDecInfo, &inptr, &bitOffset, &bitsAvail);
if (err)
return err;
if (aacDecInfo->nChans == -1) {
/* figure out implicit channel mapping if necessary */
err = GetADTSChannelMapping(aacDecInfo, inptr, bitOffset, bitsAvail);
if (err)
return err;
}
}
aacDecInfo->adtsBlocksLeft--;
} else if (aacDecInfo->format == AAC_FF_RAW) {
err = PrepareRawBlock(aacDecInfo);
if (err)
return err;
}
/* check for valid number of channels */
if (aacDecInfo->nChans > AAC_MAX_NCHANS || aacDecInfo->nChans <= 0)
return ERR_AAC_NCHANS_TOO_HIGH;
/* will be set later if active in this frame */
aacDecInfo->tnsUsed = 0;
aacDecInfo->pnsUsed = 0;
bitOffset = 0;
baseChan = 0;
#ifdef AAC_ENABLE_SBR
baseChanSBR = 0;
#endif
do {
/* parse next syntactic element */
err = DecodeNextElement(aacDecInfo, &inptr, &bitOffset, &bitsAvail);
if (err)
return err;
elementChans = elementNumChans[aacDecInfo->currBlockID];
if (baseChan + elementChans > AAC_MAX_NCHANS)
return ERR_AAC_NCHANS_TOO_HIGH;
/* noiseless decoder and dequantizer */
for (ch = 0; ch < elementChans; ch++) {
PROFILE_START("noiseless decoder");
err = DecodeNoiselessData(aacDecInfo, &inptr, &bitOffset, &bitsAvail, ch);
PROFILE_END();
if (err)
return err;
PROFILE_START("dequant");
if (Dequantize(aacDecInfo, ch))
return ERR_AAC_DEQUANT;
PROFILE_END();
}
PROFILE_START("mid-side and intensity stereo");
/* mid-side and intensity stereo */
if (aacDecInfo->currBlockID == AAC_ID_CPE) {
if (StereoProcess(aacDecInfo))
return ERR_AAC_STEREO_PROCESS;
}
PROFILE_END();
/* PNS, TNS, inverse transform */
for (ch = 0; ch < elementChans; ch++) {
PROFILE_START("PNS");
if (PNS(aacDecInfo, ch))
return ERR_AAC_PNS;
PROFILE_END();
if (aacDecInfo->sbDeinterleaveReqd[ch]) {
/* deinterleave short blocks, if required */
if (DeinterleaveShortBlocks(aacDecInfo, ch))
return ERR_AAC_SHORT_BLOCK_DEINT;
aacDecInfo->sbDeinterleaveReqd[ch] = 0;
}
PROFILE_START("TNS");
if (TNSFilter(aacDecInfo, ch))
return ERR_AAC_TNS;
PROFILE_END();
PROFILE_START("IMDCT");
if (IMDCT(aacDecInfo, ch, baseChan + ch, outbuf))
return ERR_AAC_IMDCT;
PROFILE_END();
}
#ifdef AAC_ENABLE_SBR
if (aacDecInfo->sbrEnabled && (aacDecInfo->currBlockID == AAC_ID_FIL || aacDecInfo->currBlockID == AAC_ID_LFE)) {
if (aacDecInfo->currBlockID == AAC_ID_LFE)
elementChansSBR = elementNumChans[AAC_ID_LFE];
else if (aacDecInfo->currBlockID == AAC_ID_FIL && (aacDecInfo->prevBlockID == AAC_ID_SCE || aacDecInfo->prevBlockID == AAC_ID_CPE))
elementChansSBR = elementNumChans[aacDecInfo->prevBlockID];
else
elementChansSBR = 0;
if (baseChanSBR + elementChansSBR > AAC_MAX_NCHANS)
return ERR_AAC_SBR_NCHANS_TOO_HIGH;
/* parse SBR extension data if present (contained in a fill element) */
if (DecodeSBRBitstream(aacDecInfo, baseChanSBR))
return ERR_AAC_SBR_BITSTREAM;
/* apply SBR */
if (DecodeSBRData(aacDecInfo, baseChanSBR, outbuf))
return ERR_AAC_SBR_DATA;
baseChanSBR += elementChansSBR;
}
#endif
baseChan += elementChans;
} while (aacDecInfo->currBlockID != AAC_ID_END);
/* byte align after each raw_data_block */
if (bitOffset) {
inptr++;
bitsAvail -= (8-bitOffset);
bitOffset = 0;
if (bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
}
/* update pointers */
aacDecInfo->frameCount++;
*bytesLeft -= (inptr - *inbuf);
*inbuf = inptr;
return ERR_AAC_NONE;
}

View File

@@ -1,175 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aacdec.h,v 1.8 2005/11/10 00:15:08 margotm 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
*
* aacdec.h - public C API for AAC decoder
**************************************************************************************/
#ifndef _AACDEC_H
#define _AACDEC_H
#if defined(_WIN32) && !defined(_WIN32_WCE)
#
#elif defined(_WIN32) && defined(_WIN32_WCE) && defined(ARM)
#
#elif defined(_WIN32) && defined(WINCE_EMULATOR)
#
#elif defined (__arm) && defined (__ARMCC_VERSION)
#
#elif defined(_SYMBIAN) && defined(__WINS__)
#
#elif defined(__GNUC__) && defined(__arm__)
#
#elif defined(__GNUC__) && defined(__i386__)
#
#elif defined(__APPLE__)
#
#elif defined(__GNUC__) && defined(__amd64__)
#
#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__))
#
#elif defined(_OPENWAVE_SIMULATOR) || defined(_OPENWAVE_ARMULATOR)
#
#elif defined(_SOLARIS) && !defined(__GNUC__)
#
#elif defined(ESP_PLATFORM)
#
#else
#error No platform defined. See valid options in aacdec.h
#endif
#ifndef USE_DEFAULT_STDLIB
#define USE_DEFAULT_STDLIB
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* according to spec (13818-7 section 8.2.2, 14496-3 section 4.5.3)
* max size of input buffer =
* 6144 bits = 768 bytes per SCE or CCE-I
* 12288 bits = 1536 bytes per CPE
* 0 bits = 0 bytes per CCE-D (uses bits from the SCE/CPE/CCE-I it is coupled to)
*/
#ifndef AAC_MAX_NCHANS /* if max channels isn't set in makefile, */
#define AAC_MAX_NCHANS 2 /* set to default max number of channels */
#endif
#define AAC_MAX_NSAMPS 1024
#define AAC_MAINBUF_SIZE (768 * AAC_MAX_NCHANS)
#define AAC_NUM_PROFILES 3
#define AAC_PROFILE_MP 0
#define AAC_PROFILE_LC 1
#define AAC_PROFILE_SSR 2
/* define these to enable decoder features */
#if defined(HELIX_FEATURE_AUDIO_CODEC_AAC_SBR)
#define AAC_ENABLE_SBR
#endif // HELIX_FEATURE_AUDIO_CODEC_AAC_SBR.
#define AAC_ENABLE_MPEG4
enum {
ERR_AAC_NONE = 0,
ERR_AAC_INDATA_UNDERFLOW = -1,
ERR_AAC_NULL_POINTER = -2,
ERR_AAC_INVALID_ADTS_HEADER = -3,
ERR_AAC_INVALID_ADIF_HEADER = -4,
ERR_AAC_INVALID_FRAME = -5,
ERR_AAC_MPEG4_UNSUPPORTED = -6,
ERR_AAC_CHANNEL_MAP = -7,
ERR_AAC_SYNTAX_ELEMENT = -8,
ERR_AAC_DEQUANT = -9,
ERR_AAC_STEREO_PROCESS = -10,
ERR_AAC_PNS = -11,
ERR_AAC_SHORT_BLOCK_DEINT = -12,
ERR_AAC_TNS = -13,
ERR_AAC_IMDCT = -14,
ERR_AAC_NCHANS_TOO_HIGH = -15,
ERR_AAC_SBR_INIT = -16,
ERR_AAC_SBR_BITSTREAM = -17,
ERR_AAC_SBR_DATA = -18,
ERR_AAC_SBR_PCM_FORMAT = -19,
ERR_AAC_SBR_NCHANS_TOO_HIGH = -20,
ERR_AAC_SBR_SINGLERATE_UNSUPPORTED = -21,
ERR_AAC_RAWBLOCK_PARAMS = -22,
ERR_AAC_UNKNOWN = -9999
};
typedef struct _AACFrameInfo {
int bitRate;
int nChans;
int sampRateCore;
int sampRateOut;
int bitsPerSample;
int outputSamps;
int profile;
int tnsUsed;
int pnsUsed;
} AACFrameInfo;
typedef void *HAACDecoder;
/* public C API */
HAACDecoder AACInitDecoder(void);
HAACDecoder AACInitDecoderPre(void *ptr, int sz);
void AACFreeDecoder(HAACDecoder hAACDecoder);
int AACDecode(HAACDecoder hAACDecoder, unsigned char **inbuf, int *bytesLeft, short *outbuf);
int AACFindSyncWord(unsigned char *buf, int nBytes);
void AACGetLastFrameInfo(HAACDecoder hAACDecoder, AACFrameInfo *aacFrameInfo);
int AACSetRawBlockParams(HAACDecoder hAACDecoder, int copyLast, AACFrameInfo *aacFrameInfo);
int AACFlushCodec(HAACDecoder hAACDecoder);
#ifdef HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT
int AACInitTrigtabsFloat(void);
void AACFreeTrigtabsFloat(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _AACDEC_H */

View File

@@ -1,157 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: aactabs.c,v 1.1 2005/02/26 01:47:31 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* aactabs.c - platform-independent tables for AAC decoder (global, read-only)
**************************************************************************************/
#include "aaccommon.h"
/* sample rates (table 4.5.1) */
const int sampRateTab[NUM_SAMPLE_RATES] PROGMEM = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000
};
/* max scalefactor band for prediction (main profile only) */
const int predSFBMax[NUM_SAMPLE_RATES] PROGMEM = {
33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34
};
/* channel mapping (table 1.6.3.4) (-1 = unknown, so need to determine mapping based on rules in 8.5.1) */
const int channelMapTab[NUM_DEF_CHAN_MAPS] PROGMEM = {
-1, 1, 2, 3, 4, 5, 6, 8
};
/* number of channels in each element (SCE, CPE, etc.)
* see AACElementID in aaccommon.h
*/
const int elementNumChans[NUM_ELEMENTS] PROGMEM = {
1, 2, 0, 1, 0, 0, 0, 0
};
/* total number of scale factor bands in one window */
const unsigned int /*char*/ sfBandTotalShort[NUM_SAMPLE_RATES] PROGMEM = {
12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15
};
const unsigned int /*char*/ sfBandTotalLong[NUM_SAMPLE_RATES] PROGMEM = {
41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40
};
/* scale factor band tables */
const int sfBandTabShortOffset[NUM_SAMPLE_RATES] PROGMEM = {0, 0, 0, 13, 13, 13, 28, 28, 44, 44, 44, 60};
const /*short*/ int sfBandTabShort[76] PROGMEM = {
/* short block 64, 88, 96 kHz [13] (tables 4.5.24, 4.5.26) */
0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128,
/* short block 32, 44, 48 kHz [15] (table 4.5.15) */
0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128,
/* short block 22, 24 kHz [16] (table 4.5.22) */
0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128,
/* short block 11, 12, 16 kHz [16] (table 4.5.20) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, 108, 128,
/* short block 8 kHz [16] (table 4.5.18) */
0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88, 108, 128
};
const int sfBandTabLongOffset[NUM_SAMPLE_RATES] PROGMEM = {0, 0, 42, 90, 90, 140, 192, 192, 240, 240, 240, 284};
const /*short*/ int sfBandTabLong[325] PROGMEM = {
/* long block 88, 96 kHz [42] (table 4.5.25) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212,
240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024,
/* long block 64 kHz [48] (table 4.5.13) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64,
72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, 344, 384,
424, 464, 504, 544, 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024,
/* long block 44, 48 kHz [50] (table 4.5.14) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88,
96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448,
480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024,
/* long block 32 kHz [52] (table 4.5.16) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88, 96,
108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512,
544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024,
/* long block 22, 24 kHz [48] (table 4.5.21) */
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 76,
84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, 220, 240, 260, 284,
308, 336, 364, 396, 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024,
/* long block 11, 12, 16 kHz [44] (table 4.5.19) */
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124,
136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, 368,
396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024,
/* long block 8 kHz [41] (table 4.5.17) */
0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156,
172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420,
448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024
};
/* TNS max bands (table 4.139) and max order (table 4.138) */
const int tnsMaxBandsShortOffset[AAC_NUM_PROFILES] PROGMEM = {0, 0, 12};
const unsigned /*char*/ int tnsMaxBandsShort[2*NUM_SAMPLE_RATES] PROGMEM = {
9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, /* short block, Main/LC */
7, 7, 7, 6, 6, 6, 7, 7, 8, 8, 8, 7 /* short block, SSR */
};
const unsigned /*char*/ int tnsMaxOrderShort[AAC_NUM_PROFILES] PROGMEM = {7, 7, 7};
const int tnsMaxBandsLongOffset[AAC_NUM_PROFILES] PROGMEM = {0, 0, 12};
const unsigned int /*char*/ tnsMaxBandsLong[2*NUM_SAMPLE_RATES] PROGMEM = {
31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39, /* long block, Main/LC */
28, 28, 27, 26, 26, 26, 29, 29, 23, 23, 23, 19, /* long block, SSR */
};
const unsigned /*char*/ int tnsMaxOrderLong[AAC_NUM_PROFILES] PROGMEM = {20, 12, 12};

View File

@@ -1,728 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: assembly.h,v 1.7 2005/11/10 00:04:40 margotm 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
*
* assembly.h - inline assembly language functions and prototypes
*
* MULSHIFT32(x, y) signed multiply of two 32-bit integers (x and y),
* returns top 32-bits of 64-bit result
* CLIPTOSHORT(x) convert 32-bit integer to 16-bit short,
* clipping to [-32768, 32767]
* FASTABS(x) branchless absolute value of signed integer x
* CLZ(x) count leading zeros on signed integer x
* MADD64(sum64, x, y) 64-bit multiply accumulate: sum64 += (x*y)
**************************************************************************************/
#ifndef _ASSEMBLY_H
#define _ASSEMBLY_H
/* toolchain: MSFT Visual C++
* target architecture: x86
*/
#if (defined (_WIN32) && !defined (_WIN32_WCE)) || (defined (__WINS__) && defined (_SYMBIAN)) || (defined (WINCE_EMULATOR)) || (defined (_OPENWAVE_SIMULATOR))
#pragma warning( disable : 4035 ) /* complains about inline asm not returning a value */
static __inline int MULSHIFT32(int x, int y)
{
__asm {
mov eax, x
imul y
mov eax, edx
}
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
#ifdef __CW32__
typedef long long Word64;
#else
typedef __int64 Word64;
#endif
typedef union _U64 {
Word64 w64;
struct {
/* x86 = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
/* returns 64-bit value in [edx:eax] */
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
#if (defined (_SYMBIAN_61_) || defined (_SYMBIAN_70_)) && defined (__WINS__) && !defined (__CW32__)
/* Workaround for the Symbian emulator because of non existing longlong.lib and
* hence __allmul not defined. */
__asm {
mov eax, x
imul y
add dword ptr sum64, eax
adc dword ptr sum64 + 4, edx
}
#else
sum64 += (Word64)x * (Word64)y;
#endif
return sum64;
}
/* toolchain: MSFT Embedded Visual C++
* target architecture: ARM v.4 and above (require 'M' type processor for 32x32->64 multiplier)
*/
#elif defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
/* implemented in asmfunc.s */
#ifdef __cplusplus
extern "C" {
#endif
typedef __int64 Word64;
typedef union _U64 {
Word64 w64;
struct {
/* ARM WinCE = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
/* manual name mangling for just this platform (must match labels in .s file) */
#define MULSHIFT32 raac_MULSHIFT32
#define MADD64 raac_MADD64
int MULSHIFT32(int x, int y);
Word64 MADD64(Word64 sum64, int x, int y);
#ifdef __cplusplus
}
#endif
/* toolchain: ARM ADS or RealView
* target architecture: ARM v.4 and above (requires 'M' type processor for 32x32->64 multiplier)
*/
#elif defined (XXX__arm) && defined (__ARMCC_VERSION)
static __inline int MULSHIFT32(int x, int y)
{
/* rules for smull RdLo, RdHi, Rm, Rs:
* RdHi != Rm
* RdLo != Rm
* RdHi != RdLo
*/
int zlow;
__asm {
smull zlow,y,x,y
}
return y;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
/* ARM code would look like this, but do NOT use inline asm in ADS for this,
because you can't safely use the status register flags intermixed with C code
__asm {
mov numZeros, #1
tst x, 0xffff0000
addeq numZeros, numZeros, #16
moveq x, x, lsl #16
tst x, 0xff000000
addeq numZeros, numZeros, #8
moveq x, x, lsl #8
tst x, 0xf0000000
addeq numZeros, numZeros, #4
moveq x, x, lsl #4
tst x, 0xc0000000
addeq numZeros, numZeros, #2
moveq x, x, lsl #2
sub numZeros, numZeros, x, lsr #31
}
*/
/* reference:
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
*/
}
typedef __int64 Word64;
typedef union _U64 {
Word64 w64;
struct {
/* ARM ADS = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
U64 u;
u.w64 = sum64;
__asm {
smlal u.r.lo32, u.r.hi32, x, y
}
return u.w64;
}
/* toolchain: ARM gcc
* target architecture: ARM v.4 and above (requires 'M' type processor for 32x32->64 multiplier)
*/
#elif defined(__GNUC__) && defined(XXXX__arm__)
static inline int MULSHIFT32(int x, int y)
{
int zlow;
asm ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y) : "cc");
return y;
}
/*
static inline short CLIPTOSHORT(int x)
{
int sign;
// clip to [-32768, 32767] //
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
*/
static inline short CLIPTOSHORT(int x)
{
asm ("ssat %0, #16, %1" : "=r" (x) : "r" (x));
return x;
}
/* From coder.h, ORIGINAL:
clip to [-2^n, 2^n-1], valid range of n = [1, 30]
//TODO (FB) Is there a better way ?
*/
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (n)) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
/* From coder.h, ORIGINAL:
do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit)
*/
//TODO (FB) Is there a better way ?
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
#define FASTABS(x) abs(x) //FB
#define CLZ(x) __builtin_clz(x) //FB
//Reverse byte order (16 bit) //FB
static inline unsigned int REV16( unsigned int value)
{
asm ("rev16 %0, %1" : "=r" (value) : "r" (value) );
return(value);
}
//Reverse byte order (32 bit) //FB
static inline unsigned int REV32( unsigned int value)
{
asm ("rev %0, %1" : "=r" (value) : "r" (value) );
return(value);
}
typedef long long Word64;
typedef union _U64 {
Word64 w64;
struct {
/* little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static inline Word64 MADD64(Word64 sum64, int x, int y)
{
U64 u;
u.w64 = sum64;
asm ("smlal %0,%1,%2,%3" : "+&r" (u.r.lo32), "+&r" (u.r.hi32) : "r" (x), "r" (y) : "cc");
return u.w64;
}
/* toolchain: x86 gcc
* target architecture: x86
*/
#elif defined(__APPLE__) || defined(__GNUC__) && (defined(__i386__) || defined(__amd64__)) || (defined (_SOLARIS) && !defined (__GNUC__) && defined(_SOLARISX86))
typedef long long Word64;
static __inline__ int MULSHIFT32(int x, int y)
{
int z;
z = (Word64)x * (Word64)y >> 32;
return z;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
typedef union _U64 {
Word64 w64;
struct {
/* x86 = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
#elif defined(__arm__)
typedef long long Word64;
typedef union _U64 {
Word64 w64;
struct {
/* x86 = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
#if defined(ARM7DI)
static __inline int MULSHIFT32(int x, int y) {
return x * y;
}
#else
static __inline int MULSHIFT32(int x, int y)
{
/* important rules for smull RdLo, RdHi, Rm, Rs:
* RdHi and Rm can't be the same register
* RdLo and Rm can't be the same register
* RdHi and RdLo can't be the same register
* Note: Rs determines early termination (leading sign bits) so if you want to specify
* which operand is Rs, put it in the SECOND argument (y)
* For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter
* which one is returned. (If this were a function call, returning y (R1) would
* require an extra "mov r0, r1")
*/
int zlow;
__asm__ volatile ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y)) ;
return y;
}
#endif
static __inline int FASTABS(int x)
{
int t=0; /*Really is not necessary to initialiaze only to avoid warning*/
__asm__ volatile (
"eor %0,%2,%2, asr #31;"
"sub %0,%1,%2, asr #31;"
: "=&r" (t)
: "0" (t), "r" (x)
);
return t;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
#elif defined(ESP_PLATFORM) || defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__)) || (defined (_SOLARIS) && !defined (__GNUC__) && !defined (_SOLARISX86))
typedef long long Word64;
static __inline__ int MULSHIFT32(int x, int y)
{
int z;
z = (Word64)x * (Word64)y >> 32;
return z;
}
static __inline short CLIPTOSHORT(int x)
{
int sign;
/* clip to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return 32;
/* count leading zeros with binary search (function should be 17 ARM instructions total) */
numZeros = 1;
if (!((unsigned int)x >> 16)) { numZeros += 16; x <<= 16; }
if (!((unsigned int)x >> 24)) { numZeros += 8; x <<= 8; }
if (!((unsigned int)x >> 28)) { numZeros += 4; x <<= 4; }
if (!((unsigned int)x >> 30)) { numZeros += 2; x <<= 2; }
numZeros -= ((unsigned int)x >> 31);
return numZeros;
}
typedef union _U64 {
Word64 w64;
struct {
#ifdef __XTENSA__
unsigned int lo32;
signed int hi32;
#else
/* PowerPC = big endian */
signed int hi32;
unsigned int lo32;
#endif
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
/* From coder.h, ORIGINAL:
clip to [-2^n, 2^n-1], valid range of n = [1, 30]
//TODO (FB) Is there a better way ?
*/
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (n)) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
/* From coder.h, ORIGINAL:
do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit)
*/
//TODO (FB) Is there a better way ?
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
//#define FASTABS(x) abs(x) //FB
//#define CLZ(x) __builtin_clz(x) //FB
#else
#error Unsupported platform in assembly.h
#endif /* platforms */
#ifndef CLIP_2N
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (n)) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
#endif
#ifndef CLIP_2N_SHIFT
/* From coder.h, ORIGINAL:
do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit)
*/
//TODO (FB) Is there a better way ?
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
#endif
#endif /* _ASSEMBLY_H */

View File

@@ -1,261 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: bitstream.c,v 1.2 2005/09/27 20:31:11 jrecker 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
*
* bitstream.c - bitstream parsing functions
**************************************************************************************/
#include "bitstream.h"
/**************************************************************************************
* Function: SetBitstreamPointer
*
* Description: initialize bitstream reader
*
* Inputs: pointer to BitStreamInfo struct
* number of bytes in bitstream
* pointer to byte-aligned buffer of data to read from
*
* Outputs: initialized bitstream info struct
*
* Return: none
**************************************************************************************/
void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf)
{
/* init bitstream */
bsi->bytePtr = buf;
bsi->iCache = 0; /* 4-byte unsigned int */
bsi->cachedBits = 0; /* i.e. zero bits in cache */
bsi->nBytes = nBytes;
}
/**************************************************************************************
* Function: RefillBitstreamCache
*
* Description: read new data from bitstream buffer into 32-bit cache
*
* Inputs: pointer to initialized BitStreamInfo struct
*
* Outputs: updated bitstream info struct
*
* Return: none
*
* Notes: only call when iCache is completely drained (resets bitOffset to 0)
* always loads 4 new bytes except when bsi->nBytes < 4 (end of buffer)
* stores data as big-endian in cache, regardless of machine endian-ness
**************************************************************************************/
//Optimized for REV16, REV32 (FB)
static __inline void RefillBitstreamCache(BitStreamInfo *bsi)
{
int nBytes = bsi->nBytes;
if (nBytes >= 4) {
/* optimize for common case, independent of machine endian-ness */
bsi->iCache = (*bsi->bytePtr++) << 24;
bsi->iCache |= (*bsi->bytePtr++) << 16;
bsi->iCache |= (*bsi->bytePtr++) << 8;
bsi->iCache |= (*bsi->bytePtr++);
bsi->cachedBits = 32;
bsi->nBytes -= 4;
} else {
bsi->iCache = 0;
while (nBytes--) {
bsi->iCache |= (*bsi->bytePtr++);
bsi->iCache <<= 8;
}
bsi->iCache <<= ((3 - bsi->nBytes)*8);
bsi->cachedBits = 8*bsi->nBytes;
bsi->nBytes = 0;
}
}
/**************************************************************************************
* Function: GetBits
*
* Description: get bits from bitstream, advance bitstream pointer
*
* Inputs: pointer to initialized BitStreamInfo struct
* number of bits to get from bitstream
*
* Outputs: updated bitstream info struct
*
* Return: the next nBits bits of data from bitstream buffer
*
* Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f
* for speed, does not indicate error if you overrun bit buffer
* if nBits == 0, returns 0
**************************************************************************************/
unsigned int GetBits(BitStreamInfo *bsi, int nBits)
{
unsigned int data, lowBits;
nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */
data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */
data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */
bsi->iCache <<= nBits; /* left-justify cache */
bsi->cachedBits -= nBits; /* how many bits have we drawn from the cache so far */
/* if we cross an int boundary, refill the cache */
if (bsi->cachedBits < 0) {
lowBits = -bsi->cachedBits;
RefillBitstreamCache(bsi);
data |= bsi->iCache >> (32 - lowBits); /* get the low-order bits */
bsi->cachedBits -= lowBits; /* how many bits have we drawn from the cache so far */
bsi->iCache <<= lowBits; /* left-justify cache */
}
return data;
}
/**************************************************************************************
* Function: GetBitsNoAdvance
*
* Description: get bits from bitstream, do not advance bitstream pointer
*
* Inputs: pointer to initialized BitStreamInfo struct
* number of bits to get from bitstream
*
* Outputs: none (state of BitStreamInfo struct left unchanged)
*
* Return: the next nBits bits of data from bitstream buffer
*
* Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f
* for speed, does not indicate error if you overrun bit buffer
* if nBits == 0, returns 0
**************************************************************************************/
unsigned int GetBitsNoAdvance(BitStreamInfo *bsi, int nBits)
{
unsigned char *buf;
unsigned int data, iCache;
signed int lowBits;
nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */
data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */
data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */
lowBits = nBits - bsi->cachedBits; /* how many bits do we have left to read */
/* if we cross an int boundary, read next bytes in buffer */
if (lowBits > 0) {
iCache = 0;
buf = bsi->bytePtr;
while (lowBits > 0) {
iCache <<= 8;
if (buf < bsi->bytePtr + bsi->nBytes)
iCache |= (unsigned int)*buf++;
lowBits -= 8;
}
lowBits = -lowBits;
data |= iCache >> lowBits;
}
return data;
}
/**************************************************************************************
* Function: AdvanceBitstream
*
* Description: move bitstream pointer ahead
*
* Inputs: pointer to initialized BitStreamInfo struct
* number of bits to advance bitstream
*
* Outputs: updated bitstream info struct
*
* Return: none
*
* Notes: generally used following GetBitsNoAdvance(bsi, maxBits)
**************************************************************************************/
void AdvanceBitstream(BitStreamInfo *bsi, int nBits)
{
nBits &= 0x1f;
if (nBits > bsi->cachedBits) {
nBits -= bsi->cachedBits;
RefillBitstreamCache(bsi);
}
bsi->iCache <<= nBits;
bsi->cachedBits -= nBits;
}
/**************************************************************************************
* Function: CalcBitsUsed
*
* Description: calculate how many bits have been read from bitstream
*
* Inputs: pointer to initialized BitStreamInfo struct
* pointer to start of bitstream buffer
* bit offset into first byte of startBuf (0-7)
*
* Outputs: none
*
* Return: number of bits read from bitstream, as offset from startBuf:startOffset
**************************************************************************************/
int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset)
{
int bitsUsed;
bitsUsed = (bsi->bytePtr - startBuf) * 8;
bitsUsed -= bsi->cachedBits;
bitsUsed -= startOffset;
return bitsUsed;
}
/**************************************************************************************
* Function: ByteAlignBitstream
*
* Description: bump bitstream pointer to start of next byte
*
* Inputs: pointer to initialized BitStreamInfo struct
*
* Outputs: byte-aligned bitstream BitStreamInfo struct
*
* Return: none
*
* Notes: if bitstream is already byte-aligned, do nothing
**************************************************************************************/
void ByteAlignBitstream(BitStreamInfo *bsi)
{
int offset;
offset = bsi->cachedBits & 0x07;
AdvanceBitstream(bsi, offset);
}

View File

@@ -1,74 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: bitstream.h,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* bitstream.h - definitions of bitstream handling functions
**************************************************************************************/
#ifndef _BITSTREAM_H
#define _BITSTREAM_H
#include "aaccommon.h"
/* additional external symbols to name-mangle for static linking */
#define SetBitstreamPointer STATNAME(SetBitstreamPointer)
#define GetBits STATNAME(GetBits)
#define GetBitsNoAdvance STATNAME(GetBitsNoAdvance)
#define AdvanceBitstream STATNAME(AdvanceBitstream)
#define CalcBitsUsed STATNAME(CalcBitsUsed)
#define ByteAlignBitstream STATNAME(ByteAlignBitstream)
typedef struct _BitStreamInfo {
unsigned char *bytePtr;
unsigned int iCache;
int cachedBits;
int nBytes;
} BitStreamInfo;
/* bitstream.c */
void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf);
unsigned int GetBits(BitStreamInfo *bsi, int nBits);
unsigned int GetBitsNoAdvance(BitStreamInfo *bsi, int nBits);
void AdvanceBitstream(BitStreamInfo *bsi, int nBits);
int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset);
void ByteAlignBitstream(BitStreamInfo *bsi);
#endif /* _BITSTREAM_H */

View File

@@ -1,165 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: buffers.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* buffers.c - allocation and deallocation of internal AAC decoder buffers
**************************************************************************************/
#if defined(USE_DEFAULT_STDLIB) || defined(ESP_PLATFORM)
#include <stdlib.h>
#else
#include "hlxclib/stdlib.h"
#endif
#include "coder.h"
/**************************************************************************************
* Function: ClearBuffer
*
* Description: fill buffer with 0's
*
* Inputs: pointer to buffer
* number of bytes to fill with 0
*
* Outputs: cleared buffer
*
* Return: none
*
* Notes: slow, platform-independent equivalent to memset(buf, 0, nBytes)
**************************************************************************************/
#include <string.h>
void ClearBuffer(void *buf, int nBytes)
{
/* int i;
unsigned char *cbuf = (unsigned char *)buf;
for (i = 0; i < nBytes; i++)
cbuf[i] = 0;
return;
*/
memset(buf, 0, nBytes);
}
/**************************************************************************************
* Function: AllocateBuffers
*
* Description: allocate all the memory needed for the AAC decoder
*
* Inputs: none
*
* Outputs: none
*
* Return: pointer to AACDecInfo structure, cleared to all 0's (except for
* pointer to platform-specific data structure)
*
* Notes: if one or more mallocs fail, function frees any buffers already
* allocated before returning
**************************************************************************************/
AACDecInfo *AllocateBuffers(void)
{
AACDecInfo *aacDecInfo;
aacDecInfo = (AACDecInfo *)malloc(sizeof(AACDecInfo));
if (!aacDecInfo)
return 0;
ClearBuffer(aacDecInfo, sizeof(AACDecInfo));
aacDecInfo->psInfoBase = malloc(sizeof(PSInfoBase));
if (!aacDecInfo->psInfoBase) {
FreeBuffers(aacDecInfo);
return 0;
}
ClearBuffer(aacDecInfo->psInfoBase, sizeof(PSInfoBase));
return aacDecInfo;
}
AACDecInfo *AllocateBuffersPre(void **ptr, int *sz)
{
AACDecInfo *aacDecInfo;
char *p = (char*)*ptr;
aacDecInfo = (AACDecInfo *)p;
p += (sizeof(AACDecInfo) +7 ) & ~7;
*sz -= (sizeof(AACDecInfo) +7 ) & ~7;
if (*sz < 0)
return 0;
ClearBuffer(aacDecInfo, sizeof(AACDecInfo));
aacDecInfo->psInfoBase = (PSInfoBase*)p;
p += (sizeof(PSInfoBase) + 7) & ~7;
*sz -= (sizeof(PSInfoBase) + 7) & ~7;
if (*sz <0) {
return 0;
}
ClearBuffer(aacDecInfo->psInfoBase, sizeof(PSInfoBase));
*ptr = p;
return aacDecInfo;
}
#ifndef SAFE_FREE
#define SAFE_FREE(x) {if (x) free(x); (x) = 0;} /* helper macro */
#endif
/**************************************************************************************
* Function: FreeBuffers
*
* Description: frees all the memory used by the AAC decoder
*
* Inputs: pointer to initialized AACDecInfo structure
*
* Outputs: none
*
* Return: none
*
* Notes: safe to call even if some buffers were not allocated (uses SAFE_FREE)
**************************************************************************************/
void FreeBuffers(AACDecInfo *aacDecInfo)
{
if (!aacDecInfo)
return;
SAFE_FREE(aacDecInfo->psInfoBase);
SAFE_FREE(aacDecInfo);
}

View File

@@ -1,373 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: coder.h,v 1.2 2005/06/27 21:06:00 gwright 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
*
* coder.h - definitions of platform-specific data structures, functions, and tables
**************************************************************************************/
#ifndef _CODER_H
#define _CODER_H
#include "aaccommon.h"
#include "bitstream.h"
#ifndef ASSERT
#if defined(_WIN32) && defined(_M_IX86) && (defined (_DEBUG) || defined (REL_ENABLE_ASSERTS))
#define ASSERT(x) if (!(x)) __asm int 3;
#else
#define ASSERT(x) /* do nothing */
#endif
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#define NWINDOWS_LONG 1
#define NWINDOWS_SHORT 8
#define DATA_BUF_SIZE 510 /* max count = 255 + 255 */
#define FILL_BUF_SIZE 269 /* max count = 15 + 255 - 1*/
#define ADIF_COPYID_SIZE 9
#define MAX_COMMENT_BYTES 255
#define MAX_NUM_FCE 15
#define MAX_NUM_SCE 15
#define MAX_NUM_BCE 15
#define MAX_NUM_LCE 3
#define MAX_NUM_ADE 7
#define MAX_NUM_CCE 15
#define CHAN_ELEM_IS_CPE(x) (((x) & 0x10) >> 4) /* bit 4 = SCE/CPE flag */
#define CHAN_ELEM_GET_TAG(x) (((x) & 0x0f) >> 0) /* bits 3-0 = instance tag */
#define CHAN_ELEM_SET_CPE(x) (((x) & 0x01) << 4) /* bit 4 = SCE/CPE flag */
#define CHAN_ELEM_SET_TAG(x) (((x) & 0x0f) << 0) /* bits 3-0 = instance tag */
#define MAX_HUFF_BITS 20
#define HUFFTAB_SPEC_OFFSET 1
/* do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit) */
/*
#define CLIP_2N_SHIFT(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
*/
/* clip to [-2^n, 2^n-1], valid range of n = [1, 30] */
/*
#define CLIP_2N(val, n) { \
if ((val) >> 31 != (val) >> (n)) \
(val) = ((val) >> 31) ^ ((1 << (n)) - 1); \
}
*/
#define SF_DQ_OFFSET 15
#define FBITS_OUT_DQ 20
#define FBITS_OUT_DQ_OFF (FBITS_OUT_DQ - SF_DQ_OFFSET) /* number of fraction bits out of dequant, including 2^15 bias */
#define FBITS_IN_IMDCT FBITS_OUT_DQ_OFF /* number of fraction bits into IMDCT */
#define GBITS_IN_DCT4 4 /* min guard bits in for DCT4 */
#define FBITS_LOST_DCT4 1 /* number of fraction bits lost (>> out) in DCT-IV */
#define FBITS_LOST_WND 1 /* number of fraction bits lost (>> out) in synthesis window (neg = gain frac bits) */
#define FBITS_LOST_IMDCT (FBITS_LOST_DCT4 + FBITS_LOST_WND)
#define FBITS_OUT_IMDCT (FBITS_IN_IMDCT - FBITS_LOST_IMDCT)
#define NUM_IMDCT_SIZES 2
/* additional external symbols to name-mangle for static linking */
#define DecodeProgramConfigElement STATNAME(DecodeProgramConfigElement)
#define DecodeHuffmanScalar STATNAME(DecodeHuffmanScalar)
#define DecodeSpectrumLong STATNAME(DecodeSpectrumLong)
#define DecodeSpectrumShort STATNAME(DecodeSpectrumShort)
#define DecodeICSInfo STATNAME(DecodeICSInfo)
#define DCT4 STATNAME(DCT4)
#define R4FFT STATNAME(R4FFT)
#define DecWindowOverlapNoClip STATNAME(DecWindowOverlapNoClip)
#define DecWindowOverlapLongStartNoClip STATNAME(DecWindowOverlapLongStartNoClip)
#define DecWindowOverlapLongStopNoClip STATNAME(DecWindowOverlapLongStopNoClip)
#define DecWindowOverlapShortNoClip STATNAME(DecWindowOverlapShortNoClip)
#define huffTabSpecInfo STATNAME(huffTabSpecInfo)
#define huffTabSpec STATNAME(huffTabSpec)
#define huffTabScaleFactInfo STATNAME(huffTabScaleFactInfo)
#define huffTabScaleFact STATNAME(huffTabScaleFact)
#define cos4sin4tab STATNAME(cos4sin4tab)
#define cos4sin4tabOffset STATNAME(cos4sin4tabOffset)
#define cos1sin1tab STATNAME(cos1sin1tab)
#define sinWindow STATNAME(sinWindow)
#define sinWindowOffset STATNAME(sinWindowOffset)
#define kbdWindow STATNAME(kbdWindow)
#define kbdWindowOffset STATNAME(kbdWindowOffset)
#define bitrevtab STATNAME(bitrevtab)
#define bitrevtabOffset STATNAME(bitrevtabOffset)
#define uniqueIDTab STATNAME(uniqueIDTab)
#define twidTabEven STATNAME(twidTabEven)
#define twidTabOdd STATNAME(twidTabOdd)
typedef struct _HuffInfo {
int maxBits; /* number of bits in longest codeword */
unsigned /*char*/ int count[MAX_HUFF_BITS]; /* count[i] = number of codes with length i+1 bits */
int offset; /* offset into symbol table */
} HuffInfo;
typedef struct _PulseInfo {
unsigned char pulseDataPresent;
unsigned char numPulse;
unsigned char startSFB;
unsigned char offset[MAX_PULSES];
unsigned char amp[MAX_PULSES];
} PulseInfo;
typedef struct _TNSInfo {
unsigned char tnsDataPresent;
unsigned char numFilt[MAX_TNS_FILTERS]; /* max 1 filter each for 8 short windows, or 3 filters for 1 long window */
unsigned char coefRes[MAX_TNS_FILTERS];
unsigned char length[MAX_TNS_FILTERS];
unsigned char order[MAX_TNS_FILTERS];
unsigned char dir[MAX_TNS_FILTERS];
signed char coef[MAX_TNS_COEFS]; /* max 3 filters * 20 coefs for 1 long window, or 1 filter * 7 coefs for each of 8 short windows */
} TNSInfo;
typedef struct _GainControlInfo {
unsigned char gainControlDataPresent;
unsigned char maxBand;
unsigned char adjNum[MAX_GAIN_BANDS][MAX_GAIN_WIN];
unsigned char alevCode[MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST];
unsigned char alocCode[MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST];
} GainControlInfo;
typedef struct _ICSInfo {
unsigned char icsResBit;
unsigned char winSequence;
unsigned char winShape;
unsigned char maxSFB;
unsigned char sfGroup;
unsigned char predictorDataPresent;
unsigned char predictorReset;
unsigned char predictorResetGroupNum;
unsigned char predictionUsed[MAX_PRED_SFB];
unsigned char numWinGroup;
unsigned char winGroupLen[MAX_WIN_GROUPS];
} ICSInfo;
typedef struct _ADTSHeader {
/* fixed */
unsigned char id; /* MPEG bit - should be 1 */
unsigned char layer; /* MPEG layer - should be 0 */
unsigned char protectBit; /* 0 = CRC word follows, 1 = no CRC word */
unsigned char profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
unsigned char sampRateIdx; /* sample rate index range = [0, 11] */
unsigned char privateBit; /* ignore */
unsigned char channelConfig; /* 0 = implicit, >0 = use default table */
unsigned char origCopy; /* 0 = copy, 1 = original */
unsigned char home; /* ignore */
/* variable */
unsigned char copyBit; /* 1 bit of the 72-bit copyright ID (transmitted as 1 bit per frame) */
unsigned char copyStart; /* 1 = this bit starts the 72-bit ID, 0 = it does not */
int frameLength; /* length of frame */
int bufferFull; /* number of 32-bit words left in enc buffer, 0x7FF = VBR */
unsigned char numRawDataBlocks; /* number of raw data blocks in frame */
/* CRC */
int crcCheckWord; /* 16-bit CRC check word (present if protectBit == 0) */
} ADTSHeader;
typedef struct _ADIFHeader {
unsigned char copyBit; /* 0 = no copyright ID, 1 = 72-bit copyright ID follows immediately */
unsigned char origCopy; /* 0 = copy, 1 = original */
unsigned char home; /* ignore */
unsigned char bsType; /* bitstream type: 0 = CBR, 1 = VBR */
int bitRate; /* bitRate: CBR = bits/sec, VBR = peak bits/frame, 0 = unknown */
unsigned char numPCE; /* number of program config elements (max = 16) */
int bufferFull; /* bits left in bit reservoir */
unsigned char copyID[ADIF_COPYID_SIZE]; /* optional 72-bit copyright ID */
} ADIFHeader;
/* sizeof(ProgConfigElement) = 82 bytes (if KEEP_PCE_COMMENTS not defined) */
typedef struct _ProgConfigElement {
unsigned char elemInstTag; /* element instance tag */
unsigned char profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
unsigned char sampRateIdx; /* sample rate index range = [0, 11] */
unsigned char numFCE; /* number of front channel elements (max = 15) */
unsigned char numSCE; /* number of side channel elements (max = 15) */
unsigned char numBCE; /* number of back channel elements (max = 15) */
unsigned char numLCE; /* number of LFE channel elements (max = 3) */
unsigned char numADE; /* number of associated data elements (max = 7) */
unsigned char numCCE; /* number of valid channel coupling elements (max = 15) */
unsigned char monoMixdown; /* mono mixdown: bit 4 = present flag, bits 3-0 = element number */
unsigned char stereoMixdown; /* stereo mixdown: bit 4 = present flag, bits 3-0 = element number */
unsigned char matrixMixdown; /* matrix mixdown: bit 4 = present flag, bit 3 = unused,
bits 2-1 = index, bit 0 = pseudo-surround enable */
unsigned char fce[MAX_NUM_FCE]; /* front element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
unsigned char sce[MAX_NUM_SCE]; /* side element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
unsigned char bce[MAX_NUM_BCE]; /* back element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
unsigned char lce[MAX_NUM_LCE]; /* instance tag for LFE elements */
unsigned char ade[MAX_NUM_ADE]; /* instance tag for ADE elements */
unsigned char cce[MAX_NUM_BCE]; /* channel coupling elements: bit 4 = switching flag, bits 3-0 = inst tag */
#ifdef KEEP_PCE_COMMENTS
/* make this optional - if not enabled, decoder will just skip comments */
unsigned char commentBytes;
unsigned char commentField[MAX_COMMENT_BYTES];
#endif
} ProgConfigElement;
/* state info struct for baseline (MPEG-4 LC) decoding */
typedef struct _PSInfoBase {
/* header information */
ADTSHeader fhADTS;
ADIFHeader fhADIF;
ProgConfigElement pce[MAX_NUM_PCE_ADIF];
int dataCount;
unsigned char dataBuf[DATA_BUF_SIZE];
int fillCount;
unsigned char fillBuf[FILL_BUF_SIZE];
/* state information which is the same throughout whole frame */
int nChans;
int useImpChanMap;
int sampRateIdx;
/* state information which can be overwritten by subsequent elements within frame */
ICSInfo icsInfo[MAX_NCHANS_ELEM];
int commonWin;
short scaleFactors[MAX_NCHANS_ELEM][MAX_SF_BANDS];
unsigned char sfbCodeBook[MAX_NCHANS_ELEM][MAX_SF_BANDS];
int msMaskPresent;
unsigned char msMaskBits[MAX_MS_MASK_BYTES];
int pnsUsed[MAX_NCHANS_ELEM];
int pnsLastVal;
int intensityUsed[MAX_NCHANS_ELEM];
PulseInfo pulseInfo[MAX_NCHANS_ELEM];
TNSInfo tnsInfo[MAX_NCHANS_ELEM];
int tnsLPCBuf[MAX_TNS_ORDER];
int tnsWorkBuf[MAX_TNS_ORDER];
GainControlInfo gainControlInfo[MAX_NCHANS_ELEM];
int gbCurrent[MAX_NCHANS_ELEM];
int coef[MAX_NCHANS_ELEM][AAC_MAX_NSAMPS];
#ifdef AAC_ENABLE_SBR
int sbrWorkBuf[MAX_NCHANS_ELEM][AAC_MAX_NSAMPS];
#endif
/* state information which must be saved for each element and used in next frame */
int overlap[AAC_MAX_NCHANS][AAC_MAX_NSAMPS];
int prevWinShape[AAC_MAX_NCHANS];
} PSInfoBase;
/* private implementation-specific functions */
/* decelmnt.c */
int DecodeProgramConfigElement(ProgConfigElement *pce, BitStreamInfo *bsi);
/* huffman.c */
int DecodeHuffmanScalar(const signed short *huffTab, const HuffInfo *huffTabInfo, unsigned int bitBuf, signed int *val);
void DecodeSpectrumLong(PSInfoBase *psi, BitStreamInfo *bsi, int ch);
void DecodeSpectrumShort(PSInfoBase *psi, BitStreamInfo *bsi, int ch);
/* noiseless.c */
void DecodeICSInfo(BitStreamInfo *bsi, ICSInfo *icsInfo, int sampRateIdx);
/* dct4.c */
void DCT4(int tabidx, int *coef, int gb);
/* fft.c */
void R4FFT(int tabidx, int *x);
/* sbrimdct.c */
void DecWindowOverlapNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStartNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStopNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapShortNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
/* hufftabs.c */
extern const HuffInfo huffTabSpecInfo[11];
extern const signed short huffTabSpec[1241];
extern const HuffInfo huffTabScaleFactInfo;
extern const signed short huffTabScaleFact[121];
/* trigtabs.c */
extern const int cos4sin4tabOffset[NUM_IMDCT_SIZES];
extern const int sinWindowOffset[NUM_IMDCT_SIZES];
extern const int kbdWindowOffset[NUM_IMDCT_SIZES];
extern const unsigned char bitrevtab[17 + 129];
extern const int bitrevtabOffset[NUM_IMDCT_SIZES];
#ifdef HELIX_CONFIG_AAC_GENERATE_TRIGTABS_FLOAT
/* trigtabs_fltgen.c */
extern int cos4sin4tab[128 + 1024];
extern int cos1sin1tab[514];
extern int sinWindow[128 + 1024];
extern int kbdWindow[128 + 1024];
extern int twidTabEven[4*6 + 16*6 + 64*6];
extern int twidTabOdd[8*6 + 32*6 + 128*6];
#else
/* trigtabs.c */
extern const int cos4sin4tab[128 + 1024];
extern const int cos1sin1tab[514];
extern const int sinWindow[128 + 1024];
extern const int kbdWindow[128 + 1024];
extern const int twidTabEven[4*6 + 16*6 + 64*6];
extern const int twidTabOdd[8*6 + 32*6 + 128*6];
#endif
#endif /* _CODER_H */

View File

@@ -1,337 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: dct4.c,v 1.1 2005/02/26 01:47:34 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* dct4.c - optimized DCT-IV
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
static const int nmdctTab[NUM_IMDCT_SIZES] PROGMEM = {128, 1024};
static const int postSkip[NUM_IMDCT_SIZES] PROGMEM = {15, 1};
/**************************************************************************************
* Function: PreMultiply
*
* Description: pre-twiddle stage of DCT4
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out, gains 5 (short) or 8 (long) frac bits
* i.e. gains 2-7= -5 int bits (short) or 2-10 = -8 int bits (long)
* normalization by -1/N is rolled into tables here (see trigtabs.c)
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
static void PreMultiply(int tabidx, int *zbuf1)
{
int i, nmdct, ar1, ai1, ar2, ai2, z1, z2;
int t, cms2, cps2a, sin2a, cps2b, sin2b;
int *zbuf2;
const int *csptr;
nmdct = nmdctTab[tabidx];
zbuf2 = zbuf1 + nmdct - 1;
csptr = cos4sin4tab + cos4sin4tabOffset[tabidx];
/* whole thing should fit in registers - verify that compiler does this */
for (i = nmdct >> 2; i != 0; i--) {
/* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin) */
cps2a = *csptr++;
sin2a = *csptr++;
cps2b = *csptr++;
sin2b = *csptr++;
ar1 = *(zbuf1 + 0);
ai2 = *(zbuf1 + 1);
ai1 = *(zbuf2 + 0);
ar2 = *(zbuf2 - 1);
/* gain 2 ints bit from MULSHIFT32 by Q30, but drop 7 or 10 int bits from table scaling of 1/M
* max per-sample gain (ignoring implicit scaling) = MAX(sin(angle)+cos(angle)) = 1.414
* i.e. gain 1 GB since worst case is sin(angle) = cos(angle) = 0.707 (Q30), gain 2 from
* extra sign bits, and eat one in adding
*/
t = MULSHIFT32(sin2a, ar1 + ai1);
z2 = MULSHIFT32(cps2a, ai1) - t;
cms2 = cps2a - 2*sin2a;
z1 = MULSHIFT32(cms2, ar1) + t;
*zbuf1++ = z1; /* cos*ar1 + sin*ai1 */
*zbuf1++ = z2; /* cos*ai1 - sin*ar1 */
t = MULSHIFT32(sin2b, ar2 + ai2);
z2 = MULSHIFT32(cps2b, ai2) - t;
cms2 = cps2b - 2*sin2b;
z1 = MULSHIFT32(cms2, ar2) + t;
*zbuf2-- = z2; /* cos*ai2 - sin*ar2 */
*zbuf2-- = z1; /* cos*ar2 + sin*ai2 */
}
}
/**************************************************************************************
* Function: PostMultiply
*
* Description: post-twiddle stage of DCT4
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out - gains 2 int bits
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
static void PostMultiply(int tabidx, int *fft1)
{
int i, nmdct, ar1, ai1, ar2, ai2, skipFactor;
int t, cms2, cps2, sin2;
int *fft2;
const int *csptr;
nmdct = nmdctTab[tabidx];
csptr = cos1sin1tab;
skipFactor = postSkip[tabidx];
fft2 = fft1 + nmdct - 1;
/* load coeffs for first pass
* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin)
*/
cps2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
cms2 = cps2 - 2*sin2;
for (i = nmdct >> 2; i != 0; i--) {
ar1 = *(fft1 + 0);
ai1 = *(fft1 + 1);
ar2 = *(fft2 - 1);
ai2 = *(fft2 + 0);
/* gain 2 ints bit from MULSHIFT32 by Q30
* max per-sample gain = MAX(sin(angle)+cos(angle)) = 1.414
* i.e. gain 1 GB since worst case is sin(angle) = cos(angle) = 0.707 (Q30), gain 2 from
* extra sign bits, and eat one in adding
*/
t = MULSHIFT32(sin2, ar1 + ai1);
*fft2-- = t - MULSHIFT32(cps2, ai1); /* sin*ar1 - cos*ai1 */
*fft1++ = t + MULSHIFT32(cms2, ar1); /* cos*ar1 + sin*ai1 */
cps2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
ai2 = -ai2;
t = MULSHIFT32(sin2, ar2 + ai2);
*fft2-- = t - MULSHIFT32(cps2, ai2); /* sin*ar1 - cos*ai1 */
cms2 = cps2 - 2*sin2;
*fft1++ = t + MULSHIFT32(cms2, ar2); /* cos*ar1 + sin*ai1 */
}
}
/**************************************************************************************
* Function: PreMultiplyRescale
*
* Description: pre-twiddle stage of DCT4, with rescaling for extra guard bits
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
* number of guard bits to add to input before processing
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: see notes on PreMultiply(), above
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void PreMultiplyRescale(int tabidx, int *zbuf1, int es)
{
int i, nmdct, ar1, ai1, ar2, ai2, z1, z2;
int t, cms2, cps2a, sin2a, cps2b, sin2b;
int *zbuf2;
const int *csptr;
nmdct = nmdctTab[tabidx];
zbuf2 = zbuf1 + nmdct - 1;
csptr = cos4sin4tab + cos4sin4tabOffset[tabidx];
/* whole thing should fit in registers - verify that compiler does this */
for (i = nmdct >> 2; i != 0; i--) {
/* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin) */
cps2a = *csptr++;
sin2a = *csptr++;
cps2b = *csptr++;
sin2b = *csptr++;
ar1 = *(zbuf1 + 0) >> es;
ai1 = *(zbuf2 + 0) >> es;
ai2 = *(zbuf1 + 1) >> es;
t = MULSHIFT32(sin2a, ar1 + ai1);
z2 = MULSHIFT32(cps2a, ai1) - t;
cms2 = cps2a - 2*sin2a;
z1 = MULSHIFT32(cms2, ar1) + t;
*zbuf1++ = z1;
*zbuf1++ = z2;
ar2 = *(zbuf2 - 1) >> es; /* do here to free up register used for es */
t = MULSHIFT32(sin2b, ar2 + ai2);
z2 = MULSHIFT32(cps2b, ai2) - t;
cms2 = cps2b - 2*sin2b;
z1 = MULSHIFT32(cms2, ar2) + t;
*zbuf2-- = z2;
*zbuf2-- = z1;
}
}
/**************************************************************************************
* Function: PostMultiplyRescale
*
* Description: post-twiddle stage of DCT4, with rescaling for extra guard bits
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
* number of guard bits to remove from output
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: clips output to [-2^30, 2^30 - 1], guaranteeing at least 1 guard bit
* see notes on PostMultiply(), above
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void PostMultiplyRescale(int tabidx, int *fft1, int es)
{
int i, nmdct, ar1, ai1, ar2, ai2, skipFactor, z;
int t, cs2, sin2;
int *fft2;
const int *csptr;
nmdct = nmdctTab[tabidx];
csptr = cos1sin1tab;
skipFactor = postSkip[tabidx];
fft2 = fft1 + nmdct - 1;
/* load coeffs for first pass
* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin)
*/
cs2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
for (i = nmdct >> 2; i != 0; i--) {
ar1 = *(fft1 + 0);
ai1 = *(fft1 + 1);
ai2 = *(fft2 + 0);
t = MULSHIFT32(sin2, ar1 + ai1);
z = t - MULSHIFT32(cs2, ai1);
CLIP_2N_SHIFT(z, es);
*fft2-- = z;
cs2 -= 2*sin2;
z = t + MULSHIFT32(cs2, ar1);
CLIP_2N_SHIFT(z, es);
*fft1++ = z;
cs2 = *csptr++;
sin2 = *csptr;
csptr += skipFactor;
ar2 = *fft2;
ai2 = -ai2;
t = MULSHIFT32(sin2, ar2 + ai2);
z = t - MULSHIFT32(cs2, ai2);
CLIP_2N_SHIFT(z, es);
*fft2-- = z;
cs2 -= 2*sin2;
z = t + MULSHIFT32(cs2, ar2);
CLIP_2N_SHIFT(z, es);
*fft1++ = z;
cs2 += 2*sin2;
}
}
/**************************************************************************************
* Function: DCT4
*
* Description: type-IV DCT
*
* Inputs: table index (for transform size)
* buffer of nmdct samples
* number of guard bits in the input buffer
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: operates in-place
* if number of guard bits in input is < GBITS_IN_DCT4, the input is
* scaled (>>) before the DCT4 and rescaled (<<, with clipping) after
* the DCT4 (rare)
* the output has FBITS_LOST_DCT4 fewer fraction bits than the input
* the output will always have at least 1 guard bit (GBITS_IN_DCT4 >= 4)
* int bits gained per stage (PreMul + FFT + PostMul)
* short blocks = (-5 + 4 + 2) = 1 total
* long blocks = (-8 + 7 + 2) = 1 total
**************************************************************************************/
void DCT4(int tabidx, int *coef, int gb)
{
int es;
/* fast in-place DCT-IV - adds guard bits if necessary */
if (gb < GBITS_IN_DCT4) {
es = GBITS_IN_DCT4 - gb;
PreMultiplyRescale(tabidx, coef, es);
R4FFT(tabidx, coef);
PostMultiplyRescale(tabidx, coef, es);
} else {
PreMultiply(tabidx, coef);
R4FFT(tabidx, coef);
PostMultiply(tabidx, coef);
}
}

View File

@@ -1,425 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: decelmnt.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* decelmnt.c - syntactic element decoding
**************************************************************************************/
#include "coder.h"
/**************************************************************************************
* Function: DecodeSingleChannelElement
*
* Description: decode one SCE
*
* Inputs: BitStreamInfo struct pointing to start of SCE (14496-3, table 4.4.4)
*
* Outputs: updated element instance tag
*
* Return: 0 if successful, -1 if error
*
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
**************************************************************************************/
static int DecodeSingleChannelElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
/* read instance tag */
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
return 0;
}
/**************************************************************************************
* Function: DecodeChannelPairElement
*
* Description: decode one CPE
*
* Inputs: BitStreamInfo struct pointing to start of CPE (14496-3, table 4.4.5)
*
* Outputs: updated element instance tag
* updated commonWin
* updated ICS info, if commonWin == 1
* updated mid-side stereo info, if commonWin == 1
*
* Return: 0 if successful, -1 if error
*
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
**************************************************************************************/
static int DecodeChannelPairElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
int sfb, gp, maskOffset;
unsigned char currBit, *maskPtr;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = psi->icsInfo;
/* read instance tag */
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
/* read common window flag and mid-side info (if present)
* store msMask bits in psi->msMaskBits[] as follows:
* long blocks - pack bits for each SFB in range [0, maxSFB) starting with lsb of msMaskBits[0]
* short blocks - pack bits for each SFB in range [0, maxSFB), for each group [0, 7]
* msMaskPresent = 0 means no M/S coding
* = 1 means psi->msMaskBits contains 1 bit per SFB to toggle M/S coding
* = 2 means all SFB's are M/S coded (so psi->msMaskBits is not needed)
*/
psi->commonWin = GetBits(bsi, 1);
if (psi->commonWin) {
DecodeICSInfo(bsi, icsInfo, psi->sampRateIdx);
psi->msMaskPresent = GetBits(bsi, 2);
if (psi->msMaskPresent == 1) {
maskPtr = psi->msMaskBits;
*maskPtr = 0;
maskOffset = 0;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
currBit = (unsigned char)GetBits(bsi, 1);
*maskPtr |= currBit << maskOffset;
if (++maskOffset == 8) {
maskPtr++;
*maskPtr = 0;
maskOffset = 0;
}
}
}
}
}
return 0;
}
/**************************************************************************************
* Function: DecodeLFEChannelElement
*
* Description: decode one LFE
*
* Inputs: BitStreamInfo struct pointing to start of LFE (14496-3, table 4.4.9)
*
* Outputs: updated element instance tag
*
* Return: 0 if successful, -1 if error
*
* Notes: doesn't decode individual channel stream (part of DecodeNoiselessData)
**************************************************************************************/
static int DecodeLFEChannelElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
/* read instance tag */
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
return 0;
}
/**************************************************************************************
* Function: DecodeDataStreamElement
*
* Description: decode one DSE
*
* Inputs: BitStreamInfo struct pointing to start of DSE (14496-3, table 4.4.10)
*
* Outputs: updated element instance tag
* filled in data stream buffer
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
static int DecodeDataStreamElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
unsigned int byteAlign, dataCount;
unsigned char *dataBuf;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
aacDecInfo->currInstTag = GetBits(bsi, NUM_INST_TAG_BITS);
byteAlign = GetBits(bsi, 1);
dataCount = GetBits(bsi, 8);
if (dataCount == 255)
dataCount += GetBits(bsi, 8);
if (byteAlign)
ByteAlignBitstream(bsi);
psi->dataCount = dataCount;
dataBuf = psi->dataBuf;
while (dataCount--)
*dataBuf++ = GetBits(bsi, 8);
return 0;
}
/**************************************************************************************
* Function: DecodeProgramConfigElement
*
* Description: decode one PCE
*
* Inputs: BitStreamInfo struct pointing to start of PCE (14496-3, table 4.4.2)
*
* Outputs: filled-in ProgConfigElement struct
* updated BitStreamInfo struct
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: #define KEEP_PCE_COMMENTS to save the comment field of the PCE
* (otherwise we just skip it in the bitstream, to save memory)
**************************************************************************************/
int DecodeProgramConfigElement(ProgConfigElement *pce, BitStreamInfo *bsi)
{
int i;
pce->elemInstTag = GetBits(bsi, 4);
pce->profile = GetBits(bsi, 2);
pce->sampRateIdx = GetBits(bsi, 4);
pce->numFCE = GetBits(bsi, 4);
pce->numSCE = GetBits(bsi, 4);
pce->numBCE = GetBits(bsi, 4);
pce->numLCE = GetBits(bsi, 2);
pce->numADE = GetBits(bsi, 3);
pce->numCCE = GetBits(bsi, 4);
pce->monoMixdown = GetBits(bsi, 1) << 4; /* present flag */
if (pce->monoMixdown)
pce->monoMixdown |= GetBits(bsi, 4); /* element number */
pce->stereoMixdown = GetBits(bsi, 1) << 4; /* present flag */
if (pce->stereoMixdown)
pce->stereoMixdown |= GetBits(bsi, 4); /* element number */
pce->matrixMixdown = GetBits(bsi, 1) << 4; /* present flag */
if (pce->matrixMixdown) {
pce->matrixMixdown |= GetBits(bsi, 2) << 1; /* index */
pce->matrixMixdown |= GetBits(bsi, 1); /* pseudo-surround enable */
}
for (i = 0; i < pce->numFCE; i++) {
pce->fce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
pce->fce[i] |= GetBits(bsi, 4); /* tag select */
}
for (i = 0; i < pce->numSCE; i++) {
pce->sce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
pce->sce[i] |= GetBits(bsi, 4); /* tag select */
}
for (i = 0; i < pce->numBCE; i++) {
pce->bce[i] = GetBits(bsi, 1) << 4; /* is_cpe flag */
pce->bce[i] |= GetBits(bsi, 4); /* tag select */
}
for (i = 0; i < pce->numLCE; i++)
pce->lce[i] = GetBits(bsi, 4); /* tag select */
for (i = 0; i < pce->numADE; i++)
pce->ade[i] = GetBits(bsi, 4); /* tag select */
for (i = 0; i < pce->numCCE; i++) {
pce->cce[i] = GetBits(bsi, 1) << 4; /* independent/dependent flag */
pce->cce[i] |= GetBits(bsi, 4); /* tag select */
}
ByteAlignBitstream(bsi);
#ifdef KEEP_PCE_COMMENTS
pce->commentBytes = GetBits(bsi, 8);
for (i = 0; i < pce->commentBytes; i++)
pce->commentField[i] = GetBits(bsi, 8);
#else
/* eat comment bytes and throw away */
i = GetBits(bsi, 8);
while (i--)
GetBits(bsi, 8);
#endif
return 0;
}
/**************************************************************************************
* Function: DecodeFillElement
*
* Description: decode one fill element
*
* Inputs: BitStreamInfo struct pointing to start of fill element
* (14496-3, table 4.4.11)
*
* Outputs: updated element instance tag
* unpacked extension payload
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
static int DecodeFillElement(AACDecInfo *aacDecInfo, BitStreamInfo *bsi)
{
unsigned int fillCount;
unsigned char *fillBuf;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
fillCount = GetBits(bsi, 4);
if (fillCount == 15)
fillCount += (GetBits(bsi, 8) - 1);
psi->fillCount = fillCount;
fillBuf = psi->fillBuf;
while (fillCount--)
*fillBuf++ = GetBits(bsi, 8);
aacDecInfo->currInstTag = -1; /* fill elements don't have instance tag */
aacDecInfo->fillExtType = 0;
#ifdef AAC_ENABLE_SBR
/* check for SBR
* aacDecInfo->sbrEnabled is sticky (reset each raw_data_block), so for multichannel
* need to verify that all SCE/CPE/ICCE have valid SBR fill element following, and
* must upsample by 2 for LFE
*/
if (psi->fillCount > 0) {
aacDecInfo->fillExtType = (int)((psi->fillBuf[0] >> 4) & 0x0f);
if (aacDecInfo->fillExtType == EXT_SBR_DATA || aacDecInfo->fillExtType == EXT_SBR_DATA_CRC)
aacDecInfo->sbrEnabled = 1;
}
#endif
aacDecInfo->fillBuf = psi->fillBuf;
aacDecInfo->fillCount = psi->fillCount;
return 0;
}
/**************************************************************************************
* Function: DecodeNextElement
*
* Description: decode next syntactic element in AAC frame
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer containing next element
* pointer to bit offset
* pointer to number of valid bits remaining in buf
*
* Outputs: type of element decoded (aacDecInfo->currBlockID)
* type of element decoded last time (aacDecInfo->prevBlockID)
* updated aacDecInfo state, depending on which element was decoded
* updated buffer pointer
* updated bit offset
* updated number of available bits
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int DecodeNextElement(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail)
{
int err, bitsUsed;
PSInfoBase *psi;
BitStreamInfo bsi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* init bitstream reader */
SetBitstreamPointer(&bsi, (*bitsAvail + 7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
/* read element ID (save last ID for SBR purposes) */
aacDecInfo->prevBlockID = aacDecInfo->currBlockID;
aacDecInfo->currBlockID = GetBits(&bsi, NUM_SYN_ID_BITS);
/* set defaults (could be overwritten by DecodeXXXElement(), depending on currBlockID) */
psi->commonWin = 0;
err = 0;
switch (aacDecInfo->currBlockID) {
case AAC_ID_SCE:
err = DecodeSingleChannelElement(aacDecInfo, &bsi);
break;
case AAC_ID_CPE:
err = DecodeChannelPairElement(aacDecInfo, &bsi);
break;
case AAC_ID_CCE:
/* TODO - implement CCE decoding */
break;
case AAC_ID_LFE:
err = DecodeLFEChannelElement(aacDecInfo, &bsi);
break;
case AAC_ID_DSE:
err = DecodeDataStreamElement(aacDecInfo, &bsi);
break;
case AAC_ID_PCE:
err = DecodeProgramConfigElement(psi->pce + 0, &bsi);
break;
case AAC_ID_FIL:
err = DecodeFillElement(aacDecInfo, &bsi);
break;
case AAC_ID_END:
break;
}
if (err)
return ERR_AAC_SYNTAX_ELEMENT;
/* update bitstream reader */
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
*bitsAvail -= bitsUsed;
if (*bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
return ERR_AAC_NONE;
}

View File

@@ -1,373 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: dequant.c,v 1.2 2005/05/20 18:05:41 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* dequant.c - transform coefficient dequantization and short-block deinterleaving
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define SF_OFFSET 100
/* pow(2, i/4.0) for i = [0,1,2,3], format = Q30 */
static const int pow14[4] PROGMEM = {
0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65
};
/* pow(2, i/4.0) * pow(j, 4.0/3.0) for i = [0,1,2,3], j = [0,1,2,...,15]
* format = Q28 for j = [0-3], Q25 for j = [4-15]
*/
static const int pow43_14[4][16] PROGMEM = {
{
0x00000000, 0x10000000, 0x285145f3, 0x453a5cdb, /* Q28 */
0x0cb2ff53, 0x111989d6, 0x15ce31c8, 0x1ac7f203, /* Q25 */
0x20000000, 0x257106b9, 0x2b16b4a3, 0x30ed74b4, /* Q25 */
0x36f23fa5, 0x3d227bd3, 0x437be656, 0x49fc823c, /* Q25 */
},
{
0x00000000, 0x1306fe0a, 0x2ff221af, 0x52538f52,
0x0f1a1bf4, 0x1455ccc2, 0x19ee62a8, 0x1fd92396,
0x260dfc14, 0x2c8694d8, 0x333dcb29, 0x3a2f5c7a,
0x4157aed5, 0x48b3aaa3, 0x50409f76, 0x57fc3010,
},
{
0x00000000, 0x16a09e66, 0x39047c0f, 0x61e734aa,
0x11f59ac4, 0x182ec633, 0x1ed66a45, 0x25dfc55a,
0x2d413ccd, 0x34f3462d, 0x3cefc603, 0x4531ab69,
0x4db4adf8, 0x56752054, 0x5f6fcfcd, 0x68a1eca1,
},
{
0x00000000, 0x1ae89f99, 0x43ce3e4b, 0x746d57b2,
0x155b8109, 0x1cc21cdc, 0x24ac1839, 0x2d0a479e,
0x35d13f33, 0x3ef80748, 0x48775c93, 0x524938cd,
0x5c68841d, 0x66d0df0a, 0x717e7bfe, 0x7c6e0305,
},
};
/* pow(j, 4.0 / 3.0) for j = [16,17,18,...,63], format = Q23 */
static const int pow43[48] PROGMEM = {
0x1428a2fa, 0x15db1bd6, 0x1796302c, 0x19598d85,
0x1b24e8bb, 0x1cf7fcfa, 0x1ed28af2, 0x20b4582a,
0x229d2e6e, 0x248cdb55, 0x26832fda, 0x28800000,
0x2a832287, 0x2c8c70a8, 0x2e9bc5d8, 0x30b0ff99,
0x32cbfd4a, 0x34eca001, 0x3712ca62, 0x393e6088,
0x3b6f47e0, 0x3da56717, 0x3fe0a5fc, 0x4220ed72,
0x44662758, 0x46b03e7c, 0x48ff1e87, 0x4b52b3f3,
0x4daaebfd, 0x5007b497, 0x5268fc62, 0x54ceb29c,
0x5738c721, 0x59a72a59, 0x5c19cd35, 0x5e90a129,
0x610b9821, 0x638aa47f, 0x660db90f, 0x6894c90b,
0x6b1fc80c, 0x6daeaa0d, 0x70416360, 0x72d7e8b0,
0x75722ef9, 0x78102b85, 0x7ab1d3ec, 0x7d571e09,
};
/* sqrt(0.5), format = Q31 */
#define SQRTHALF 0x5a82799a
/* Minimax polynomial approximation to pow(x, 4/3), over the range
* poly43lo: x = [0.5, 0.7071]
* poly43hi: x = [0.7071, 1.0]
*
* Relative error < 1E-7
* Coefs are scaled by 4, 2, 1, 0.5, 0.25
*/
//fb
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
static const int poly43lo[5] PROGMEM = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 };
static const int poly43hi[5] PROGMEM = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 };
#pragma GCC diagnostic pop
/* pow2exp[i] = pow(2, i*4/3) exponent */
static const int pow2exp[8] PROGMEM = { 14, 13, 11, 10, 9, 7, 6, 5 };
/* pow2exp[i] = pow(2, i*4/3) fraction */
static const int pow2frac[8] PROGMEM = {
0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94,
0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6
};
/**************************************************************************************
* Function: DequantBlock
*
* Description: dequantize one block of transform coefficients (in-place)
*
* Inputs: quantized transform coefficients, range = [0, 8191]
* number of samples to dequantize
* scalefactor for this block of data, range = [0, 256]
*
* Outputs: dequantized transform coefficients in Q(FBITS_OUT_DQ_OFF)
*
* Return: guard bit mask (OR of abs value of all dequantized coefs)
*
* Notes: applies dequant formula y = pow(x, 4.0/3.0) * pow(2, (scale - 100)/4.0)
* * pow(2, FBITS_OUT_DQ_OFF)
* clips outputs to Q(FBITS_OUT_DQ_OFF)
* output has no minimum number of guard bits
**************************************************************************************/
static int DequantBlock(int *inbuf, int nSamps, int scale)
{
int iSamp, scalef, scalei, x, y, gbMask, shift, tab4[4];
const int *tab16, *coef;
if (nSamps <= 0)
return 0;
scale -= SF_OFFSET; /* new range = [-100, 156] */
/* with two's complement numbers, scalei/scalef factorization works for pos and neg values of scale:
* [+4...+7] >> 2 = +1, [ 0...+3] >> 2 = 0, [-4...-1] >> 2 = -1, [-8...-5] >> 2 = -2 ...
* (-1 & 0x3) = 3, (-2 & 0x3) = 2, (-3 & 0x3) = 1, (0 & 0x3) = 0
*
* Example: 2^(-5/4) = 2^(-1) * 2^(-1/4) = 2^-2 * 2^(3/4)
*/
tab16 = pow43_14[scale & 0x3];
scalef = pow14[scale & 0x3];
scalei = (scale >> 2) + FBITS_OUT_DQ_OFF;
/* cache first 4 values:
* tab16[j] = Q28 for j = [0,3]
* tab4[x] = x^(4.0/3.0) * 2^(0.25*scale), Q(FBITS_OUT_DQ_OFF)
*/
shift = 28 - scalei;
if (shift > 31) {
tab4[0] = tab4[1] = tab4[2] = tab4[3] = 0;
} else if (shift <= 0) {
shift = -shift;
if (shift > 31)
shift = 31;
for (x = 0; x < 4; x++) {
y = tab16[x];
if (y > (0x7fffffff >> shift))
y = 0x7fffffff; /* clip (rare) */
else
y <<= shift;
tab4[x] = y;
}
} else {
tab4[0] = 0;
tab4[1] = tab16[1] >> shift;
tab4[2] = tab16[2] >> shift;
tab4[3] = tab16[3] >> shift;
}
gbMask = 0;
do {
iSamp = *inbuf;
x = FASTABS(iSamp);
if (x < 4) {
y = tab4[x];
} else {
if (x < 16) {
/* result: y = Q25 (tab16 = Q25) */
y = tab16[x];
shift = 25 - scalei;
} else if (x < 64) {
/* result: y = Q21 (pow43tab[j] = Q23, scalef = Q30) */
y = pow43[x-16];
shift = 21 - scalei;
y = MULSHIFT32(y, scalef);
} else {
/* normalize to [0x40000000, 0x7fffffff]
* input x = [64, 8191] = [64, 2^13-1]
* ranges:
* shift = 7: 64 - 127
* shift = 6: 128 - 255
* shift = 5: 256 - 511
* shift = 4: 512 - 1023
* shift = 3: 1024 - 2047
* shift = 2: 2048 - 4095
* shift = 1: 4096 - 8191
*/
x <<= 17;
shift = 0;
if (x < 0x08000000)
x <<= 4, shift += 4;
if (x < 0x20000000)
x <<= 2, shift += 2;
if (x < 0x40000000)
x <<= 1, shift += 1;
coef = (x < SQRTHALF) ? poly43lo : poly43hi;
/* polynomial */
y = coef[0];
y = MULSHIFT32(y, x) + coef[1];
y = MULSHIFT32(y, x) + coef[2];
y = MULSHIFT32(y, x) + coef[3];
y = MULSHIFT32(y, x) + coef[4];
y = MULSHIFT32(y, pow2frac[shift]) << 3;
/* fractional scale
* result: y = Q21 (pow43tab[j] = Q23, scalef = Q30)
*/
y = MULSHIFT32(y, scalef); /* now y is Q24 */
shift = 24 - scalei - pow2exp[shift];
}
/* integer scale */
if (shift <= 0) {
shift = -shift;
if (shift > 31)
shift = 31;
if (y > (0x7fffffff >> shift))
y = 0x7fffffff; /* clip (rare) */
else
y <<= shift;
} else {
if (shift > 31)
shift = 31;
y >>= shift;
}
}
/* sign and store (gbMask used to count GB's) */
gbMask |= y;
/* apply sign */
iSamp >>= 31;
y ^= iSamp;
y -= iSamp;
*inbuf++ = y;
} while (--nSamps);
return gbMask;
}
/**************************************************************************************
* Function: Dequantize
*
* Description: dequantize all transform coefficients for one channel
*
* Inputs: valid AACDecInfo struct (including unpacked, quantized coefficients)
* index of current channel
*
* Outputs: dequantized coefficients, including short-block deinterleaving
* flags indicating if intensity and/or PNS is active
* minimum guard bit count for dequantized coefficients
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int Dequantize(AACDecInfo *aacDecInfo, int ch)
{
int gp, cb, sfb, win, width, nSamps, gbMask;
int *coef;
const int /*short*/ *sfbTab;
unsigned char *sfbCodeBook;
short *scaleFactors;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
if (icsInfo->winSequence == 2) {
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
nSamps = NSAMPS_SHORT;
} else {
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
nSamps = NSAMPS_LONG;
}
coef = psi->coef[ch];
sfbCodeBook = psi->sfbCodeBook[ch];
scaleFactors = psi->scaleFactors[ch];
psi->intensityUsed[ch] = 0;
psi->pnsUsed[ch] = 0;
gbMask = 0;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
/* dequantize one scalefactor band (not necessary if codebook is intensity or PNS)
* for zero codebook, still run dequantizer in case non-zero pulse data was added
*/
cb = (int)(sfbCodeBook[sfb]);
width = sfbTab[sfb+1] - sfbTab[sfb];
if (cb >= 0 && cb <= 11)
gbMask |= DequantBlock(coef, width, scaleFactors[sfb]);
else if (cb == 13)
psi->pnsUsed[ch] = 1;
else if (cb == 14 || cb == 15)
psi->intensityUsed[ch] = 1; /* should only happen if ch == 1 */
coef += width;
}
coef += (nSamps - sfbTab[icsInfo->maxSFB]);
}
sfbCodeBook += icsInfo->maxSFB;
scaleFactors += icsInfo->maxSFB;
}
aacDecInfo->pnsUsed |= psi->pnsUsed[ch]; /* set flag if PNS used for any channel */
/* calculate number of guard bits in dequantized data */
psi->gbCurrent[ch] = CLZ(gbMask) - 1;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: DeinterleaveShortBlocks
*
* Description: deinterleave transform coefficients in short blocks for one channel
*
* Inputs: valid AACDecInfo struct (including unpacked, quantized coefficients)
* index of current channel
*
* Outputs: deinterleaved coefficients (window groups into 8 separate windows)
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: only necessary if deinterleaving not part of Huffman decoding
**************************************************************************************/
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch)
{
(void)aacDecInfo;
(void)ch;
/* not used for this implementation - short block deinterleaving performed during Huffman decoding */
return ERR_AAC_NONE;
}

View File

@@ -1,393 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: fft.c,v 1.1 2005/02/26 01:47:34 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* fft.c - Ken's optimized radix-4 DIT FFT, optional radix-8 first pass for odd log2(N)
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define NUM_FFT_SIZES 2
static const int nfftTab[NUM_FFT_SIZES] PROGMEM ={64, 512};
static const int nfftlog2Tab[NUM_FFT_SIZES] PROGMEM = {6, 9};
#define SQRT1_2 0x5a82799a /* sqrt(1/2) in Q31 */
#define swapcplx(p0,p1) \
t = p0; t1 = *(&(p0)+1); p0 = p1; *(&(p0)+1) = *(&(p1)+1); p1 = t; *(&(p1)+1) = t1
/**************************************************************************************
* Function: BitReverse
*
* Description: Ken's fast in-place bit reverse, using super-small table
*
* Inputs: buffer of samples
* table index (for transform size)
*
* Outputs: bit-reversed samples in same buffer
*
* Return: none
**************************************************************************************/
/*__attribute__ ((section (".data"))) */ static void BitReverse(int *inout, int tabidx)
{
int *part0, *part1;
int a,b, t,t1;
const unsigned char* tab = bitrevtab + bitrevtabOffset[tabidx];
int nbits = nfftlog2Tab[tabidx];
part0 = inout;
part1 = inout + (1 << nbits);
while ((a = pgm_read_byte(tab++)) != 0) {
b = pgm_read_byte(tab++);
swapcplx(part0[4*a+0], part0[4*b+0]); /* 0xxx0 <-> 0yyy0 */
swapcplx(part0[4*a+2], part1[4*b+0]); /* 0xxx1 <-> 1yyy0 */
swapcplx(part1[4*a+0], part0[4*b+2]); /* 1xxx0 <-> 0yyy1 */
swapcplx(part1[4*a+2], part1[4*b+2]); /* 1xxx1 <-> 1yyy1 */
}
do {
swapcplx(part0[4*a+2], part1[4*a+0]); /* 0xxx1 <-> 1xxx0 */
} while ((a = pgm_read_byte(tab++)) != 0);
}
/**************************************************************************************
* Function: R4FirstPass
*
* Description: radix-4 trivial pass for decimation-in-time FFT
*
* Inputs: buffer of (bit-reversed) samples
* number of R4 butterflies per group (i.e. nfft / 4)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 2 guard bits, gains no integer bits,
* guard bits out = guard bits in - 2
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void R4FirstPass(int *x, int bg)
{
int ar, ai, br, bi, cr, ci, dr, di;
for (; bg != 0; bg--) {
ar = x[0] + x[2];
br = x[0] - x[2];
ai = x[1] + x[3];
bi = x[1] - x[3];
cr = x[4] + x[6];
dr = x[4] - x[6];
ci = x[5] + x[7];
di = x[5] - x[7];
/* max per-sample gain = 4.0 (adding 4 inputs together) */
x[0] = ar + cr;
x[4] = ar - cr;
x[1] = ai + ci;
x[5] = ai - ci;
x[2] = br + di;
x[6] = br - di;
x[3] = bi - dr;
x[7] = bi + dr;
x += 8;
}
}
/**************************************************************************************
* Function: R8FirstPass
*
* Description: radix-8 trivial pass for decimation-in-time FFT
*
* Inputs: buffer of (bit-reversed) samples
* number of R8 butterflies per group (i.e. nfft / 8)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 3 guard bits, gains 1 integer bit
* guard bits out = guard bits in - 3 (if inputs are full scale)
* or guard bits in - 2 (if inputs bounded to +/- sqrt(2)/2)
* see scaling comments in code
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void R8FirstPass(int *x, int bg)
{
int ar, ai, br, bi, cr, ci, dr, di;
int sr, si, tr, ti, ur, ui, vr, vi;
int wr, wi, xr, xi, yr, yi, zr, zi;
for (; bg != 0; bg--) {
ar = x[0] + x[2];
br = x[0] - x[2];
ai = x[1] + x[3];
bi = x[1] - x[3];
cr = x[4] + x[6];
dr = x[4] - x[6];
ci = x[5] + x[7];
di = x[5] - x[7];
sr = ar + cr;
ur = ar - cr;
si = ai + ci;
ui = ai - ci;
tr = br - di;
vr = br + di;
ti = bi + dr;
vi = bi - dr;
ar = x[ 8] + x[10];
br = x[ 8] - x[10];
ai = x[ 9] + x[11];
bi = x[ 9] - x[11];
cr = x[12] + x[14];
dr = x[12] - x[14];
ci = x[13] + x[15];
di = x[13] - x[15];
/* max gain of wr/wi/yr/yi vs input = 2
* (sum of 4 samples >> 1)
*/
wr = (ar + cr) >> 1;
yr = (ar - cr) >> 1;
wi = (ai + ci) >> 1;
yi = (ai - ci) >> 1;
/* max gain of output vs input = 4
* (sum of 4 samples >> 1 + sum of 4 samples >> 1)
*/
x[ 0] = (sr >> 1) + wr;
x[ 8] = (sr >> 1) - wr;
x[ 1] = (si >> 1) + wi;
x[ 9] = (si >> 1) - wi;
x[ 4] = (ur >> 1) + yi;
x[12] = (ur >> 1) - yi;
x[ 5] = (ui >> 1) - yr;
x[13] = (ui >> 1) + yr;
ar = br - di;
cr = br + di;
ai = bi + dr;
ci = bi - dr;
/* max gain of xr/xi/zr/zi vs input = 4*sqrt(2)/2 = 2*sqrt(2)
* (sum of 8 samples, multiply by sqrt(2)/2, implicit >> 1 from Q31)
*/
xr = MULSHIFT32(SQRT1_2, ar - ai);
xi = MULSHIFT32(SQRT1_2, ar + ai);
zr = MULSHIFT32(SQRT1_2, cr - ci);
zi = MULSHIFT32(SQRT1_2, cr + ci);
/* max gain of output vs input = (2 + 2*sqrt(2) ~= 4.83)
* (sum of 4 samples >> 1, plus xr/xi/zr/zi with gain of 2*sqrt(2))
* in absolute terms, we have max gain of appx 9.656 (4 + 0.707*8)
* but we also gain 1 int bit (from MULSHIFT32 or from explicit >> 1)
*/
x[ 6] = (tr >> 1) - xr;
x[14] = (tr >> 1) + xr;
x[ 7] = (ti >> 1) - xi;
x[15] = (ti >> 1) + xi;
x[ 2] = (vr >> 1) + zi;
x[10] = (vr >> 1) - zi;
x[ 3] = (vi >> 1) - zr;
x[11] = (vi >> 1) + zr;
x += 16;
}
}
/**************************************************************************************
* Function: R4Core
*
* Description: radix-4 pass for decimation-in-time FFT
*
* Inputs: buffer of samples
* number of R4 butterflies per group
* number of R4 groups per pass
* pointer to twiddle factors tables
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: gain 2 integer bits per pass (see scaling comments in code)
* min 1 GB in
* gbOut = gbIn - 1 (short block) or gbIn - 2 (long block)
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void R4Core(int *x, int bg, int gp, int *wtab)
{
int ar, ai, br, bi, cr, ci, dr, di, tr, ti;
int wd, ws, wi;
int i, j, step;
int *xptr, *wptr;
for (; bg != 0; gp <<= 2, bg >>= 2) {
step = 2*gp;
xptr = x;
/* max per-sample gain, per group < 1 + 3*sqrt(2) ~= 5.25 if inputs x are full-scale
* do 3 groups for long block, 2 groups for short block (gain 2 int bits per group)
*
* very conservative scaling:
* group 1: max gain = 5.25, int bits gained = 2, gb used = 1 (2^3 = 8)
* group 2: max gain = 5.25^2 = 27.6, int bits gained = 4, gb used = 1 (2^5 = 32)
* group 3: max gain = 5.25^3 = 144.7, int bits gained = 6, gb used = 2 (2^8 = 256)
*/
for (i = bg; i != 0; i--) {
wptr = wtab;
for (j = gp; j != 0; j--) {
ar = xptr[0];
ai = xptr[1];
xptr += step;
/* gain 2 int bits for br/bi, cr/ci, dr/di (MULSHIFT32 by Q30)
* gain 1 net GB
*/
ws = wptr[0];
wi = wptr[1];
br = xptr[0];
bi = xptr[1];
wd = ws + 2*wi;
tr = MULSHIFT32(wi, br + bi);
br = MULSHIFT32(wd, br) - tr; /* cos*br + sin*bi */
bi = MULSHIFT32(ws, bi) + tr; /* cos*bi - sin*br */
xptr += step;
ws = wptr[2];
wi = wptr[3];
cr = xptr[0];
ci = xptr[1];
wd = ws + 2*wi;
tr = MULSHIFT32(wi, cr + ci);
cr = MULSHIFT32(wd, cr) - tr;
ci = MULSHIFT32(ws, ci) + tr;
xptr += step;
ws = wptr[4];
wi = wptr[5];
dr = xptr[0];
di = xptr[1];
wd = ws + 2*wi;
tr = MULSHIFT32(wi, dr + di);
dr = MULSHIFT32(wd, dr) - tr;
di = MULSHIFT32(ws, di) + tr;
wptr += 6;
tr = ar;
ti = ai;
ar = (tr >> 2) - br;
ai = (ti >> 2) - bi;
br = (tr >> 2) + br;
bi = (ti >> 2) + bi;
tr = cr;
ti = ci;
cr = tr + dr;
ci = di - ti;
dr = tr - dr;
di = di + ti;
xptr[0] = ar + ci;
xptr[1] = ai + dr;
xptr -= step;
xptr[0] = br - cr;
xptr[1] = bi - di;
xptr -= step;
xptr[0] = ar - ci;
xptr[1] = ai - dr;
xptr -= step;
xptr[0] = br + cr;
xptr[1] = bi + di;
xptr += 2;
}
xptr += 3*step;
}
wtab += 3*step;
}
}
/**************************************************************************************
* Function: R4FFT
*
* Description: Ken's very fast in-place radix-4 decimation-in-time FFT
*
* Inputs: table index (for transform size)
* buffer of samples (non bit-reversed)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 5 guard bits in for nfft <= 512
* gbOut = gbIn - 4 (assuming input is from PreMultiply)
* gains log2(nfft) - 2 int bits total
* so gain 7 int bits (LONG), 4 int bits (SHORT)
**************************************************************************************/
void R4FFT(int tabidx, int *x)
{
int order = nfftlog2Tab[tabidx];
int nfft = nfftTab[tabidx];
/* decimation in time */
BitReverse(x, tabidx);
if (order & 0x1) {
/* long block: order = 9, nfft = 512 */
R8FirstPass(x, nfft >> 3); /* gain 1 int bit, lose 2 GB */
R4Core(x, nfft >> 5, 8, (int *)twidTabOdd); /* gain 6 int bits, lose 2 GB */
} else {
/* short block: order = 6, nfft = 64 */
R4FirstPass(x, nfft >> 2); /* gain 0 int bits, lose 2 GB */
R4Core(x, nfft >> 4, 4, (int *)twidTabEven); /* gain 4 int bits, lose 1 GB */
}
}

View File

@@ -1,496 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: filefmt.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* filefmt.c - ADIF and ADTS header decoding, raw block handling
**************************************************************************************/
#include "coder.h"
/**************************************************************************************
* Function: UnpackADTSHeader
*
* Description: parse the ADTS frame header and initialize decoder state
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer with complete ADTS frame header (byte aligned)
* header size = 7 bytes, plus 2 if CRC
*
* Outputs: filled in ADTS struct
* updated buffer pointer
* updated bit offset
* updated number of available bits
*
* Return: 0 if successful, error code (< 0) if error
*
* TODO: test CRC
* verify that fixed fields don't change between frames
**************************************************************************************/
int UnpackADTSHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail)
{
int bitsUsed;
PSInfoBase *psi;
BitStreamInfo bsi;
ADTSHeader *fhADTS;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
fhADTS = &(psi->fhADTS);
/* init bitstream reader */
SetBitstreamPointer(&bsi, (*bitsAvail + 7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
/* verify that first 12 bits of header are syncword */
if (GetBits(&bsi, 12) != 0x0fff) {
return ERR_AAC_INVALID_ADTS_HEADER;
}
/* fixed fields - should not change from frame to frame */
fhADTS->id = GetBits(&bsi, 1);
fhADTS->layer = GetBits(&bsi, 2);
fhADTS->protectBit = GetBits(&bsi, 1);
fhADTS->profile = GetBits(&bsi, 2);
fhADTS->sampRateIdx = GetBits(&bsi, 4);
fhADTS->privateBit = GetBits(&bsi, 1);
fhADTS->channelConfig = GetBits(&bsi, 3);
fhADTS->origCopy = GetBits(&bsi, 1);
fhADTS->home = GetBits(&bsi, 1);
/* variable fields - can change from frame to frame */
fhADTS->copyBit = GetBits(&bsi, 1);
fhADTS->copyStart = GetBits(&bsi, 1);
fhADTS->frameLength = GetBits(&bsi, 13);
fhADTS->bufferFull = GetBits(&bsi, 11);
fhADTS->numRawDataBlocks = GetBits(&bsi, 2) + 1;
/* note - MPEG4 spec, correction 1 changes how CRC is handled when protectBit == 0 and numRawDataBlocks > 1 */
if (fhADTS->protectBit == 0)
fhADTS->crcCheckWord = GetBits(&bsi, 16);
/* byte align */
ByteAlignBitstream(&bsi); /* should always be aligned anyway */
/* check validity of header */
if (fhADTS->layer != 0 || fhADTS->profile != AAC_PROFILE_LC ||
fhADTS->sampRateIdx >= NUM_SAMPLE_RATES || fhADTS->channelConfig >= NUM_DEF_CHAN_MAPS)
return ERR_AAC_INVALID_ADTS_HEADER;
#ifndef AAC_ENABLE_MPEG4
if (fhADTS->id != 1)
return ERR_AAC_MPEG4_UNSUPPORTED;
#endif
/* update codec info */
psi->sampRateIdx = fhADTS->sampRateIdx;
if (!psi->useImpChanMap)
psi->nChans = channelMapTab[fhADTS->channelConfig];
/* syntactic element fields will be read from bitstream for each element */
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
/* fill in user-accessible data (TODO - calc bitrate, handle tricky channel config cases) */
aacDecInfo->bitRate = 0;
aacDecInfo->nChans = psi->nChans;
aacDecInfo->sampRate = sampRateTab[psi->sampRateIdx];
aacDecInfo->profile = fhADTS->profile;
aacDecInfo->sbrEnabled = 0;
aacDecInfo->adtsBlocksLeft = fhADTS->numRawDataBlocks;
/* update bitstream reader */
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
*bitsAvail -= bitsUsed ;
if (*bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: GetADTSChannelMapping
*
* Description: determine the number of channels from implicit mapping rules
*
* Inputs: valid AACDecInfo struct
* pointer to start of raw_data_block
* bit offset
* bits available
*
* Outputs: updated number of channels
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: calculates total number of channels using rules in 14496-3, 4.5.1.2.1
* does not attempt to deduce speaker geometry
**************************************************************************************/
int GetADTSChannelMapping(AACDecInfo *aacDecInfo, unsigned char *buf, int bitOffset, int bitsAvail)
{
int ch, nChans, elementChans, err;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
nChans = 0;
do {
/* parse next syntactic element */
err = DecodeNextElement(aacDecInfo, &buf, &bitOffset, &bitsAvail);
if (err)
return err;
elementChans = elementNumChans[aacDecInfo->currBlockID];
nChans += elementChans;
for (ch = 0; ch < elementChans; ch++) {
err = DecodeNoiselessData(aacDecInfo, &buf, &bitOffset, &bitsAvail, ch);
if (err)
return err;
}
} while (aacDecInfo->currBlockID != AAC_ID_END);
if (nChans <= 0)
return ERR_AAC_CHANNEL_MAP;
/* update number of channels in codec state and user-accessible info structs */
psi->nChans = nChans;
aacDecInfo->nChans = psi->nChans;
psi->useImpChanMap = 1;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: GetNumChannelsADIF
*
* Description: get number of channels from program config elements in an ADIF file
*
* Inputs: array of filled-in program config element structures
* number of PCE's
*
* Outputs: none
*
* Return: total number of channels in file
* -1 if error (invalid number of PCE's or unsupported mode)
**************************************************************************************/
static int GetNumChannelsADIF(ProgConfigElement *fhPCE, int nPCE)
{
int i, j, nChans;
if (nPCE < 1 || nPCE > MAX_NUM_PCE_ADIF)
return -1;
nChans = 0;
for (i = 0; i < nPCE; i++) {
/* for now: only support LC, no channel coupling */
if (fhPCE[i].profile != AAC_PROFILE_LC || fhPCE[i].numCCE > 0)
return -1;
/* add up number of channels in all channel elements (assume all single-channel) */
nChans += fhPCE[i].numFCE;
nChans += fhPCE[i].numSCE;
nChans += fhPCE[i].numBCE;
nChans += fhPCE[i].numLCE;
/* add one more for every element which is a channel pair */
for (j = 0; j < fhPCE[i].numFCE; j++) {
if (CHAN_ELEM_IS_CPE(fhPCE[i].fce[j]))
nChans++;
}
for (j = 0; j < fhPCE[i].numSCE; j++) {
if (CHAN_ELEM_IS_CPE(fhPCE[i].sce[j]))
nChans++;
}
for (j = 0; j < fhPCE[i].numBCE; j++) {
if (CHAN_ELEM_IS_CPE(fhPCE[i].bce[j]))
nChans++;
}
}
return nChans;
}
/**************************************************************************************
* Function: GetSampleRateIdxADIF
*
* Description: get sampling rate index from program config elements in an ADIF file
*
* Inputs: array of filled-in program config element structures
* number of PCE's
*
* Outputs: none
*
* Return: sample rate of file
* -1 if error (invalid number of PCE's or sample rate mismatch)
**************************************************************************************/
static int GetSampleRateIdxADIF(ProgConfigElement *fhPCE, int nPCE)
{
int i, idx;
if (nPCE < 1 || nPCE > MAX_NUM_PCE_ADIF)
return -1;
/* make sure all PCE's have the same sample rate */
idx = fhPCE[0].sampRateIdx;
for (i = 1; i < nPCE; i++) {
if (fhPCE[i].sampRateIdx != idx)
return -1;
}
return idx;
}
/**************************************************************************************
* Function: UnpackADIFHeader
*
* Description: parse the ADIF file header and initialize decoder state
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer with complete ADIF header
* (starting at 'A' in 'ADIF' tag)
* pointer to bit offset
* pointer to number of valid bits remaining in inbuf
*
* Outputs: filled-in ADIF struct
* updated buffer pointer
* updated bit offset
* updated number of available bits
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int UnpackADIFHeader(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail)
{
int i, bitsUsed;
PSInfoBase *psi;
BitStreamInfo bsi;
ADIFHeader *fhADIF;
ProgConfigElement *pce;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* init bitstream reader */
SetBitstreamPointer(&bsi, (*bitsAvail + 7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
/* unpack ADIF file header */
fhADIF = &(psi->fhADIF);
pce = psi->pce;
/* verify that first 32 bits of header are "ADIF" */
if (GetBits(&bsi, 8) != 'A' || GetBits(&bsi, 8) != 'D' || GetBits(&bsi, 8) != 'I' || GetBits(&bsi, 8) != 'F')
return ERR_AAC_INVALID_ADIF_HEADER;
/* read ADIF header fields */
fhADIF->copyBit = GetBits(&bsi, 1);
if (fhADIF->copyBit) {
for (i = 0; i < ADIF_COPYID_SIZE; i++)
fhADIF->copyID[i] = GetBits(&bsi, 8);
}
fhADIF->origCopy = GetBits(&bsi, 1);
fhADIF->home = GetBits(&bsi, 1);
fhADIF->bsType = GetBits(&bsi, 1);
fhADIF->bitRate = GetBits(&bsi, 23);
fhADIF->numPCE = GetBits(&bsi, 4) + 1; /* add 1 (so range = [1, 16]) */
if (fhADIF->bsType == 0)
fhADIF->bufferFull = GetBits(&bsi, 20);
/* parse all program config elements */
for (i = 0; i < fhADIF->numPCE; i++)
DecodeProgramConfigElement(pce + i, &bsi);
/* byte align */
ByteAlignBitstream(&bsi);
/* update codec info */
psi->nChans = GetNumChannelsADIF(pce, fhADIF->numPCE);
psi->sampRateIdx = GetSampleRateIdxADIF(pce, fhADIF->numPCE);
/* check validity of header */
if (psi->nChans < 0 || psi->sampRateIdx < 0 || psi->sampRateIdx >= NUM_SAMPLE_RATES)
return ERR_AAC_INVALID_ADIF_HEADER;
/* syntactic element fields will be read from bitstream for each element */
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
/* fill in user-accessible data */
aacDecInfo->bitRate = 0;
aacDecInfo->nChans = psi->nChans;
aacDecInfo->sampRate = sampRateTab[psi->sampRateIdx];
aacDecInfo->profile = pce[0].profile;
aacDecInfo->sbrEnabled = 0;
/* update bitstream reader */
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
*bitsAvail -= bitsUsed ;
if (*bitsAvail < 0)
return ERR_AAC_INDATA_UNDERFLOW;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: SetRawBlockParams
*
* Description: set internal state variables for decoding a stream of raw data blocks
*
* Inputs: valid AACDecInfo struct
* flag indicating source of parameters (from previous headers or passed
* explicitly by caller)
* number of channels
* sample rate
* profile ID
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: if copyLast == 1, then psi->nChans, psi->sampRateIdx, and
* aacDecInfo->profile are not changed (it's assumed that we already
* set them, such as by a previous call to UnpackADTSHeader())
* if copyLast == 0, then the parameters we passed in are used instead
**************************************************************************************/
int SetRawBlockParams(AACDecInfo *aacDecInfo, int copyLast, int nChans, int sampRate, int profile)
{
int idx;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
if (!copyLast) {
aacDecInfo->profile = profile;
psi->nChans = nChans;
for (idx = 0; idx < NUM_SAMPLE_RATES; idx++) {
if (sampRate == sampRateTab[idx]) {
psi->sampRateIdx = idx;
break;
}
}
if (idx == NUM_SAMPLE_RATES)
return ERR_AAC_INVALID_FRAME;
}
aacDecInfo->nChans = psi->nChans;
aacDecInfo->sampRate = sampRateTab[psi->sampRateIdx];
/* check validity of header */
if (psi->sampRateIdx >= NUM_SAMPLE_RATES || psi->sampRateIdx < 0 || aacDecInfo->profile != AAC_PROFILE_LC)
return ERR_AAC_RAWBLOCK_PARAMS;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: PrepareRawBlock
*
* Description: reset per-block state variables for raw blocks (no ADTS/ADIF headers)
*
* Inputs: valid AACDecInfo struct
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int PrepareRawBlock(AACDecInfo *aacDecInfo)
{
// PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
// psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* syntactic element fields will be read from bitstream for each element */
aacDecInfo->prevBlockID = AAC_ID_INVALID;
aacDecInfo->currBlockID = AAC_ID_INVALID;
aacDecInfo->currInstTag = -1;
/* fill in user-accessible data */
aacDecInfo->bitRate = 0;
aacDecInfo->sbrEnabled = 0;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: FlushCodec
*
* Description: flush internal codec state (after seeking, for example)
*
* Inputs: valid AACDecInfo struct
*
* Outputs: updated state variables in aacDecInfo
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: only need to clear data which is persistent between frames
* (such as overlap buffer)
**************************************************************************************/
int FlushCodec(AACDecInfo *aacDecInfo)
{
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
ClearBuffer(psi->overlap, AAC_MAX_NCHANS * AAC_MAX_NSAMPS * sizeof(int));
ClearBuffer(psi->prevWinShape, AAC_MAX_NCHANS * sizeof(int));
return ERR_AAC_NONE;
}

View File

@@ -1,415 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: huffman.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
*
* huffman.c - Huffman decoding
**************************************************************************************/
#include "coder.h"
/**************************************************************************************
* Function: DecodeHuffmanScalar
*
* Description: decode one Huffman symbol from bitstream
*
* Inputs: pointers to Huffman table and info struct
* left-aligned bit buffer with >= huffTabInfo->maxBits bits
*
* Outputs: decoded symbol in *val
*
* Return: number of bits in symbol
*
* Notes: assumes canonical Huffman codes:
* first CW always 0, we have "count" CW's of length "nBits" bits
* starting CW for codes of length nBits+1 =
* (startCW[nBits] + count[nBits]) << 1
* if there are no codes at nBits, then we just keep << 1 each time
* (since count[nBits] = 0)
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ int DecodeHuffmanScalar(const signed short *huffTab, const HuffInfo *huffTabInfo, unsigned int bitBuf, signed int *val)
{
unsigned int count, start, shift, t;
const unsigned /*char*/ int *countPtr;
const signed short *map;
map = huffTab + huffTabInfo->offset;
countPtr = huffTabInfo->count;
start = 0;
count = 0;
shift = 32;
do {
start += count;
start <<= 1;
map += count;
count = *countPtr++;
shift--;
t = (bitBuf >> shift) - start;
} while (t >= count);
*val = (signed int)pgm_read_word(&map[t]);
return (countPtr - huffTabInfo->count);
}
#define APPLY_SIGN(v, s) {(v) ^= ((signed int)(s) >> 31); (v) -= ((signed int)(s) >> 31);}
#define GET_QUAD_SIGNBITS(v) (((unsigned int)(v) << 17) >> 29) /* bits 14-12, unsigned */
#define GET_QUAD_W(v) (((signed int)(v) << 20) >> 29) /* bits 11-9, sign-extend */
#define GET_QUAD_X(v) (((signed int)(v) << 23) >> 29) /* bits 8-6, sign-extend */
#define GET_QUAD_Y(v) (((signed int)(v) << 26) >> 29) /* bits 5-3, sign-extend */
#define GET_QUAD_Z(v) (((signed int)(v) << 29) >> 29) /* bits 2-0, sign-extend */
#define GET_PAIR_SIGNBITS(v) (((unsigned int)(v) << 20) >> 30) /* bits 11-10, unsigned */
#define GET_PAIR_Y(v) (((signed int)(v) << 22) >> 27) /* bits 9-5, sign-extend */
#define GET_PAIR_Z(v) (((signed int)(v) << 27) >> 27) /* bits 4-0, sign-extend */
#define GET_ESC_SIGNBITS(v) (((unsigned int)(v) << 18) >> 30) /* bits 13-12, unsigned */
#define GET_ESC_Y(v) (((signed int)(v) << 20) >> 26) /* bits 11-6, sign-extend */
#define GET_ESC_Z(v) (((signed int)(v) << 26) >> 26) /* bits 5-0, sign-extend */
/**************************************************************************************
* Function: UnpackZeros
*
* Description: fill a section of coefficients with zeros
*
* Inputs: number of coefficients
*
* Outputs: nVals zeros, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 4 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
static void UnpackZeros(int nVals, int *coef)
{
while (nVals > 0) {
*coef++ = 0;
*coef++ = 0;
*coef++ = 0;
*coef++ = 0;
nVals -= 4;
}
}
/**************************************************************************************
* Function: UnpackQuads
*
* Description: decode a section of 4-way vector Huffman coded coefficients
*
* Inputs BitStreamInfo struct pointing to start of codewords for this section
* index of Huffman codebook
* number of coefficients
*
* Outputs: nVals coefficients, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 4 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void UnpackQuads(BitStreamInfo *bsi, int cb, int nVals, int *coef)
{
int w, x, y, z, maxBits, nCodeBits, nSignBits, val;
unsigned int bitBuf;
maxBits = huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET].maxBits + 4;
while (nVals > 0) {
/* decode quad */
bitBuf = GetBitsNoAdvance(bsi, maxBits) << (32 - maxBits);
nCodeBits = DecodeHuffmanScalar(huffTabSpec, &huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET], bitBuf, &val);
w = GET_QUAD_W(val);
x = GET_QUAD_X(val);
y = GET_QUAD_Y(val);
z = GET_QUAD_Z(val);
bitBuf <<= nCodeBits;
nSignBits = (int)GET_QUAD_SIGNBITS(val);
AdvanceBitstream(bsi, nCodeBits + nSignBits);
if (nSignBits) {
if (w) {APPLY_SIGN(w, bitBuf); bitBuf <<= 1;}
if (x) {APPLY_SIGN(x, bitBuf); bitBuf <<= 1;}
if (y) {APPLY_SIGN(y, bitBuf); bitBuf <<= 1;}
if (z) {APPLY_SIGN(z, bitBuf); bitBuf <<= 1;}
}
*coef++ = w; *coef++ = x; *coef++ = y; *coef++ = z;
nVals -= 4;
}
}
/**************************************************************************************
* Function: UnpackPairsNoEsc
*
* Description: decode a section of 2-way vector Huffman coded coefficients,
* using non-esc tables (5 through 10)
*
* Inputs BitStreamInfo struct pointing to start of codewords for this section
* index of Huffman codebook (must not be the escape codebook)
* number of coefficients
*
* Outputs: nVals coefficients, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 2 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void UnpackPairsNoEsc(BitStreamInfo *bsi, int cb, int nVals, int *coef)
{
int y, z, maxBits, nCodeBits, nSignBits, val;
unsigned int bitBuf;
maxBits = huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET].maxBits + 2;
while (nVals > 0) {
/* decode pair */
bitBuf = GetBitsNoAdvance(bsi, maxBits) << (32 - maxBits);
nCodeBits = DecodeHuffmanScalar(huffTabSpec, &huffTabSpecInfo[cb-HUFFTAB_SPEC_OFFSET], bitBuf, &val);
y = GET_PAIR_Y(val);
z = GET_PAIR_Z(val);
bitBuf <<= nCodeBits;
nSignBits = GET_PAIR_SIGNBITS(val);
AdvanceBitstream(bsi, nCodeBits + nSignBits);
if (nSignBits) {
if (y) {APPLY_SIGN(y, bitBuf); bitBuf <<= 1;}
if (z) {APPLY_SIGN(z, bitBuf); bitBuf <<= 1;}
}
*coef++ = y; *coef++ = z;
nVals -= 2;
}
}
/**************************************************************************************
* Function: UnpackPairsEsc
*
* Description: decode a section of 2-way vector Huffman coded coefficients,
* using esc table (11)
*
* Inputs BitStreamInfo struct pointing to start of codewords for this section
* index of Huffman codebook (must be the escape codebook)
* number of coefficients
*
* Outputs: nVals coefficients, starting at coef
*
* Return: none
*
* Notes: assumes nVals is always a multiple of 2 because all scalefactor bands
* are a multiple of 4 coefficients long
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void UnpackPairsEsc(BitStreamInfo *bsi, int cb, int nVals, int *coef)
{
int y, z, maxBits, nCodeBits, nSignBits, n, val;
unsigned int bitBuf;
maxBits = huffTabSpecInfo[cb - HUFFTAB_SPEC_OFFSET].maxBits + 2;
while (nVals > 0) {
/* decode pair with escape value */
bitBuf = GetBitsNoAdvance(bsi, maxBits) << (32 - maxBits);
nCodeBits = DecodeHuffmanScalar(huffTabSpec, &huffTabSpecInfo[cb-HUFFTAB_SPEC_OFFSET], bitBuf, &val);
y = GET_ESC_Y(val);
z = GET_ESC_Z(val);
bitBuf <<= nCodeBits;
nSignBits = GET_ESC_SIGNBITS(val);
AdvanceBitstream(bsi, nCodeBits + nSignBits);
if (y == 16) {
n = 4;
while (GetBits(bsi, 1) == 1)
n++;
y = (1 << n) + GetBits(bsi, n);
}
if (z == 16) {
n = 4;
while (GetBits(bsi, 1) == 1)
n++;
z = (1 << n) + GetBits(bsi, n);
}
if (nSignBits) {
if (y) {APPLY_SIGN(y, bitBuf); bitBuf <<= 1;}
if (z) {APPLY_SIGN(z, bitBuf); bitBuf <<= 1;}
}
*coef++ = y; *coef++ = z;
nVals -= 2;
}
}
/**************************************************************************************
* Function: DecodeSpectrumLong
*
* Description: decode transform coefficients for frame with one long block
*
* Inputs: platform specific info struct
* BitStreamInfo struct pointing to start of spectral data
* (14496-3, table 4.4.29)
* index of current channel
*
* Outputs: decoded, quantized coefficients for this channel
*
* Return: none
*
* Notes: adds in pulse data if present
* fills coefficient buffer with zeros in any region not coded with
* codebook in range [1, 11] (including sfb's above sfbMax)
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ void DecodeSpectrumLong(PSInfoBase *psi, BitStreamInfo *bsi, int ch)
{
int i, sfb, cb, nVals, offset;
const /*short*/ int *sfbTab;
unsigned char *sfbCodeBook;
int *coef;
ICSInfo *icsInfo;
PulseInfo *pi;
coef = psi->coef[ch];
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
/* decode long block */
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
sfbCodeBook = psi->sfbCodeBook[ch];
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
cb = *sfbCodeBook++;
nVals = sfbTab[sfb+1] - sfbTab[sfb];
if (cb == 0)
UnpackZeros(nVals, coef);
else if (cb <= 4)
UnpackQuads(bsi, cb, nVals, coef);
else if (cb <= 10)
UnpackPairsNoEsc(bsi, cb, nVals, coef);
else if (cb == 11)
UnpackPairsEsc(bsi, cb, nVals, coef);
else
UnpackZeros(nVals, coef);
coef += nVals;
}
/* fill with zeros above maxSFB */
nVals = NSAMPS_LONG - sfbTab[sfb];
UnpackZeros(nVals, coef);
/* add pulse data, if present */
pi = &psi->pulseInfo[ch];
if (pi->pulseDataPresent) {
coef = psi->coef[ch];
offset = sfbTab[pi->startSFB];
for (i = 0; i < pi->numPulse; i++) {
offset += pi->offset[i];
if (coef[offset] > 0)
coef[offset] += pi->amp[i];
else
coef[offset] -= pi->amp[i];
}
ASSERT(offset < NSAMPS_LONG);
}
}
/**************************************************************************************
* Function: DecodeSpectrumShort
*
* Description: decode transform coefficients for frame with eight short blocks
*
* Inputs: platform specific info struct
* BitStreamInfo struct pointing to start of spectral data
* (14496-3, table 4.4.29)
* index of current channel
*
* Outputs: decoded, quantized coefficients for this channel
*
* Return: none
*
* Notes: fills coefficient buffer with zeros in any region not coded with
* codebook in range [1, 11] (including sfb's above sfbMax)
* deinterleaves window groups into 8 windows
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ void DecodeSpectrumShort(PSInfoBase *psi, BitStreamInfo *bsi, int ch)
{
int gp, cb, nVals=0, win, offset, sfb;
const /*short*/ int *sfbTab;
unsigned char *sfbCodeBook;
int *coef;
ICSInfo *icsInfo;
coef = psi->coef[ch];
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
/* decode short blocks, deinterleaving in-place */
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
sfbCodeBook = psi->sfbCodeBook[ch];
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
nVals = sfbTab[sfb+1] - sfbTab[sfb];
cb = *sfbCodeBook++;
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
offset = win*NSAMPS_SHORT;
if (cb == 0)
UnpackZeros(nVals, coef + offset);
else if (cb <= 4)
UnpackQuads(bsi, cb, nVals, coef + offset);
else if (cb <= 10)
UnpackPairsNoEsc(bsi, cb, nVals, coef + offset);
else if (cb == 11)
UnpackPairsEsc(bsi, cb, nVals, coef + offset);
else
UnpackZeros(nVals, coef + offset);
}
coef += nVals;
}
/* fill with zeros above maxSFB */
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
offset = win*NSAMPS_SHORT;
nVals = NSAMPS_SHORT - sfbTab[sfb];
UnpackZeros(nVals, coef + offset);
}
coef += nVals;
coef += (icsInfo->winGroupLen[gp] - 1)*NSAMPS_SHORT;
}
ASSERT(coef == psi->coef[ch] + NSAMPS_LONG);
}

View File

@@ -1,177 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: hufftabs.c,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* hufftabs.c - Huffman symbol tables
**************************************************************************************/
#include "coder.h"
const HuffInfo huffTabSpecInfo[11] PROGMEM = {
/* table 0 not used */
{11, { 1, 0, 0, 0, 8, 0, 24, 0, 24, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
{ 9, { 0, 0, 1, 1, 7, 24, 15, 19, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 81},
{16, { 1, 0, 0, 4, 2, 6, 3, 5, 15, 15, 8, 9, 3, 3, 5, 2, 0, 0, 0, 0}, 162},
{12, { 0, 0, 0, 10, 6, 0, 9, 21, 8, 14, 11, 2, 0, 0, 0, 0, 0, 0, 0, 0}, 243},
{13, { 1, 0, 0, 4, 4, 0, 4, 12, 12, 12, 18, 10, 4, 0, 0, 0, 0, 0, 0, 0}, 324},
{11, { 0, 0, 0, 9, 0, 16, 13, 8, 23, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 405},
{12, { 1, 0, 2, 1, 0, 4, 5, 10, 14, 15, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0}, 486},
{10, { 0, 0, 1, 5, 7, 10, 14, 15, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 550},
{15, { 1, 0, 2, 1, 0, 4, 3, 8, 11, 20, 31, 38, 32, 14, 4, 0, 0, 0, 0, 0}, 614},
{12, { 0, 0, 0, 3, 8, 14, 17, 25, 31, 41, 22, 8, 0, 0, 0, 0, 0, 0, 0, 0}, 783},
{12, { 0, 0, 0, 2, 6, 7, 16, 59, 55, 95, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 952},
};
const signed short huffTabSpec[1241] PROGMEM = {
/* spectrum table 1 [81] (signed) */
0x0000, 0x0200, 0x0e00, 0x0007, 0x0040, 0x0001, 0x0038, 0x0008, 0x01c0, 0x03c0, 0x0e40, 0x0039, 0x0078, 0x01c8, 0x000f, 0x0240,
0x003f, 0x0fc0, 0x01f8, 0x0238, 0x0047, 0x0e08, 0x0009, 0x0208, 0x01c1, 0x0048, 0x0041, 0x0e38, 0x0201, 0x0e07, 0x0207, 0x0e01,
0x01c7, 0x0278, 0x0e78, 0x03c8, 0x004f, 0x0079, 0x01c9, 0x01cf, 0x03f8, 0x0239, 0x007f, 0x0e48, 0x0e0f, 0x0fc8, 0x01f9, 0x03c1,
0x03c7, 0x0e47, 0x0ff8, 0x01ff, 0x0049, 0x020f, 0x0241, 0x0e41, 0x0248, 0x0fc1, 0x0e3f, 0x0247, 0x023f, 0x0e39, 0x0fc7, 0x0e09,
0x0209, 0x03cf, 0x0e79, 0x0e4f, 0x03f9, 0x0249, 0x0fc9, 0x027f, 0x0fcf, 0x0fff, 0x0279, 0x03c9, 0x0e49, 0x0e7f, 0x0ff9, 0x03ff,
0x024f,
/* spectrum table 2 [81] (signed) */
0x0000, 0x0200, 0x0e00, 0x0001, 0x0038, 0x0007, 0x01c0, 0x0008, 0x0040, 0x01c8, 0x0e40, 0x0078, 0x000f, 0x0047, 0x0039, 0x0e07,
0x03c0, 0x0238, 0x0fc0, 0x003f, 0x0208, 0x0201, 0x01c1, 0x0e08, 0x0041, 0x01f8, 0x0e01, 0x01c7, 0x0e38, 0x0240, 0x0048, 0x0009,
0x0207, 0x0079, 0x0239, 0x0e78, 0x01cf, 0x03c8, 0x0247, 0x0209, 0x0e48, 0x01f9, 0x0248, 0x0e0f, 0x0ff8, 0x0e39, 0x03f8, 0x0278,
0x03c1, 0x0e47, 0x0fc8, 0x0e09, 0x0fc1, 0x0fc7, 0x01ff, 0x020f, 0x023f, 0x007f, 0x0049, 0x0e41, 0x0e3f, 0x004f, 0x03c7, 0x01c9,
0x0241, 0x03cf, 0x0e79, 0x03f9, 0x0fff, 0x0e4f, 0x0e49, 0x0249, 0x0fcf, 0x03c9, 0x0e7f, 0x0fc9, 0x027f, 0x03ff, 0x0ff9, 0x0279,
0x024f,
/* spectrum table 3 [81] (unsigned) */
0x0000, 0x1200, 0x1001, 0x1040, 0x1008, 0x2240, 0x2009, 0x2048, 0x2041, 0x2208, 0x3049, 0x2201, 0x3248, 0x4249, 0x3209, 0x3241,
0x1400, 0x1002, 0x200a, 0x2440, 0x3288, 0x2011, 0x3051, 0x2280, 0x304a, 0x3448, 0x1010, 0x2088, 0x2050, 0x1080, 0x2042, 0x2408,
0x4289, 0x3089, 0x3250, 0x4251, 0x3281, 0x2210, 0x3211, 0x2081, 0x4449, 0x424a, 0x3441, 0x320a, 0x2012, 0x3052, 0x3488, 0x3290,
0x2202, 0x2401, 0x3091, 0x2480, 0x4291, 0x3242, 0x3409, 0x4252, 0x4489, 0x2090, 0x308a, 0x3212, 0x3481, 0x3450, 0x3490, 0x3092,
0x4491, 0x4451, 0x428a, 0x4292, 0x2082, 0x2410, 0x3282, 0x3411, 0x444a, 0x3442, 0x4492, 0x448a, 0x4452, 0x340a, 0x2402, 0x3482,
0x3412,
/* spectrum table 4 [81] (unsigned) */
0x4249, 0x3049, 0x3241, 0x3248, 0x3209, 0x1200, 0x2240, 0x0000, 0x2009, 0x2208, 0x2201, 0x2048, 0x1001, 0x2041, 0x1008, 0x1040,
0x4449, 0x4251, 0x4289, 0x424a, 0x3448, 0x3441, 0x3288, 0x3409, 0x3051, 0x304a, 0x3250, 0x3089, 0x320a, 0x3281, 0x3242, 0x3211,
0x2440, 0x2408, 0x2280, 0x2401, 0x2042, 0x2088, 0x200a, 0x2050, 0x2081, 0x2202, 0x2011, 0x2210, 0x1400, 0x1002, 0x1080, 0x1010,
0x4291, 0x4489, 0x4451, 0x4252, 0x428a, 0x444a, 0x3290, 0x3488, 0x3450, 0x3091, 0x3052, 0x3481, 0x308a, 0x3411, 0x3212, 0x4491,
0x3282, 0x340a, 0x3442, 0x4292, 0x4452, 0x448a, 0x2090, 0x2480, 0x2012, 0x2410, 0x2082, 0x2402, 0x4492, 0x3092, 0x3490, 0x3482,
0x3412,
/* spectrum table 5 [81] (signed) */
0x0000, 0x03e0, 0x0020, 0x0001, 0x001f, 0x003f, 0x03e1, 0x03ff, 0x0021, 0x03c0, 0x0002, 0x0040, 0x001e, 0x03df, 0x0041, 0x03fe,
0x0022, 0x03c1, 0x005f, 0x03e2, 0x003e, 0x03a0, 0x0060, 0x001d, 0x0003, 0x03bf, 0x0023, 0x0061, 0x03fd, 0x03a1, 0x007f, 0x003d,
0x03e3, 0x03c2, 0x0042, 0x03de, 0x005e, 0x03be, 0x007e, 0x03c3, 0x005d, 0x0062, 0x0043, 0x03a2, 0x03dd, 0x001c, 0x0380, 0x0081,
0x0080, 0x039f, 0x0004, 0x009f, 0x03fc, 0x0024, 0x03e4, 0x0381, 0x003c, 0x007d, 0x03bd, 0x03a3, 0x03c4, 0x039e, 0x0082, 0x005c,
0x0044, 0x0063, 0x0382, 0x03dc, 0x009e, 0x007c, 0x039d, 0x0383, 0x0064, 0x03a4, 0x0083, 0x009d, 0x03bc, 0x009c, 0x0384, 0x0084,
0x039c,
/* spectrum table 6 [81] (signed) */
0x0000, 0x0020, 0x001f, 0x0001, 0x03e0, 0x0021, 0x03e1, 0x003f, 0x03ff, 0x005f, 0x0041, 0x03c1, 0x03df, 0x03c0, 0x03e2, 0x0040,
0x003e, 0x0022, 0x001e, 0x03fe, 0x0002, 0x005e, 0x03c2, 0x03de, 0x0042, 0x03a1, 0x0061, 0x007f, 0x03e3, 0x03bf, 0x0023, 0x003d,
0x03fd, 0x0060, 0x03a0, 0x001d, 0x0003, 0x0062, 0x03be, 0x03c3, 0x0043, 0x007e, 0x005d, 0x03dd, 0x03a2, 0x0063, 0x007d, 0x03bd,
0x03a3, 0x003c, 0x03fc, 0x0081, 0x0381, 0x039f, 0x0024, 0x009f, 0x03e4, 0x001c, 0x0382, 0x039e, 0x0044, 0x03dc, 0x0380, 0x0082,
0x009e, 0x03c4, 0x0080, 0x005c, 0x0004, 0x03bc, 0x03a4, 0x007c, 0x009d, 0x0064, 0x0083, 0x0383, 0x039d, 0x0084, 0x0384, 0x039c,
0x009c,
/* spectrum table 7 [64] (unsigned) */
0x0000, 0x0420, 0x0401, 0x0821, 0x0841, 0x0822, 0x0440, 0x0402, 0x0861, 0x0823, 0x0842, 0x0460, 0x0403, 0x0843, 0x0862, 0x0824,
0x0881, 0x0825, 0x08a1, 0x0863, 0x0844, 0x0404, 0x0480, 0x0882, 0x0845, 0x08a2, 0x0405, 0x08c1, 0x04a0, 0x0826, 0x0883, 0x0865,
0x0864, 0x08a3, 0x0846, 0x08c2, 0x0827, 0x0866, 0x0406, 0x04c0, 0x0884, 0x08e1, 0x0885, 0x08e2, 0x08a4, 0x08c3, 0x0847, 0x08e3,
0x08c4, 0x08a5, 0x0886, 0x0867, 0x04e0, 0x0407, 0x08c5, 0x08a6, 0x08e4, 0x0887, 0x08a7, 0x08e5, 0x08e6, 0x08c6, 0x08c7, 0x08e7,
/* spectrum table 8 [64] (unsigned) */
0x0821, 0x0841, 0x0420, 0x0822, 0x0401, 0x0842, 0x0000, 0x0440, 0x0402, 0x0861, 0x0823, 0x0862, 0x0843, 0x0863, 0x0881, 0x0824,
0x0882, 0x0844, 0x0460, 0x0403, 0x0883, 0x0864, 0x08a2, 0x08a1, 0x0845, 0x0825, 0x08a3, 0x0865, 0x0884, 0x08a4, 0x0404, 0x0885,
0x0480, 0x0846, 0x08c2, 0x08c1, 0x0826, 0x0866, 0x08c3, 0x08a5, 0x04a0, 0x08c4, 0x0405, 0x0886, 0x08e1, 0x08e2, 0x0847, 0x08c5,
0x08e3, 0x0827, 0x08a6, 0x0867, 0x08c6, 0x08e4, 0x04c0, 0x0887, 0x0406, 0x08e5, 0x08e6, 0x08c7, 0x08a7, 0x04e0, 0x0407, 0x08e7,
/* spectrum table 9 [169] (unsigned) */
0x0000, 0x0420, 0x0401, 0x0821, 0x0841, 0x0822, 0x0440, 0x0402, 0x0861, 0x0842, 0x0823, 0x0460, 0x0403, 0x0843, 0x0862, 0x0824,
0x0881, 0x0844, 0x0825, 0x0882, 0x0863, 0x0404, 0x0480, 0x08a1, 0x0845, 0x0826, 0x0864, 0x08a2, 0x08c1, 0x0883, 0x0405, 0x0846,
0x04a0, 0x0827, 0x0865, 0x0828, 0x0901, 0x0884, 0x08a3, 0x08c2, 0x08e1, 0x0406, 0x0902, 0x0848, 0x0866, 0x0847, 0x0885, 0x0921,
0x0829, 0x08e2, 0x04c0, 0x08a4, 0x08c3, 0x0903, 0x0407, 0x0922, 0x0868, 0x0886, 0x0867, 0x0408, 0x0941, 0x08c4, 0x0849, 0x08a5,
0x0500, 0x04e0, 0x08e3, 0x0942, 0x0923, 0x0904, 0x082a, 0x08e4, 0x08c5, 0x08a6, 0x0888, 0x0887, 0x0869, 0x0961, 0x08a8, 0x0520,
0x0905, 0x0943, 0x084a, 0x0409, 0x0962, 0x0924, 0x08c6, 0x0981, 0x0889, 0x0906, 0x082b, 0x0925, 0x0944, 0x08a7, 0x08e5, 0x084b,
0x082c, 0x0982, 0x0963, 0x086a, 0x08a9, 0x08c7, 0x0907, 0x0964, 0x040a, 0x08e6, 0x0983, 0x0540, 0x0945, 0x088a, 0x08c8, 0x084c,
0x0926, 0x0927, 0x088b, 0x0560, 0x08c9, 0x086b, 0x08aa, 0x0908, 0x08e8, 0x0985, 0x086c, 0x0965, 0x08e7, 0x0984, 0x0966, 0x0946,
0x088c, 0x08e9, 0x08ab, 0x040b, 0x0986, 0x08ca, 0x0580, 0x0947, 0x08ac, 0x08ea, 0x0928, 0x040c, 0x0967, 0x0909, 0x0929, 0x0948,
0x08eb, 0x0987, 0x08cb, 0x090b, 0x0968, 0x08ec, 0x08cc, 0x090a, 0x0949, 0x090c, 0x092a, 0x092b, 0x092c, 0x094b, 0x0989, 0x094a,
0x0969, 0x0988, 0x096a, 0x098a, 0x098b, 0x094c, 0x096b, 0x096c, 0x098c,
/* spectrum table 10 [169] (unsigned) */
0x0821, 0x0822, 0x0841, 0x0842, 0x0420, 0x0401, 0x0823, 0x0862, 0x0861, 0x0843, 0x0863, 0x0440, 0x0402, 0x0844, 0x0882, 0x0824,
0x0881, 0x0000, 0x0883, 0x0864, 0x0460, 0x0403, 0x0884, 0x0845, 0x08a2, 0x0825, 0x08a1, 0x08a3, 0x0865, 0x08a4, 0x0885, 0x08c2,
0x0846, 0x08c3, 0x0480, 0x08c1, 0x0404, 0x0826, 0x0866, 0x08a5, 0x08c4, 0x0886, 0x08c5, 0x08e2, 0x0867, 0x0847, 0x08a6, 0x0902,
0x08e3, 0x04a0, 0x08e1, 0x0405, 0x0901, 0x0827, 0x0903, 0x08e4, 0x0887, 0x0848, 0x08c6, 0x08e5, 0x0828, 0x0868, 0x0904, 0x0888,
0x08a7, 0x0905, 0x08a8, 0x08e6, 0x08c7, 0x0922, 0x04c0, 0x08c8, 0x0923, 0x0869, 0x0921, 0x0849, 0x0406, 0x0906, 0x0924, 0x0889,
0x0942, 0x0829, 0x08e7, 0x0907, 0x0925, 0x08e8, 0x0943, 0x08a9, 0x0944, 0x084a, 0x0941, 0x086a, 0x0926, 0x08c9, 0x0500, 0x088a,
0x04e0, 0x0962, 0x08e9, 0x0963, 0x0946, 0x082a, 0x0961, 0x0927, 0x0407, 0x0908, 0x0945, 0x086b, 0x08aa, 0x0909, 0x0965, 0x0408,
0x0964, 0x084b, 0x08ea, 0x08ca, 0x0947, 0x088b, 0x082b, 0x0982, 0x0928, 0x0983, 0x0966, 0x08ab, 0x0984, 0x0967, 0x0985, 0x086c,
0x08cb, 0x0520, 0x0948, 0x0540, 0x0981, 0x0409, 0x088c, 0x0929, 0x0986, 0x084c, 0x090a, 0x092a, 0x082c, 0x0968, 0x0987, 0x08eb,
0x08ac, 0x08cc, 0x0949, 0x090b, 0x0988, 0x040a, 0x08ec, 0x0560, 0x094a, 0x0969, 0x096a, 0x040b, 0x096b, 0x092b, 0x094b, 0x0580,
0x090c, 0x0989, 0x094c, 0x092c, 0x096c, 0x098b, 0x040c, 0x098a, 0x098c,
/* spectrum table 11 [289] (unsigned) */
0x0000, 0x2041, 0x2410, 0x1040, 0x1001, 0x2081, 0x2042, 0x2082, 0x2043, 0x20c1, 0x20c2, 0x1080, 0x2083, 0x1002, 0x20c3, 0x2101,
0x2044, 0x2102, 0x2084, 0x2103, 0x20c4, 0x10c0, 0x1003, 0x2141, 0x2142, 0x2085, 0x2104, 0x2045, 0x2143, 0x20c5, 0x2144, 0x2105,
0x2182, 0x2086, 0x2181, 0x2183, 0x20c6, 0x2046, 0x2110, 0x20d0, 0x2405, 0x2403, 0x2404, 0x2184, 0x2406, 0x1100, 0x2106, 0x1004,
0x2090, 0x2145, 0x2150, 0x2407, 0x2402, 0x2408, 0x2087, 0x21c2, 0x20c7, 0x2185, 0x2146, 0x2190, 0x240a, 0x21c3, 0x21c1, 0x2409,
0x21d0, 0x2050, 0x2047, 0x2107, 0x240b, 0x21c4, 0x240c, 0x2210, 0x2401, 0x2186, 0x2250, 0x2088, 0x2147, 0x2290, 0x240d, 0x2203,
0x2202, 0x20c8, 0x1140, 0x240e, 0x22d0, 0x21c5, 0x2108, 0x2187, 0x21c6, 0x1005, 0x2204, 0x240f, 0x2310, 0x2048, 0x2201, 0x2390,
0x2148, 0x2350, 0x20c9, 0x2205, 0x21c7, 0x2089, 0x2206, 0x2242, 0x2243, 0x23d0, 0x2109, 0x2188, 0x1180, 0x2244, 0x2149, 0x2207,
0x21c8, 0x2049, 0x2283, 0x1006, 0x2282, 0x2241, 0x2245, 0x210a, 0x208a, 0x2246, 0x20ca, 0x2189, 0x2284, 0x2208, 0x2285, 0x2247,
0x22c3, 0x204a, 0x11c0, 0x2286, 0x21c9, 0x20cb, 0x214a, 0x2281, 0x210b, 0x22c2, 0x2342, 0x218a, 0x2343, 0x208b, 0x1400, 0x214b,
0x22c5, 0x22c4, 0x2248, 0x21ca, 0x2209, 0x1010, 0x210d, 0x1007, 0x20cd, 0x22c6, 0x2341, 0x2344, 0x2303, 0x208d, 0x2345, 0x220a,
0x218b, 0x2288, 0x2287, 0x2382, 0x2304, 0x204b, 0x210c, 0x22c1, 0x20cc, 0x204d, 0x2302, 0x21cb, 0x20ce, 0x214c, 0x214d, 0x2384,
0x210e, 0x22c7, 0x2383, 0x2305, 0x2346, 0x2306, 0x1200, 0x22c8, 0x208c, 0x2249, 0x2385, 0x218d, 0x228a, 0x23c2, 0x220b, 0x224a,
0x2386, 0x2289, 0x214e, 0x22c9, 0x2381, 0x208e, 0x218c, 0x204c, 0x2348, 0x1008, 0x2347, 0x21cc, 0x2307, 0x21cd, 0x23c3, 0x2301,
0x218e, 0x208f, 0x23c5, 0x23c4, 0x204e, 0x224b, 0x210f, 0x2387, 0x220d, 0x2349, 0x220c, 0x214f, 0x20cf, 0x228b, 0x22ca, 0x2308,
0x23c6, 0x23c7, 0x220e, 0x23c1, 0x21ce, 0x1240, 0x1009, 0x224d, 0x224c, 0x2309, 0x2388, 0x228d, 0x2389, 0x230a, 0x218f, 0x21cf,
0x224e, 0x23c8, 0x22cb, 0x22ce, 0x204f, 0x228c, 0x228e, 0x234b, 0x234a, 0x22cd, 0x22cc, 0x220f, 0x238b, 0x234c, 0x230d, 0x23c9,
0x238a, 0x1280, 0x230b, 0x224f, 0x100a, 0x230c, 0x12c0, 0x230e, 0x228f, 0x234d, 0x100d, 0x238c, 0x23ca, 0x23cb, 0x22cf, 0x238d,
0x1340, 0x100b, 0x234e, 0x23cc, 0x23cd, 0x230f, 0x1380, 0x238e, 0x234f, 0x1300, 0x238f, 0x100e, 0x100c, 0x23ce, 0x13c0, 0x100f,
0x23cf,
};
const HuffInfo huffTabScaleFactInfo PROGMEM =
{19, { 1, 0, 1, 3, 2, 4, 3, 5, 4, 6, 6, 6, 5, 8, 4, 7, 3, 7, 46, 0}, 0};
/* note - includes offset of -60 (4.6.2.3 in spec) */
const signed short huffTabScaleFact[121] PROGMEM = {
/* scale factor table [121] */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, 6, -6, 7, -7, 8,
-8, 9, -9, 10, -10, -11, 11, 12, -12, 13, -13, 14, -14, 16, 15, 17,
18, -15, -17, -16, 19, -18, -19, 20, -20, 21, -21, 22, -22, 23, -23, -25,
25, -27, -24, -26, 24, -28, 27, 29, -30, -29, 26, -31, -34, -33, -32, -36,
28, -35, -38, -37, 30, -39, -41, -57, -59, -58, -60, 38, 39, 40, 41, 42,
57, 37, 31, 32, 33, 34, 35, 36, 44, 51, 52, 53, 54, 55, 56, 50,
45, 46, 47, 48, 49, 58, -54, -52, -51, -50, -55, 43, 60, 59, -56, -53,
-45, -44, -42, -40, -43, -49, -48, -46, -47,
};

View File

@@ -1,589 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: imdct.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* imdct.c - inverse MDCT
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define RND_VAL (1 << (FBITS_OUT_IMDCT-1))
#ifndef AAC_ENABLE_SBR
/**************************************************************************************
* Function: DecWindowOverlap
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence LONG-LONG
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data")))*/ static void DecWindowOverlap(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
pcm1 = pcm0 + (1024 - 1) * nChans;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
if (winTypeCurr == winTypePrev) {
/* cut window loads in half since current and overlap sections use same symmetric window */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
} else {
/* different windows for current and overlap parts - should still fit in registers on ARM w/o stack spill */
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
}
/**************************************************************************************
* Function: DecWindowOverlapLongStart
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence LONG-START
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data")))*/ static void DecWindowOverlapLongStart(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
pcm1 = pcm0 + (1024 - 1) * nChans;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
in = *buf1--;
*over1-- = 0; /* Wn = 0 for n = (2047, 2046, ... 1600) */
*over0++ = in >> 1; /* Wn = 1 for n = (1024, 1025, ... 1471) */
} while (--i);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++; /* W[0], W[1], ... --> W[255], W[254], ... */
w1 = *wndCurr++; /* W[127], W[126], ... --> W[128], W[129], ... */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* Wn = short window for n = (1599, 1598, ... , 1536) */
*over0++ = MULSHIFT32(w1, in); /* Wn = short window for n = (1472, 1473, ... , 1535) */
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapLongStop
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence LONG-STOP
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data")))*/ static void DecWindowOverlapLongStop(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
pcm1 = pcm0 + (1024 - 1) * nChans;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
/* Wn = 0 for n = (0, 1, ... 447) */
/* Wn = 1 for n = (576, 577, ... 1023) */
in = *buf0++;
f1 = in >> 1; /* scale since skipping multiply by Q31 */
in = *over0;
*pcm0 = CLIPTOSHORT( (in + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (--i);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapShort
*
* Description: apply synthesis window, do overlap-add, clip to 16-bit PCM,
* for winSequence EIGHT-SHORT (does all 8 short blocks)
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* number of channels
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 16-bit PCM, interleaved by nChans
*
* Return: none
*
* Notes: this processes one channel at a time, but skips every other sample in
* the output buffer (pcm) for stereo interleaving
* this should fit in registers on ARM
*
* TODO: ARM5E version with saturating overlap/add (QADD)
* asm code with free pointer updates, better load scheduling
**************************************************************************************/
/*__attribute__ ((section (".data"))) */ static void DecWindowOverlapShort(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1;
short *pcm1;
const int *wndPrev, *wndCurr;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* pcm[0-447] = 0 + overlap[0-447] */
i = 448;
do {
f0 = *over0++;
f1 = *over0++;
*pcm0 = CLIPTOSHORT( (f0 + RND_VAL) >> FBITS_OUT_IMDCT ); pcm0 += nChans;
*pcm0 = CLIPTOSHORT( (f1 + RND_VAL) >> FBITS_OUT_IMDCT ); pcm0 += nChans;
i -= 2;
} while (i);
/* pcm[448-575] = Wp[0-127] * block0[0-127] + overlap[448-575] */
pcm1 = pcm0 + (128 - 1) * nChans;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *over1;
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
/* save over0/over1 for next short block, in the slots just vacated */
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
/* pcm[576-703] = Wc[128-255] * block0[128-255] + Wc[0-127] * block1[0-127] + overlap[576-703]
* pcm[704-831] = Wc[128-255] * block1[128-255] + Wc[0-127] * block2[0-127] + overlap[704-831]
* pcm[832-959] = Wc[128-255] * block2[128-255] + Wc[0-127] * block3[0-127] + overlap[832-959]
*/
for (i = 0; i < 3; i++) {
pcm0 += 64 * nChans;
pcm1 = pcm0 + (128 - 1) * nChans;
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 - 128); /* from last short block */
in += *(over0 + 0); /* from last full frame */
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *(over1 - 128); /* from last short block */
in += *(over1 + 0); /* from last full frame */
*pcm1 = CLIPTOSHORT( (in + f1 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm1 -= nChans;
/* save over0/over1 for next short block, in the slots just vacated */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* pcm[960-1023] = Wc[128-191] * block3[128-191] + Wc[0-63] * block4[0-63] + overlap[960-1023]
* over[0-63] = Wc[192-255] * block3[192-255] + Wc[64-127] * block4[64-127]
*/
pcm0 += 64 * nChans;
over0 -= 832; /* points at overlap[64] */
over1 = over0 + 128 - 1; /* points at overlap[191] */
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 + 768); /* from last short block */
in += *(over0 + 896); /* from last full frame */
*pcm0 = CLIPTOSHORT( (in - f0 + RND_VAL) >> FBITS_OUT_IMDCT );
pcm0 += nChans;
in = *(over1 + 768); /* from last short block */
*(over1 - 128) = in + f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* save in overlap[128-191] */
*over0++ = MULSHIFT32(w1, in); /* save in overlap[64-127] */
} while (over0 < over1);
/* over0 now points at overlap[128] */
/* over[64-191] = Wc[128-255] * block4[128-255] + Wc[0-127] * block5[0-127]
* over[192-319] = Wc[128-255] * block5[128-255] + Wc[0-127] * block6[0-127]
* over[320-447] = Wc[128-255] * block6[128-255] + Wc[0-127] * block7[0-127]
* over[448-576] = Wc[128-255] * block7[128-255]
*/
for (i = 0; i < 3; i++) {
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
/* from last short block */
*(over0 - 128) -= f0;
*(over1 - 128)+= f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* over[576-1024] = 0 */
i = 448;
over0 += 64;
do {
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
i -= 4;
} while (i);
}
#endif /* !AAC_ENABLE_SBR */
/**************************************************************************************
* Function: IMDCT
*
* Description: inverse transform and convert to 16-bit PCM
*
* Inputs: valid AACDecInfo struct
* index of current channel (0 for SCE/LFE, 0 or 1 for CPE)
* output channel (range = [0, nChans-1])
*
* Outputs: complete frame of decoded PCM, after inverse transform
*
* Return: 0 if successful, -1 if error
*
* Notes: If AAC_ENABLE_SBR is defined at compile time then window + overlap
* does NOT clip to 16-bit PCM and does NOT interleave channels
* If AAC_ENABLE_SBR is NOT defined at compile time, then window + overlap
* does clip to 16-bit PCM and interleaves channels
* If SBR is enabled at compile time, but we don't know whether it is
* actually used for this frame (e.g. the first frame of a stream),
* we need to produce both clipped 16-bit PCM in outbuf AND
* unclipped 32-bit PCM in the SBR input buffer. In this case we make
* a separate pass over the 32-bit PCM to produce 16-bit PCM output.
* This inflicts a slight performance hit when decoding non-SBR files.
**************************************************************************************/
int IMDCT(AACDecInfo *aacDecInfo, int ch, int chOut, short *outbuf)
{
int i;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
outbuf += chOut;
/* optimized type-IV DCT (operates inplace) */
if (icsInfo->winSequence == 2) {
/* 8 short blocks */
for (i = 0; i < 8; i++)
DCT4(0, psi->coef[ch] + i*128, psi->gbCurrent[ch]);
} else {
/* 1 long block */
DCT4(1, psi->coef[ch], psi->gbCurrent[ch]);
}
#ifdef AAC_ENABLE_SBR
/* window, overlap-add, don't clip to short (send to SBR decoder)
* store the decoded 32-bit samples in top half (second AAC_MAX_NSAMPS samples) of coef buffer
*/
if (icsInfo->winSequence == 0)
DecWindowOverlapNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 1)
DecWindowOverlapLongStartNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 2)
DecWindowOverlapShortNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 3)
DecWindowOverlapLongStopNoClip(psi->coef[ch], psi->overlap[chOut], psi->sbrWorkBuf[ch], icsInfo->winShape, psi->prevWinShape[chOut]);
if (!aacDecInfo->sbrEnabled) {
for (i = 0; i < AAC_MAX_NSAMPS; i++) {
*outbuf = CLIPTOSHORT((psi->sbrWorkBuf[ch][i] + RND_VAL) >> FBITS_OUT_IMDCT);
outbuf += aacDecInfo->nChans;
}
}
aacDecInfo->rawSampleBuf[ch] = psi->sbrWorkBuf[ch];
aacDecInfo->rawSampleBytes = sizeof(int);
aacDecInfo->rawSampleFBits = FBITS_OUT_IMDCT;
#else
/* window, overlap-add, round to PCM - optimized for each window sequence */
if (icsInfo->winSequence == 0)
DecWindowOverlap(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 1)
DecWindowOverlapLongStart(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 2)
DecWindowOverlapShort(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
else if (icsInfo->winSequence == 3)
DecWindowOverlapLongStop(psi->coef[ch], psi->overlap[chOut], outbuf, aacDecInfo->nChans, icsInfo->winShape, psi->prevWinShape[chOut]);
aacDecInfo->rawSampleBuf[ch] = 0;
aacDecInfo->rawSampleBytes = 0;
aacDecInfo->rawSampleFBits = 0;
#endif
psi->prevWinShape[chOut] = icsInfo->winShape;
return 0;
}

View File

@@ -1,484 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: noiseless.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* noiseless.c - decode channel info, scalefactors, quantized coefficients,
* scalefactor band codebook, and TNS coefficients from bitstream
**************************************************************************************/
#include "coder.h"
//#include "profile.h"
//#define PROFILE_START(x)
//#define PROFILE_END()
/**************************************************************************************
* Function: DecodeICSInfo
*
* Description: decode individual channel stream info
*
* Inputs: BitStreamInfo struct pointing to start of ICS info
* (14496-3, table 4.4.6)
* sample rate index
*
* Outputs: updated icsInfo struct
*
* Return: none
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ void DecodeICSInfo(BitStreamInfo *bsi, ICSInfo *icsInfo, int sampRateIdx)
{
int sfb, g, mask;
icsInfo->icsResBit = GetBits(bsi, 1);
icsInfo->winSequence = GetBits(bsi, 2);
icsInfo->winShape = GetBits(bsi, 1);
if (icsInfo->winSequence == 2) {
/* short block */
icsInfo->maxSFB = GetBits(bsi, 4);
icsInfo->sfGroup = GetBits(bsi, 7);
icsInfo->numWinGroup = 1;
icsInfo->winGroupLen[0] = 1;
mask = 0x40; /* start with bit 6 */
for (g = 0; g < 7; g++) {
if (icsInfo->sfGroup & mask) {
icsInfo->winGroupLen[icsInfo->numWinGroup - 1]++;
} else {
icsInfo->numWinGroup++;
icsInfo->winGroupLen[icsInfo->numWinGroup - 1] = 1;
}
mask >>= 1;
}
} else {
/* long block */
icsInfo->maxSFB = GetBits(bsi, 6);
icsInfo->predictorDataPresent = GetBits(bsi, 1);
if (icsInfo->predictorDataPresent) {
icsInfo->predictorReset = GetBits(bsi, 1);
if (icsInfo->predictorReset)
icsInfo->predictorResetGroupNum = GetBits(bsi, 5);
for (sfb = 0; sfb < MIN(icsInfo->maxSFB, predSFBMax[sampRateIdx]); sfb++)
icsInfo->predictionUsed[sfb] = GetBits(bsi, 1);
}
icsInfo->numWinGroup = 1;
icsInfo->winGroupLen[0] = 1;
}
}
/**************************************************************************************
* Function: DecodeSectionData
*
* Description: decode section data (scale factor band groupings and
* associated Huffman codebooks)
*
* Inputs: BitStreamInfo struct pointing to start of ICS info
* (14496-3, table 4.4.25)
* window sequence (short or long blocks)
* number of window groups (1 for long blocks, 1-8 for short blocks)
* max coded scalefactor band
*
* Outputs: index of Huffman codebook for each scalefactor band in each section
*
* Return: none
*
* Notes: sectCB, sectEnd, sfbCodeBook, ordered by window groups for short blocks
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void DecodeSectionData(BitStreamInfo *bsi, int winSequence, int numWinGrp, int maxSFB, unsigned char *sfbCodeBook)
{
int g, cb, sfb;
int sectLen, sectLenBits, sectLenIncr, sectEscapeVal;
sectLenBits = (winSequence == 2 ? 3 : 5);
sectEscapeVal = (1 << sectLenBits) - 1;
for (g = 0; g < numWinGrp; g++) {
sfb = 0;
while (sfb < maxSFB) {
cb = GetBits(bsi, 4); /* next section codebook */
sectLen = 0;
do {
sectLenIncr = GetBits(bsi, sectLenBits);
sectLen += sectLenIncr;
} while (sectLenIncr == sectEscapeVal);
sfb += sectLen;
while (sectLen--)
*sfbCodeBook++ = (unsigned char)cb;
}
ASSERT(sfb == maxSFB);
}
}
/**************************************************************************************
* Function: DecodeOneScaleFactor
*
* Description: decode one scalefactor using scalefactor Huffman codebook
*
* Inputs: BitStreamInfo struct pointing to start of next coded scalefactor
*
* Outputs: updated BitstreamInfo struct
*
* Return: one decoded scalefactor, including index_offset of -60
**************************************************************************************/
static int DecodeOneScaleFactor(BitStreamInfo *bsi)
{
int nBits, val;
unsigned int bitBuf;
/* decode next scalefactor from bitstream */
bitBuf = GetBitsNoAdvance(bsi, huffTabScaleFactInfo.maxBits) << (32 - huffTabScaleFactInfo.maxBits);
//PROFILE_START("DecodeHuffmanScalar");
nBits = DecodeHuffmanScalar(huffTabScaleFact, &huffTabScaleFactInfo, bitBuf, &val);
AdvanceBitstream(bsi, nBits);
//PROFILE_END();
return val;
}
/**************************************************************************************
* Function: DecodeScaleFactors
*
* Description: decode scalefactors, PNS energy, and intensity stereo weights
*
* Inputs: BitStreamInfo struct pointing to start of ICS info
* (14496-3, table 4.4.26)
* number of window groups (1 for long blocks, 1-8 for short blocks)
* max coded scalefactor band
* global gain (starting value for differential scalefactor coding)
* index of Huffman codebook for each scalefactor band in each section
*
* Outputs: decoded scalefactor for each section
*
* Return: none
*
* Notes: sfbCodeBook, scaleFactors ordered by window groups for short blocks
* for section with codebook 13, scaleFactors buffer has decoded PNS
* energy instead of regular scalefactor
* for section with codebook 14 or 15, scaleFactors buffer has intensity
* stereo weight instead of regular scalefactor
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void DecodeScaleFactors(BitStreamInfo *bsi, int numWinGrp, int maxSFB, int globalGain,
unsigned char *sfbCodeBook, short *scaleFactors)
{
int g, sfbCB, nrg, npf, val, sf, is;
/* starting values for differential coding */
sf = globalGain;
is = 0;
nrg = globalGain - 90 - 256;
npf = 1;
for (g = 0; g < numWinGrp * maxSFB; g++) {
sfbCB = *sfbCodeBook++;
if (sfbCB == 14 || sfbCB == 15) {
/* intensity stereo - differential coding */
val = DecodeOneScaleFactor(bsi);
is += val;
*scaleFactors++ = (short)is;
} else if (sfbCB == 13) {
/* PNS - first energy is directly coded, rest are Huffman coded (npf = noise_pcm_flag) */
if (npf) {
val = GetBits(bsi, 9);
npf = 0;
} else {
val = DecodeOneScaleFactor(bsi);
}
nrg += val;
*scaleFactors++ = (short)nrg;
} else if (sfbCB >= 1 && sfbCB <= 11) {
/* regular (non-zero) region - differential coding */
val = DecodeOneScaleFactor(bsi);
sf += val;
*scaleFactors++ = (short)sf;
} else {
/* inactive scalefactor band if codebook 0 */
*scaleFactors++ = 0;
}
}
}
/**************************************************************************************
* Function: DecodePulseInfo
*
* Description: decode pulse information
*
* Inputs: BitStreamInfo struct pointing to start of pulse info
* (14496-3, table 4.4.7)
*
* Outputs: updated PulseInfo struct
*
* Return: none
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void DecodePulseInfo(BitStreamInfo *bsi, PulseInfo *pi)
{
int i;
pi->numPulse = GetBits(bsi, 2) + 1; /* add 1 here */
pi->startSFB = GetBits(bsi, 6);
for (i = 0; i < pi->numPulse; i++) {
pi->offset[i] = GetBits(bsi, 5);
pi->amp[i] = GetBits(bsi, 4);
}
}
/**************************************************************************************
* Function: DecodeTNSInfo
*
* Description: decode TNS filter information
*
* Inputs: BitStreamInfo struct pointing to start of TNS info
* (14496-3, table 4.4.27)
* window sequence (short or long blocks)
*
* Outputs: updated TNSInfo struct
* buffer of decoded (signed) TNS filter coefficients
*
* Return: none
**************************************************************************************/
static const signed char sgnMask[3] = {0x02, 0x04, 0x08};
static const signed char negMask[3] = {~0x03, ~0x07, ~0x0f};
static void DecodeTNSInfo(BitStreamInfo *bsi, int winSequence, TNSInfo *ti, signed char *tnsCoef)
{
int i, w, f, coefBits, compress;
signed char c, s, n;
unsigned char *filtLength, *filtOrder, *filtDir;
filtLength = ti->length;
filtOrder = ti->order;
filtDir = ti->dir;
if (winSequence == 2) {
/* short blocks */
for (w = 0; w < NWINDOWS_SHORT; w++) {
ti->numFilt[w] = GetBits(bsi, 1);
if (ti->numFilt[w]) {
ti->coefRes[w] = GetBits(bsi, 1) + 3;
*filtLength = GetBits(bsi, 4);
*filtOrder = GetBits(bsi, 3);
if (*filtOrder) {
*filtDir++ = GetBits(bsi, 1);
compress = GetBits(bsi, 1);
coefBits = (int)ti->coefRes[w] - compress; /* 2, 3, or 4 */
s = sgnMask[coefBits - 2];
n = negMask[coefBits - 2];
for (i = 0; i < *filtOrder; i++) {
c = GetBits(bsi, coefBits);
if (c & s) c |= n;
*tnsCoef++ = c;
}
}
filtLength++;
filtOrder++;
}
}
} else {
/* long blocks */
ti->numFilt[0] = GetBits(bsi, 2);
if (ti->numFilt[0])
ti->coefRes[0] = GetBits(bsi, 1) + 3;
for (f = 0; f < ti->numFilt[0]; f++) {
*filtLength = GetBits(bsi, 6);
*filtOrder = GetBits(bsi, 5);
if (*filtOrder) {
*filtDir++ = GetBits(bsi, 1);
compress = GetBits(bsi, 1);
coefBits = (int)ti->coefRes[0] - compress; /* 2, 3, or 4 */
s = sgnMask[coefBits - 2];
n = negMask[coefBits - 2];
for (i = 0; i < *filtOrder; i++) {
c = GetBits(bsi, coefBits);
if (c & s) c |= n;
*tnsCoef++ = c;
}
}
filtLength++;
filtOrder++;
}
}
}
/* bitstream field lengths for gain control data:
* gainBits[winSequence][0] = maxWindow (how many gain windows there are)
* gainBits[winSequence][1] = locBitsZero (bits for alocCode if window == 0)
* gainBits[winSequence][2] = locBits (bits for alocCode if window != 0)
*/
static const unsigned char gainBits[4][3] = {
{1, 5, 5}, /* long */
{2, 4, 2}, /* start */
{8, 2, 2}, /* short */
{2, 4, 5}, /* stop */
};
/**************************************************************************************
* Function: DecodeGainControlInfo
*
* Description: decode gain control information (SSR profile only)
*
* Inputs: BitStreamInfo struct pointing to start of gain control info
* (14496-3, table 4.4.12)
* window sequence (short or long blocks)
*
* Outputs: updated GainControlInfo struct
*
* Return: none
**************************************************************************************/
static void DecodeGainControlInfo(BitStreamInfo *bsi, int winSequence, GainControlInfo *gi)
{
int bd, wd, ad;
int locBits, locBitsZero, maxWin;
gi->maxBand = GetBits(bsi, 2);
maxWin = (int)gainBits[winSequence][0];
locBitsZero = (int)gainBits[winSequence][1];
locBits = (int)gainBits[winSequence][2];
for (bd = 1; bd <= gi->maxBand; bd++) {
for (wd = 0; wd < maxWin; wd++) {
gi->adjNum[bd][wd] = GetBits(bsi, 3);
for (ad = 0; ad < gi->adjNum[bd][wd]; ad++) {
gi->alevCode[bd][wd][ad] = GetBits(bsi, 4);
gi->alocCode[bd][wd][ad] = GetBits(bsi, (wd == 0 ? locBitsZero : locBits));
}
}
}
}
/**************************************************************************************
* Function: DecodeICS
*
* Description: decode individual channel stream
*
* Inputs: platform specific info struct
* BitStreamInfo struct pointing to start of individual channel stream
* (14496-3, table 4.4.24)
* index of current channel
*
* Outputs: updated section data, scale factor data, pulse data, TNS data,
* and gain control data
*
* Return: none
**************************************************************************************/
static void DecodeICS(PSInfoBase *psi, BitStreamInfo *bsi, int ch)
{
int globalGain;
ICSInfo *icsInfo;
PulseInfo *pi;
TNSInfo *ti;
GainControlInfo *gi;
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
globalGain = GetBits(bsi, 8);
if (!psi->commonWin)
DecodeICSInfo(bsi, icsInfo, psi->sampRateIdx);
DecodeSectionData(bsi, icsInfo->winSequence, icsInfo->numWinGroup, icsInfo->maxSFB, psi->sfbCodeBook[ch]);
DecodeScaleFactors(bsi, icsInfo->numWinGroup, icsInfo->maxSFB, globalGain, psi->sfbCodeBook[ch], psi->scaleFactors[ch]);
pi = &psi->pulseInfo[ch];
pi->pulseDataPresent = GetBits(bsi, 1);
if (pi->pulseDataPresent)
DecodePulseInfo(bsi, pi);
ti = &psi->tnsInfo[ch];
ti->tnsDataPresent = GetBits(bsi, 1);
if (ti->tnsDataPresent)
DecodeTNSInfo(bsi, icsInfo->winSequence, ti, ti->coef);
gi = &psi->gainControlInfo[ch];
gi->gainControlDataPresent = GetBits(bsi, 1);
if (gi->gainControlDataPresent)
DecodeGainControlInfo(bsi, icsInfo->winSequence, gi);
}
/**************************************************************************************
* Function: DecodeNoiselessData
*
* Description: decode noiseless data (side info and transform coefficients)
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer pointing to start of individual channel stream
* (14496-3, table 4.4.24)
* pointer to bit offset
* pointer to number of valid bits remaining in buf
* index of current channel
*
* Outputs: updated global gain, section data, scale factor data, pulse data,
* TNS data, gain control data, and spectral data
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int DecodeNoiselessData(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail, int ch)
{
int bitsUsed;
BitStreamInfo bsi;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
SetBitstreamPointer(&bsi, (*bitsAvail+7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
DecodeICS(psi, &bsi, ch);
if (icsInfo->winSequence == 2)
DecodeSpectrumShort(psi, &bsi, ch);
else
DecodeSpectrumLong(psi, &bsi, ch);
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += ((bitsUsed + *bitOffset) >> 3);
*bitOffset = ((bitsUsed + *bitOffset) & 0x07);
*bitsAvail -= bitsUsed;
aacDecInfo->sbDeinterleaveReqd[ch] = 0;
aacDecInfo->tnsUsed |= psi->tnsInfo[ch].tnsDataPresent; /* set flag if TNS used for any channel */
return ERR_AAC_NONE;
}

View File

@@ -1,357 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: pns.c,v 1.2 2005/03/10 17:01:56 jrecker 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
*
* pns.c - perceptual noise substitution
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: Get32BitVal
*
* Description: generate 32-bit unsigned random number
*
* Inputs: last number calculated (seed, first time through)
*
* Outputs: new number, saved in *last
*
* Return: 32-bit number, uniformly distributed between [0, 2^32)
*
* Notes: uses simple linear congruential generator
**************************************************************************************/
static unsigned int Get32BitVal(unsigned int *last)
{
unsigned int r = *last;
/* use same coefs as MPEG reference code (classic LCG)
* use unsigned multiply to force reliable wraparound behavior in C (mod 2^32)
*/
r = (1664525U * r) + 1013904223U;
*last = r;
return r;
}
#define NUM_ITER_INVSQRT 4
#define X0_COEF_2 0xc0000000 /* Q29: -2.0 */
#define X0_OFF_2 0x60000000 /* Q29: 3.0 */
#define Q26_3 0x0c000000 /* Q26: 3.0 */
/**************************************************************************************
* Function: InvRootR
*
* Description: use Newton's method to solve for x = 1/sqrt(r)
*
* Inputs: r in Q30 format, range = [0.25, 1] (normalize inputs to this range)
*
* Outputs: none
*
* Return: x = Q29, range = (1, 2)
*
* Notes: guaranteed to converge and not overflow for any r in this range
*
* xn+1 = xn - f(xn)/f'(xn)
* f(x) = 1/sqrt(r) - x = 0 (find root)
* = 1/x^2 - r
* f'(x) = -2/x^3
*
* so xn+1 = xn/2 * (3 - r*xn^2)
*
* NUM_ITER_INVSQRT = 3, maxDiff = 1.3747e-02
* NUM_ITER_INVSQRT = 4, maxDiff = 3.9832e-04
**************************************************************************************/
static int InvRootR(int r)
{
int i, xn, t;
/* use linear equation for initial guess
* x0 = -2*r + 3 (so x0 always >= correct answer in range [0.25, 1))
* xn = Q29 (at every step)
*/
xn = (MULSHIFT32(r, X0_COEF_2) << 2) + X0_OFF_2;
for (i = 0; i < NUM_ITER_INVSQRT; i++) {
t = MULSHIFT32(xn, xn); /* Q26 = Q29*Q29 */
t = Q26_3 - (MULSHIFT32(r, t) << 2); /* Q26 = Q26 - (Q31*Q26 << 1) */
xn = MULSHIFT32(xn, t) << (6 - 1); /* Q29 = (Q29*Q26 << 6), and -1 for division by 2 */
}
/* clip to range (1.0, 2.0)
* (because of rounding, this can converge to xn slightly > 2.0 when r is near 0.25)
*/
if (xn >> 30)
xn = (1 << 30) - 1;
return xn;
}
/**************************************************************************************
* Function: ScaleNoiseVector
*
* Description: apply scaling to vector of noise coefficients for one scalefactor band
*
* Inputs: unscaled coefficients
* number of coefficients in vector (one scalefactor band of coefs)
* scalefactor for this band (i.e. noise energy)
*
* Outputs: nVals coefficients in Q(FBITS_OUT_DQ_OFF)
*
* Return: guard bit mask (OR of abs value of all noise coefs)
**************************************************************************************/
static int ScaleNoiseVector(int *coef, int nVals, int sf)
{
/* pow(2, i/4.0) for i = [0,1,2,3], format = Q30 */
static const int pow14[4] PROGMEM = {
0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65
};
int i, c, spec, energy, sq, scalef, scalei, invSqrtEnergy, z, gbMask;
energy = 0;
for (i = 0; i < nVals; i++) {
spec = coef[i];
/* max nVals = max SFB width = 96, so energy can gain < 2^7 bits in accumulation */
sq = (spec * spec) >> 8; /* spec*spec range = (-2^30, 2^30) */
energy += sq;
}
/* unless nVals == 1 (or the number generator is broken...), this should not happen */
if (energy == 0)
return 0; /* coef[i] must = 0 for i = [0, nVals-1], so gbMask = 0 */
/* pow(2, sf/4) * pow(2, FBITS_OUT_DQ_OFF) */
scalef = pow14[sf & 0x3];
scalei = (sf >> 2) + FBITS_OUT_DQ_OFF;
/* energy has implied factor of 2^-8 since we shifted the accumulator
* normalize energy to range [0.25, 1.0), calculate 1/sqrt(1), and denormalize
* i.e. divide input by 2^(30-z) and convert to Q30
* output of 1/sqrt(i) now has extra factor of 2^((30-z)/2)
* for energy > 0, z is an even number between 0 and 28
* final scaling of invSqrtEnergy:
* 2^(15 - z/2) to compensate for implicit 2^(30-z) factor in input
* +4 to compensate for implicit 2^-8 factor in input
*/
z = CLZ(energy) - 2; /* energy has at least 2 leading zeros (see acc loop) */
z &= 0xfffffffe; /* force even */
invSqrtEnergy = InvRootR(energy << z); /* energy << z must be in range [0x10000000, 0x40000000] */
scalei -= (15 - z/2 + 4); /* nInt = 1/sqrt(energy) in Q29 */
/* normalize for final scaling */
z = CLZ(invSqrtEnergy) - 1;
invSqrtEnergy <<= z;
scalei -= (z - 3 - 2); /* -2 for scalef, z-3 for invSqrtEnergy */
scalef = MULSHIFT32(scalef, invSqrtEnergy); /* scalef (input) = Q30, invSqrtEnergy = Q29 * 2^z */
gbMask = 0;
if (scalei < 0) {
scalei = -scalei;
if (scalei > 31)
scalei = 31;
for (i = 0; i < nVals; i++) {
c = MULSHIFT32(coef[i], scalef) >> scalei;
gbMask |= FASTABS(c);
coef[i] = c;
}
} else {
/* for scalei <= 16, no clipping possible (coef[i] is < 2^15 before scaling)
* for scalei > 16, just saturate exponent (rare)
* scalef is close to full-scale (since we normalized invSqrtEnergy)
* remember, we are just producing noise here
*/
if (scalei > 16)
scalei = 16;
for (i = 0; i < nVals; i++) {
c = MULSHIFT32(coef[i] << scalei, scalef);
coef[i] = c;
gbMask |= FASTABS(c);
}
}
return gbMask;
}
/**************************************************************************************
* Function: GenerateNoiseVector
*
* Description: create vector of noise coefficients for one scalefactor band
*
* Inputs: seed for number generator
* number of coefficients to generate
*
* Outputs: buffer of nVals coefficients, range = [-2^15, 2^15)
* updated seed for number generator
*
* Return: none
**************************************************************************************/
static void GenerateNoiseVector(int *coef, int *last, int nVals)
{
int i;
for (i = 0; i < nVals; i++)
coef[i] = ((signed int)Get32BitVal((unsigned int *)last)) >> 16;
}
/**************************************************************************************
* Function: CopyNoiseVector
*
* Description: copy vector of noise coefficients for one scalefactor band from L to R
*
* Inputs: buffer of left coefficients
* number of coefficients to copy
*
* Outputs: buffer of right coefficients
*
* Return: none
**************************************************************************************/
static void CopyNoiseVector(int *coefL, int *coefR, int nVals)
{
int i;
for (i = 0; i < nVals; i++)
coefR[i] = coefL[i];
}
/**************************************************************************************
* Function: PNS
*
* Description: apply perceptual noise substitution, if enabled (MPEG-4 only)
*
* Inputs: valid AACDecInfo struct
* index of current channel
*
* Outputs: shaped noise in scalefactor bands where PNS is active
* updated minimum guard bit count for this channel
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
int PNS(AACDecInfo *aacDecInfo, int ch)
{
int gp, sfb, win, width, nSamps, gb, gbMask;
int *coef;
const /*short*/ int *sfbTab;
unsigned char *sfbCodeBook;
short *scaleFactors;
int msMaskOffset, checkCorr, genNew;
unsigned char msMask;
unsigned char *msMaskPtr;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
if (!psi->pnsUsed[ch])
return 0;
if (icsInfo->winSequence == 2) {
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
nSamps = NSAMPS_SHORT;
} else {
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
nSamps = NSAMPS_LONG;
}
coef = psi->coef[ch];
sfbCodeBook = psi->sfbCodeBook[ch];
scaleFactors = psi->scaleFactors[ch];
checkCorr = (aacDecInfo->currBlockID == AAC_ID_CPE && psi->commonWin == 1 ? 1 : 0);
gbMask = 0;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
msMaskPtr = psi->msMaskBits + ((gp*icsInfo->maxSFB) >> 3);
msMaskOffset = ((gp*icsInfo->maxSFB) & 0x07);
msMask = (*msMaskPtr++) >> msMaskOffset;
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
width = sfbTab[sfb+1] - sfbTab[sfb];
if (sfbCodeBook[sfb] == 13) {
if (ch == 0) {
/* generate new vector, copy into ch 1 if it's possible that the channels will be correlated
* if ch 1 has PNS enabled for this SFB but it's uncorrelated (i.e. ms_used == 0),
* the copied values will be overwritten when we process ch 1
*/
GenerateNoiseVector(coef, &psi->pnsLastVal, width);
if (checkCorr && psi->sfbCodeBook[1][gp*icsInfo->maxSFB + sfb] == 13)
CopyNoiseVector(coef, psi->coef[1] + (coef - psi->coef[0]), width);
} else {
/* generate new vector if no correlation between channels */
genNew = 1;
if (checkCorr && psi->sfbCodeBook[0][gp*icsInfo->maxSFB + sfb] == 13) {
if ( (psi->msMaskPresent == 1 && (msMask & 0x01)) || psi->msMaskPresent == 2 )
genNew = 0;
}
if (genNew)
GenerateNoiseVector(coef, &psi->pnsLastVal, width);
}
gbMask |= ScaleNoiseVector(coef, width, psi->scaleFactors[ch][gp*icsInfo->maxSFB + sfb]);
}
coef += width;
/* get next mask bit (should be branchless on ARM) */
msMask >>= 1;
if (++msMaskOffset == 8) {
msMask = *msMaskPtr++;
msMaskOffset = 0;
}
}
coef += (nSamps - sfbTab[icsInfo->maxSFB]);
}
sfbCodeBook += icsInfo->maxSFB;
scaleFactors += icsInfo->maxSFB;
}
/* update guard bit count if necessary */
gb = CLZ(gbMask) - 1;
if (psi->gbCurrent[ch] > gb)
psi->gbCurrent[ch] = gb;
return 0;
}

View File

@@ -1,127 +0,0 @@
Fixed-point HE-AAC decoder
Developed by RealNetworks, 2005
===============================
Overview
--------
This module contains a high-performance HE-AAC decoder for 32-bit fixed-point
processors. The following is a summary of what is and is not supported:
Supported:
- MPEG2, MPEG4 low complexity decoding (intensity stereo, M-S, TNS, PNS)
- spectral band replication (SBR), high-quality mode
- mono, stereo, and multichannel modes
- ADTS, ADIF, and raw data block file formats
Not currently supported:
- main or SSR profile, LTP
- coupling channel elements (CCE)
- 960/1920-sample frame size
- low-power mode SBR
- downsampled (single-rate) SBR
- parametric stereo
Highlights
----------
- highly optimized for ARM processors (details in docs/ subdirectory)
- reference x86 implementation
- C and assembly code only (C++ not required for codec library)
- reentrant, statically linkable
- low memory (details in docs/ subdirectory)
- option to use Intel Integrated Performance Primitives (details below)
Supported platforms and toolchains
----------------------------------
This codec should run on any 32-bit fixed-point processor which can perform a full 32x32-bit
multiply (providing a 64-bit result). The following processors and toolchains are supported:
- x86, Microsoft Visual C++
- x86, GNU toolchain (gcc)
- ARM, ARM Developer Suite (ADS)
- ARM, Microsoft Embedded Visual C++
- ARM, GNU toolchain (gcc)
ARM refers to any processor supporting ARM architecture v.4 or above. Thumb is not required.
Generally ADS produces the fastest code. EVC 3 does not support inline assembly code for
ARM targets, so calls to MULSHIFT32 (smull on ARM) are left as function calls. This incurs
a significant performance penalty. For the fastest code on targets which do not normally use
ADS consider compiling with ADS, using the -S option to output assembly code, and
feeding this assembly code to the assembler of your choice. This might require some
syntax changes in the .S file.
Adding support for a new processor is fairly simple. Simply add a new block to the file
real/assembly.h which implements the required inline assembly functions for your processor.
Something like
...
#elif defined NEW_PROCESSOR
/* you implement MULSHIFT32() and so forth */
#else
#error Unsupported platform in assembly.h
#endif
Optionally you can rewrite or add assembly language files optimized for your platform. Note
that many of the algorithms are designed for an ARM-type processor, so performance of the
unmodified C code might be noticeably worse on other architectures.
Adding support for a new toolchain is straightforward. Use the sample projects or the
Helix makefiles as a template for which source files to include.
Multichannel
------------
For multichannel, just set AAC_MAX_NCHANS in pub/aacdec.h to the desired max number
of channels (default = 2) and recompile. This increases RAM usage since more memory
is required to save state for multiple channels. See docs/memory.xls for details.
Directory structure
-------------------
fixpt/ platform-independent code and tables, public API
fixpt/docs memory and CPU usage figures, callgraphs
fixpt/hxwrap Helix wrapper code and makefiles
fixpt/ipp source code which uses IPP for decoding (see the "IPP" section below)
fixpt/pub public header files
fixpt/real source code for RealNetworks' AAC decoder
fixpt/testwrap sample code to build a command-line test application
Code organization
-----------------
fixpt/
aacdec.c main decode functions, exports C-only API
aactabs.c common tables used by all implementations
fixpt/pub/
aaccommon.h low-level codec API which aacdec.c calls
aacdec.h high-level codec API which applications call
statname.h symbols which get name-mangled by C preprocessor to allow static linking
fixpt/ipp source code for wrapper files which link in IPP libraries
fixpt/real full source code for RealNetworks AAC decoder, including SBR
fixpt/real/asm optimized assembly code files for certain platforms
To build an AAC decoder library, you'll need to compile the top-level files and EITHER
real/*.c OR ipp/*.c and the appropriate IPP library.
Decoder using Real code: aacdec.c + aactabs.c + real/*.c + real/asm/[platform]/*.s (if necessary)
Decoder using IPP code: aacdec.c + aactabs.c + ipp/*.c + ippac*.lib
IPP
---
For certain platforms Intel<65> has created highly-optimized object code libraries of DSP
routines. These are called the Intel<65> Integrated Performance Primitives (IPP). If IPP
libraries are available for a platform, this AAC decoder can link them in and use them
instead of the RealNetworks source code. To use IPP, you still need to build the top-level
files (aacdec.c, aactabs.c). You also build the files in ipp/*.c. These are just thin
wrappers which provide the glue logic between the top-level decode functions in
aacdec.c and the optimized DSP primitives in the IPP libraries. IPP libraries are not
included in this module. You must obtain them WITH A LICENSE directly from Intel.
Further info on the latest versions of IPP (as of the date of this readme) is available
from the URL below:
http://www.intel.com/software/products/ipp/
This site explains how to obtain IPP and the terms under which IPP libraries may be used.
The code in this module is merely wrapper code which calls IPP functions. You are fully
responsible for adhering to the license agreement under which you obtain the IPP
libraries from Intel.
readme.txt last updated 02/25/05

View File

@@ -1,431 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbr.c,v 1.3 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
*
* sbr.c - top level functions for SBR
**************************************************************************************/
#if defined(USE_DEFAULT_STDLIB) || defined(ESP_PLATFORM)
#include <stdio.h>
#include <stdlib.h>
#else
#include "hlxclib/stdlib.h"
#endif
#include "sbr.h"
/**************************************************************************************
* Function: InitSBRState
*
* Description: initialize PSInfoSBR struct at start of stream or after flush
*
* Inputs: valid AACDecInfo struct
*
* Outputs: PSInfoSBR struct with proper initial state
*
* Return: none
**************************************************************************************/
static void InitSBRState(PSInfoSBR *psi)
{
int i, ch;
unsigned char *c;
if (!psi)
return;
/* clear SBR state structure */
c = (unsigned char *)psi;
for (i = 0; i < (int)sizeof(PSInfoSBR); i++)
*c++ = 0;
/* initialize non-zero state variables */
for (ch = 0; ch < AAC_MAX_NCHANS; ch++) {
psi->sbrChan[ch].reset = 1;
psi->sbrChan[ch].laPrev = -1;
}
}
/**************************************************************************************
* Function: InitSBR
*
* Description: initialize SBR decoder
*
* Inputs: valid AACDecInfo struct
*
* Outputs: PSInfoSBR struct to hold SBR state information
*
* Return: 0 if successful, error code (< 0) if error
*
* Note: memory allocation for SBR is only done here
**************************************************************************************/
int InitSBR(AACDecInfo *aacDecInfo)
{
PSInfoSBR *psi;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* allocate SBR state structure */
psi = (PSInfoSBR *)malloc(sizeof(PSInfoSBR));
if (!psi) {
printf("OOM in SBR, can't allocate %d bytes\n", sizeof(PSInfoSBR));
return ERR_AAC_SBR_INIT;
}
InitSBRState(psi);
aacDecInfo->psInfoSBR = psi;
return ERR_AAC_NONE;
}
int InitSBRPre(AACDecInfo *aacDecInfo, void **ptr, int *sz)
{
PSInfoSBR *psi;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* allocate SBR state structure */
psi = (PSInfoSBR *)*ptr;
*sz -= sizeof(PSInfoSBR);
if (*sz < 0) {
printf("OOM in SBR, can't allocate %d bytes\n", sizeof(PSInfoSBR));
return ERR_AAC_SBR_INIT;
}
InitSBRState(psi);
*ptr = (void*)((char*)(*ptr) + sizeof(PSInfoSBR));
aacDecInfo->psInfoSBR = psi;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: FreeSBR
*
* Description: free SBR decoder
*
* Inputs: valid AACDecInfo struct
*
* Outputs: none
*
* Return: none
*
* Note: memory deallocation for SBR is only done here
**************************************************************************************/
void FreeSBR(AACDecInfo *aacDecInfo)
{
if (aacDecInfo && aacDecInfo->psInfoSBR)
free(aacDecInfo->psInfoSBR);
return;
}
/**************************************************************************************
* Function: DecodeSBRBitstream
*
* Description: decode sideband information for SBR
*
* Inputs: valid AACDecInfo struct
* fill buffer with SBR extension block
* number of bytes in fill buffer
* base output channel (range = [0, nChans-1])
*
* Outputs: initialized state structs (SBRHdr, SBRGrid, SBRFreq, SBRChan)
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: SBR payload should be in aacDecInfo->fillBuf
* returns with no error if fill buffer is not an SBR extension block,
* or if current block is not a fill block (e.g. for LFE upsampling)
**************************************************************************************/
int DecodeSBRBitstream(AACDecInfo *aacDecInfo, int chBase)
{
int headerFlag;
BitStreamInfo bsi;
PSInfoSBR *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoSBR)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR);
if (aacDecInfo->currBlockID != AAC_ID_FIL || (aacDecInfo->fillExtType != EXT_SBR_DATA && aacDecInfo->fillExtType != EXT_SBR_DATA_CRC))
return ERR_AAC_NONE;
SetBitstreamPointer(&bsi, aacDecInfo->fillCount, aacDecInfo->fillBuf);
if (GetBits(&bsi, 4) != (unsigned int)aacDecInfo->fillExtType)
return ERR_AAC_SBR_BITSTREAM;
if (aacDecInfo->fillExtType == EXT_SBR_DATA_CRC)
psi->crcCheckWord = GetBits(&bsi, 10);
headerFlag = GetBits(&bsi, 1);
if (headerFlag) {
/* get sample rate index for output sample rate (2x base rate) */
psi->sampRateIdx = GetSampRateIdx(2 * aacDecInfo->sampRate);
if (psi->sampRateIdx < 0 || psi->sampRateIdx >= NUM_SAMPLE_RATES)
return ERR_AAC_SBR_BITSTREAM;
else if (psi->sampRateIdx >= NUM_SAMPLE_RATES_SBR)
return ERR_AAC_SBR_SINGLERATE_UNSUPPORTED;
/* reset flag = 1 if header values changed */
if (UnpackSBRHeader(&bsi, &(psi->sbrHdr[chBase])))
psi->sbrChan[chBase].reset = 1;
/* first valid SBR header should always trigger CalcFreqTables(), since psi->reset was set in InitSBR() */
if (psi->sbrChan[chBase].reset)
CalcFreqTables(&(psi->sbrHdr[chBase+0]), &(psi->sbrFreq[chBase]), psi->sampRateIdx);
/* copy and reset state to right channel for CPE */
if (aacDecInfo->prevBlockID == AAC_ID_CPE)
psi->sbrChan[chBase+1].reset = psi->sbrChan[chBase+0].reset;
}
/* if no header has been received, upsample only */
if (psi->sbrHdr[chBase].count == 0)
return ERR_AAC_NONE;
if (aacDecInfo->prevBlockID == AAC_ID_SCE) {
UnpackSBRSingleChannel(&bsi, psi, chBase);
} else if (aacDecInfo->prevBlockID == AAC_ID_CPE) {
UnpackSBRChannelPair(&bsi, psi, chBase);
} else {
return ERR_AAC_SBR_BITSTREAM;
}
ByteAlignBitstream(&bsi);
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: DecodeSBRData
*
* Description: apply SBR to one frame of PCM data
*
* Inputs: 1024 samples of decoded 32-bit PCM, before SBR
* size of input PCM samples (must be 4 bytes)
* number of fraction bits in input PCM samples
* base output channel (range = [0, nChans-1])
* initialized state structs (SBRHdr, SBRGrid, SBRFreq, SBRChan)
*
* Outputs: 2048 samples of decoded 16-bit PCM, after SBR
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int DecodeSBRData(AACDecInfo *aacDecInfo, int chBase, short *outbuf)
{
int k, l, ch, chBlock, qmfaBands, qmfsBands;
int upsampleOnly, gbIdx, gbMask;
int *inbuf;
short *outptr;
PSInfoSBR *psi;
SBRHeader *sbrHdr;
SBRGrid *sbrGrid;
SBRFreq *sbrFreq;
SBRChan *sbrChan;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoSBR)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR);
/* same header and freq tables for both channels in CPE */
sbrHdr = &(psi->sbrHdr[chBase]);
sbrFreq = &(psi->sbrFreq[chBase]);
/* upsample only if we haven't received an SBR header yet or if we have an LFE block */
if (aacDecInfo->currBlockID == AAC_ID_LFE) {
chBlock = 1;
upsampleOnly = 1;
} else if (aacDecInfo->currBlockID == AAC_ID_FIL) {
if (aacDecInfo->prevBlockID == AAC_ID_SCE)
chBlock = 1;
else if (aacDecInfo->prevBlockID == AAC_ID_CPE)
chBlock = 2;
else
return ERR_AAC_NONE;
upsampleOnly = (sbrHdr->count == 0 ? 1 : 0);
if (aacDecInfo->fillExtType != EXT_SBR_DATA && aacDecInfo->fillExtType != EXT_SBR_DATA_CRC)
return ERR_AAC_NONE;
} else {
/* ignore non-SBR blocks */
return ERR_AAC_NONE;
}
if (upsampleOnly) {
sbrFreq->kStart = 32;
sbrFreq->numQMFBands = 0;
}
for (ch = 0; ch < chBlock; ch++) {
sbrGrid = &(psi->sbrGrid[chBase + ch]);
sbrChan = &(psi->sbrChan[chBase + ch]);
if (aacDecInfo->rawSampleBuf[ch] == 0 || aacDecInfo->rawSampleBytes != 4)
return ERR_AAC_SBR_PCM_FORMAT;
inbuf = (int *)aacDecInfo->rawSampleBuf[ch];
outptr = outbuf + chBase + ch;
/* restore delay buffers (could use ring buffer or keep in temp buffer for nChans == 1) */
for (l = 0; l < HF_GEN; l++) {
for (k = 0; k < 64; k++) {
psi->XBuf[l][k][0] = psi->XBufDelay[chBase + ch][l][k][0];
psi->XBuf[l][k][1] = psi->XBufDelay[chBase + ch][l][k][1];
}
}
/* step 1 - analysis QMF */
qmfaBands = sbrFreq->kStart;
for (l = 0; l < 32; l++) {
gbMask = QMFAnalysis(inbuf + l*32, psi->delayQMFA[chBase + ch], psi->XBuf[l + HF_GEN][0],
aacDecInfo->rawSampleFBits, &(psi->delayIdxQMFA[chBase + ch]), qmfaBands);
gbIdx = ((l + HF_GEN) >> 5) & 0x01;
sbrChan->gbMask[gbIdx] |= gbMask; /* gbIdx = (0 if i < 32), (1 if i >= 32) */
}
if (upsampleOnly) {
/* no SBR - just run synthesis QMF to upsample by 2x */
qmfsBands = 32;
for (l = 0; l < 32; l++) {
/* step 4 - synthesis QMF */
QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans);
outptr += 64*aacDecInfo->nChans;
}
} else {
/* if previous frame had lower SBR starting freq than current, zero out the synthesized QMF
* bands so they aren't used as sources for patching
* after patch generation, restore from delay buffer
* can only happen after header reset
*/
for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) {
for (l = 0; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) {
psi->XBuf[l][k][0] = 0;
psi->XBuf[l][k][1] = 0;
}
}
/* step 2 - HF generation */
GenerateHighFreq(psi, sbrGrid, sbrFreq, sbrChan, ch);
/* restore SBR bands that were cleared before patch generation (time slots 0, 1 no longer needed) */
for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) {
for (l = HF_ADJ; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) {
psi->XBuf[l][k][0] = psi->XBufDelay[chBase + ch][l][k][0];
psi->XBuf[l][k][1] = psi->XBufDelay[chBase + ch][l][k][1];
}
}
/* step 3 - HF adjustment */
AdjustHighFreq(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch);
/* step 4 - synthesis QMF */
qmfsBands = sbrFreq->kStartPrev + sbrFreq->numQMFBandsPrev;
for (l = 0; l < sbrGrid->envTimeBorder[0]; l++) {
/* if new envelope starts mid-frame, use old settings until start of first envelope in this frame */
QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans);
outptr += 64*aacDecInfo->nChans;
}
qmfsBands = sbrFreq->kStart + sbrFreq->numQMFBands;
for ( ; l < 32; l++) {
/* use new settings for rest of frame (usually the entire frame, unless the first envelope starts mid-frame) */
QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans);
outptr += 64*aacDecInfo->nChans;
}
}
/* save delay */
for (l = 0; l < HF_GEN; l++) {
for (k = 0; k < 64; k++) {
psi->XBufDelay[chBase + ch][l][k][0] = psi->XBuf[l+32][k][0];
psi->XBufDelay[chBase + ch][l][k][1] = psi->XBuf[l+32][k][1];
}
}
sbrChan->gbMask[0] = sbrChan->gbMask[1];
sbrChan->gbMask[1] = 0;
if (sbrHdr->count > 0)
sbrChan->reset = 0;
}
sbrFreq->kStartPrev = sbrFreq->kStart;
sbrFreq->numQMFBandsPrev = sbrFreq->numQMFBands;
if (aacDecInfo->nChans > 0 && (chBase + ch) == aacDecInfo->nChans)
psi->frameCount++;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: FlushCodecSBR
*
* Description: flush internal SBR codec state (after seeking, for example)
*
* Inputs: valid AACDecInfo struct
*
* Outputs: updated state variables for SBR
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: SBR is heavily dependent on state from previous frames
* (e.g. delta coded scalefactors, previous envelope boundaries, etc.)
* On flush, we reset everything as if SBR had just been initialized
* for the first time. This triggers "upsample-only" mode until
* the first valid SBR header is received. Then SBR starts as usual.
**************************************************************************************/
int FlushCodecSBR(AACDecInfo *aacDecInfo)
{
PSInfoSBR *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoSBR)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR);
InitSBRState(psi);
return 0;
}

View File

@@ -1,383 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbr.h,v 1.2 2005/05/20 18:05:41 jrecker 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
*
* sbr.h - definitions of platform-specific SBR data structures, functions, and tables
**************************************************************************************/
#ifndef _SBR_H
#define _SBR_H
#include "aaccommon.h"
#include "bitstream.h"
#ifndef ASSERT
#if defined(_WIN32) && defined(_M_IX86) && (defined (_DEBUG) || defined (REL_ENABLE_ASSERTS))
#define ASSERT(x) if (!(x)) __asm int 3;
#else
#define ASSERT(x) /* do nothing */
#endif
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#define NUM_TIME_SLOTS 16
#define SAMPLES_PER_SLOT 2 /* RATE in spec */
#define NUM_SAMPLE_RATES_SBR 9 /* downsampled (single-rate) mode unsupported, so only use Fs_sbr >= 16 kHz */
#define MAX_NUM_ENV 5
#define MAX_NUM_NOISE_FLOORS 2
#define MAX_NUM_NOISE_FLOOR_BANDS 5 /* max Nq, see 4.6.18.3.6 */
#define MAX_NUM_PATCHES 5
#define MAX_NUM_SMOOTH_COEFS 5
#define HF_GEN 8
#define HF_ADJ 2
#define MAX_QMF_BANDS 48 /* max QMF subbands covered by SBR (4.6.18.3.6) */
#define FBITS_IN_QMFA 14
#define FBITS_LOST_QMFA (1 + 2 + 3 + 2 + 1) /* 1 from cTab, 2 in premul, 3 in FFT, 2 in postmul, 1 for implicit scaling by 2.0 */
#define FBITS_OUT_QMFA (FBITS_IN_QMFA - FBITS_LOST_QMFA)
#define MIN_GBITS_IN_QMFS 2
#define FBITS_IN_QMFS FBITS_OUT_QMFA
#define FBITS_LOST_DCT4_64 (2 + 3 + 2) /* 2 in premul, 3 in FFT, 2 in postmul */
#define FBITS_OUT_DQ_ENV 29 /* dequantized env scalefactors are Q(29 - envDataDequantScale) */
#define FBITS_OUT_DQ_NOISE 24 /* range of Q_orig = [2^-24, 2^6] */
#define NOISE_FLOOR_OFFSET 6
/* see comments in ApplyBoost() */
#define FBITS_GLIM_BOOST 24
#define FBITS_QLIM_BOOST 14
#define MAX_HUFF_BITS 20
#define NUM_QMF_DELAY_BUFS 10
#define DELAY_SAMPS_QMFA (NUM_QMF_DELAY_BUFS * 32)
#define DELAY_SAMPS_QMFS (NUM_QMF_DELAY_BUFS * 128)
/* additional external symbols to name-mangle for static linking */
#define FFT32C STATNAME(FFT32C)
#define CalcFreqTables STATNAME(CalcFreqTables)
#define AdjustHighFreq STATNAME(AdjustHighFreq)
#define GenerateHighFreq STATNAME(GenerateHighFreq)
#define DecodeSBREnvelope STATNAME(DecodeSBREnvelope)
#define DecodeSBRNoise STATNAME(DecodeSBRNoise)
#define UncoupleSBREnvelope STATNAME(UncoupleSBREnvelope)
#define UncoupleSBRNoise STATNAME(UncoupleSBRNoise)
#define InvRNormalized STATNAME(InvRNormalized)
#define RatioPowInv STATNAME(RatioPowInv)
#define SqrtFix STATNAME(SqrtFix)
#define QMFAnalysis STATNAME(QMFAnalysis)
#define QMFSynthesis STATNAME(QMFSynthesis)
#define GetSampRateIdx STATNAME(GetSampRateIdx)
#define UnpackSBRHeader STATNAME(UnpackSBRHeader)
#define UnpackSBRSingleChannel STATNAME(UnpackSBRSingleChannel)
#define UnpackSBRChannelPair STATNAME(UnpackSBRChannelPair)
/* asm functions */
#define CVKernel1 STATNAME(CVKernel1)
#define CVKernel2 STATNAME(CVKernel2)
#define QMFAnalysisConv STATNAME(QMFAnalysisConv)
#define QMFSynthesisConv STATNAME(QMFSynthesisConv)
#define k0Tab STATNAME(k0Tab)
#define k2Tab STATNAME(k2Tab)
#define goalSBTab STATNAME(goalSBTab)
#define huffTabSBR STATNAME(huffTabSBR)
#define huffTabSBRInfo STATNAME(huffTabSBRInfo)
#define log2Tab STATNAME(log2Tab)
#define noiseTab STATNAME(noiseTab)
#define cTabA STATNAME(cTabA)
#define cTabS STATNAME(cTabS)
/* do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit) */
#define CLIP_2N_SHIFT30(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
/*
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != ((y) >> (n))) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
*/
enum {
SBR_GRID_FIXFIX = 0,
SBR_GRID_FIXVAR = 1,
SBR_GRID_VARFIX = 2,
SBR_GRID_VARVAR = 3
};
enum {
HuffTabSBR_tEnv15 = 0,
HuffTabSBR_fEnv15 = 1,
HuffTabSBR_tEnv15b = 2,
HuffTabSBR_fEnv15b = 3,
HuffTabSBR_tEnv30 = 4,
HuffTabSBR_fEnv30 = 5,
HuffTabSBR_tEnv30b = 6,
HuffTabSBR_fEnv30b = 7,
HuffTabSBR_tNoise30 = 8,
HuffTabSBR_fNoise30 = 5,
HuffTabSBR_tNoise30b = 9,
HuffTabSBR_fNoise30b = 7
};
typedef struct _HuffInfo {
int maxBits; /* number of bits in longest codeword */
unsigned /*char*/ int count[MAX_HUFF_BITS]; /* count[i] = number of codes with length i+1 bits */
int offset; /* offset into symbol table */
} HuffInfo;
/* need one SBRHeader per element (SCE/CPE), updated only on new header */
typedef struct _SBRHeader {
int count;
unsigned char ampRes;
unsigned char startFreq;
unsigned char stopFreq;
unsigned char crossOverBand;
unsigned char resBitsHdr;
unsigned char hdrExtra1;
unsigned char hdrExtra2;
unsigned char freqScale;
unsigned char alterScale;
unsigned char noiseBands;
unsigned char limiterBands;
unsigned char limiterGains;
unsigned char interpFreq;
unsigned char smoothMode;
} SBRHeader;
/* need one SBRGrid per channel, updated every frame */
typedef struct _SBRGrid {
unsigned char frameClass;
unsigned char ampResFrame;
unsigned char pointer;
unsigned char numEnv; /* L_E */
unsigned char envTimeBorder[MAX_NUM_ENV+1]; /* t_E */
unsigned char freqRes[MAX_NUM_ENV]; /* r */
unsigned char numNoiseFloors; /* L_Q */
unsigned char noiseTimeBorder[MAX_NUM_NOISE_FLOORS+1]; /* t_Q */
unsigned char numEnvPrev;
unsigned char numNoiseFloorsPrev;
unsigned char freqResPrev;
} SBRGrid;
/* need one SBRFreq per element (SCE/CPE/LFE), updated only on header reset */
typedef struct _SBRFreq {
int kStart; /* k_x */
int nMaster;
int nHigh;
int nLow;
int nLimiter; /* N_l */
int numQMFBands; /* M */
int numNoiseFloorBands; /* Nq */
int kStartPrev;
int numQMFBandsPrev;
unsigned char freqMaster[MAX_QMF_BANDS + 1]; /* not necessary to save this after derived tables are generated */
unsigned char freqHigh[MAX_QMF_BANDS + 1];
unsigned char freqLow[MAX_QMF_BANDS / 2 + 1]; /* nLow = nHigh - (nHigh >> 1) */
unsigned char freqNoise[MAX_NUM_NOISE_FLOOR_BANDS+1];
unsigned char freqLimiter[MAX_QMF_BANDS / 2 + MAX_NUM_PATCHES]; /* max (intermediate) size = nLow + numPatches - 1 */
unsigned char numPatches;
unsigned char patchNumSubbands[MAX_NUM_PATCHES + 1];
unsigned char patchStartSubband[MAX_NUM_PATCHES + 1];
} SBRFreq;
typedef struct _SBRChan {
int reset;
unsigned char deltaFlagEnv[MAX_NUM_ENV];
unsigned char deltaFlagNoise[MAX_NUM_NOISE_FLOORS];
signed char envDataQuant[MAX_NUM_ENV][MAX_QMF_BANDS]; /* range = [0, 127] */
signed char noiseDataQuant[MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS];
unsigned char invfMode[2][MAX_NUM_NOISE_FLOOR_BANDS]; /* invfMode[0/1][band] = prev/curr */
int chirpFact[MAX_NUM_NOISE_FLOOR_BANDS]; /* bwArray */
unsigned char addHarmonicFlag[2]; /* addHarmonicFlag[0/1] = prev/curr */
unsigned char addHarmonic[2][64]; /* addHarmonic[0/1][band] = prev/curr */
int gbMask[2]; /* gbMask[0/1] = XBuf[0-31]/XBuf[32-39] */
signed char laPrev;
int noiseTabIndex;
int sinIndex;
int gainNoiseIndex;
int gTemp[MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS];
int qTemp[MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS];
} SBRChan;
typedef struct _PSInfoSBR {
/* save for entire file */
int frameCount;
int sampRateIdx;
/* state info that must be saved for each channel */
SBRHeader sbrHdr[AAC_MAX_NCHANS];
SBRGrid sbrGrid[AAC_MAX_NCHANS];
SBRFreq sbrFreq[AAC_MAX_NCHANS];
SBRChan sbrChan[AAC_MAX_NCHANS];
/* temp variables, no need to save between blocks */
unsigned char dataExtra;
unsigned char resBitsData;
unsigned char extendedDataPresent;
int extendedDataSize;
signed char envDataDequantScale[MAX_NCHANS_ELEM][MAX_NUM_ENV];
int envDataDequant[MAX_NCHANS_ELEM][MAX_NUM_ENV][MAX_QMF_BANDS];
int noiseDataDequant[MAX_NCHANS_ELEM][MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS];
int eCurr[MAX_QMF_BANDS];
unsigned char eCurrExp[MAX_QMF_BANDS];
unsigned char eCurrExpMax;
signed char la;
int crcCheckWord;
int couplingFlag;
int envBand;
int eOMGainMax;
int gainMax;
int gainMaxFBits;
int noiseFloorBand;
int qp1Inv;
int qqp1Inv;
int sMapped;
int sBand;
int highBand;
int sumEOrigMapped;
int sumECurrGLim;
int sumSM;
int sumQM;
int gLimBoost[MAX_QMF_BANDS];
int qmLimBoost[MAX_QMF_BANDS];
int smBoost[MAX_QMF_BANDS];
int smBuf[MAX_QMF_BANDS];
int qmLimBuf[MAX_QMF_BANDS];
int gLimBuf[MAX_QMF_BANDS];
int gLimFbits[MAX_QMF_BANDS];
int gFiltLast[MAX_QMF_BANDS];
int qFiltLast[MAX_QMF_BANDS];
/* large buffers */
int delayIdxQMFA[AAC_MAX_NCHANS];
int delayQMFA[AAC_MAX_NCHANS][DELAY_SAMPS_QMFA];
int delayIdxQMFS[AAC_MAX_NCHANS];
int delayQMFS[AAC_MAX_NCHANS][DELAY_SAMPS_QMFS];
int XBufDelay[AAC_MAX_NCHANS][HF_GEN][64][2];
int XBuf[32+8][64][2];
} PSInfoSBR;
/* sbrfft.c */
void FFT32C(int *x);
/* sbrfreq.c */
int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx);
/* sbrhfadj.c */
void AdjustHighFreq(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
/* sbrhfgen.c */
void GenerateHighFreq(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
/* sbrhuff.c */
void DecodeSBREnvelope(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
void DecodeSBRNoise(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
void UncoupleSBREnvelope(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
void UncoupleSBRNoise(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
/* sbrmath.c */
int InvRNormalized(int r);
int RatioPowInv(int a, int b, int c);
int SqrtFix(int x, int fBitsIn, int *fBitsOut);
/* sbrqmf.c */
int QMFAnalysis(int *inbuf, int *delay, int *XBuf, int fBitsIn, int *delayIdx, int qmfaBands);
void QMFSynthesis(int *inbuf, int *delay, int *delayIdx, int qmfsBands, short *outbuf, int nChans);
/* sbrside.c */
int GetSampRateIdx(int sampRate);
int UnpackSBRHeader(BitStreamInfo *bsi, SBRHeader *sbrHdr);
void UnpackSBRSingleChannel(BitStreamInfo *bsi, PSInfoSBR *psi, int chOut);
void UnpackSBRChannelPair(BitStreamInfo *bsi, PSInfoSBR *psi, int chOut);
/* sbrtabs.c */
extern const unsigned char k0Tab[NUM_SAMPLE_RATES_SBR][16];
extern const unsigned char k2Tab[NUM_SAMPLE_RATES_SBR][14];
extern const unsigned char goalSBTab[NUM_SAMPLE_RATES_SBR];
extern const HuffInfo huffTabSBRInfo[10];
extern const signed int /*short*/ huffTabSBR[604];
extern const int log2Tab[65];
extern const int noiseTab[512*2];
extern const int cTabA[165];
extern const int cTabS[640];
#endif /* _SBR_H */

View File

@@ -1,368 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrfft.c,v 1.1 2005/02/26 01:47:35 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* sbrfft.c - optimized FFT for SBR QMF filters
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
#define SQRT1_2 0x5a82799a
/* swap RE{p0} with RE{p1} and IM{P0} with IM{P1} */
#define swapcplx(p0,p1) \
t = p0; t1 = *(&(p0)+1); p0 = p1; *(&(p0)+1) = *(&(p1)+1); p1 = t; *(&(p1)+1) = t1
/* nfft = 32, hard coded since small, fixed size FFT
static const unsigned char bitrevtab32[9] = {
0x01, 0x04, 0x03, 0x06, 0x00, 0x02, 0x05, 0x07, 0x00,
};
*/
/* twiddle table for radix 4 pass, format = Q31 */
static const int twidTabOdd32[8*6] = {
0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x539eba45, 0xe7821d59,
0x4b418bbe, 0xf383a3e2, 0x58c542c5, 0xdc71898d, 0x5a82799a, 0xd2bec333, 0x539eba45, 0xe7821d59,
0x539eba45, 0xc4df2862, 0x539eba45, 0xc4df2862, 0x58c542c5, 0xdc71898d, 0x3248d382, 0xc13ad060,
0x40000000, 0xc0000000, 0x5a82799a, 0xd2bec333, 0x00000000, 0xd2bec333, 0x22a2f4f8, 0xc4df2862,
0x58c542c5, 0xcac933ae, 0xcdb72c7e, 0xf383a3e2, 0x00000000, 0xd2bec333, 0x539eba45, 0xc4df2862,
0xac6145bb, 0x187de2a7, 0xdd5d0b08, 0xe7821d59, 0x4b418bbe, 0xc13ad060, 0xa73abd3b, 0x3536cc52,
};
/**************************************************************************************
* Function: BitReverse32
*
* Description: Ken's fast in-place bit reverse
*
* Inputs: buffer of 32 complex samples
*
* Outputs: bit-reversed samples in same buffer
*
* Return: none
**************************************************************************************/
static void BitReverse32(int *inout)
{
int t, t1;
swapcplx(inout[2], inout[32]);
swapcplx(inout[4], inout[16]);
swapcplx(inout[6], inout[48]);
swapcplx(inout[10], inout[40]);
swapcplx(inout[12], inout[24]);
swapcplx(inout[14], inout[56]);
swapcplx(inout[18], inout[36]);
swapcplx(inout[22], inout[52]);
swapcplx(inout[26], inout[44]);
swapcplx(inout[30], inout[60]);
swapcplx(inout[38], inout[50]);
swapcplx(inout[46], inout[58]);
}
/**************************************************************************************
* Function: R8FirstPass32
*
* Description: radix-8 trivial pass for decimation-in-time FFT (log2(N) = 5)
*
* Inputs: buffer of (bit-reversed) samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 3 guard bits, gains 1 integer bit
* guard bits out = guard bits in - 3 (if inputs are full scale)
* or guard bits in - 2 (if inputs bounded to +/- sqrt(2)/2)
* see scaling comments in fft.c for base AAC
* should compile with no stack spills on ARM (verify compiled output)
* current instruction count (per pass): 16 LDR, 16 STR, 4 SMULL, 61 ALU
**************************************************************************************/
static void R8FirstPass32(int *r0)
{
int r1, r2, r3, r4, r5, r6, r7;
int r8, r9, r10, r11, r12, r14;
/* number of passes = fft size / 8 = 32 / 8 = 4 */
r1 = (32 >> 3);
do {
r2 = r0[8];
r3 = r0[9];
r4 = r0[10];
r5 = r0[11];
r6 = r0[12];
r7 = r0[13];
r8 = r0[14];
r9 = r0[15];
r10 = r2 + r4;
r11 = r3 + r5;
r12 = r6 + r8;
r14 = r7 + r9;
r2 -= r4;
r3 -= r5;
r6 -= r8;
r7 -= r9;
r4 = r2 - r7;
r5 = r2 + r7;
r8 = r3 - r6;
r9 = r3 + r6;
r2 = r4 - r9;
r3 = r4 + r9;
r6 = r5 - r8;
r7 = r5 + r8;
r2 = MULSHIFT32(SQRT1_2, r2); /* can use r4, r5, r8, or r9 for constant and lo32 scratch reg */
r3 = MULSHIFT32(SQRT1_2, r3);
r6 = MULSHIFT32(SQRT1_2, r6);
r7 = MULSHIFT32(SQRT1_2, r7);
r4 = r10 + r12;
r5 = r10 - r12;
r8 = r11 + r14;
r9 = r11 - r14;
r10 = r0[0];
r11 = r0[2];
r12 = r0[4];
r14 = r0[6];
r10 += r11;
r12 += r14;
r4 >>= 1;
r10 += r12;
r4 += (r10 >> 1);
r0[ 0] = r4;
r4 -= (r10 >> 1);
r4 = (r10 >> 1) - r4;
r0[ 8] = r4;
r9 >>= 1;
r10 -= 2*r12;
r4 = (r10 >> 1) + r9;
r0[ 4] = r4;
r4 = (r10 >> 1) - r9;
r0[12] = r4;
r10 += r12;
r10 -= 2*r11;
r12 -= 2*r14;
r4 = r0[1];
r9 = r0[3];
r11 = r0[5];
r14 = r0[7];
r4 += r9;
r11 += r14;
r8 >>= 1;
r4 += r11;
r8 += (r4 >> 1);
r0[ 1] = r8;
r8 -= (r4 >> 1);
r8 = (r4 >> 1) - r8;
r0[ 9] = r8;
r5 >>= 1;
r4 -= 2*r11;
r8 = (r4 >> 1) - r5;
r0[ 5] = r8;
r8 = (r4 >> 1) + r5;
r0[13] = r8;
r4 += r11;
r4 -= 2*r9;
r11 -= 2*r14;
r9 = r10 - r11;
r10 += r11;
r14 = r4 + r12;
r4 -= r12;
r5 = (r10 >> 1) + r7;
r8 = (r4 >> 1) - r6;
r0[ 2] = r5;
r0[ 3] = r8;
r5 = (r9 >> 1) - r2;
r8 = (r14 >> 1) - r3;
r0[ 6] = r5;
r0[ 7] = r8;
r5 = (r10 >> 1) - r7;
r8 = (r4 >> 1) + r6;
r0[10] = r5;
r0[11] = r8;
r5 = (r9 >> 1) + r2;
r8 = (r14 >> 1) + r3;
r0[14] = r5;
r0[15] = r8;
r0 += 16;
r1--;
} while (r1 != 0);
}
/**************************************************************************************
* Function: R4Core32
*
* Description: radix-4 pass for 32-point decimation-in-time FFT
*
* Inputs: buffer of samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: gain 2 integer bits
* guard bits out = guard bits in - 1 (if inputs are full scale)
* see scaling comments in fft.c for base AAC
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
* should compile with no stack spills on ARM (verify compiled output)
* current instruction count (per pass): 16 LDR, 16 STR, 4 SMULL, 61 ALU
**************************************************************************************/
static void R4Core32(int *r0)
{
int r2, r3, r4, r5, r6, r7;
int r8, r9, r10, r12, r14;
int *r1;
r1 = (int *)twidTabOdd32;
r10 = 8;
do {
/* can use r14 for lo32 scratch register in all MULSHIFT32 */
r2 = r1[0];
r3 = r1[1];
r4 = r0[16];
r5 = r0[17];
r12 = r4 + r5;
r12 = MULSHIFT32(r3, r12);
r5 = MULSHIFT32(r2, r5) + r12;
r2 += 2*r3;
r4 = MULSHIFT32(r2, r4) - r12;
r2 = r1[2];
r3 = r1[3];
r6 = r0[32];
r7 = r0[33];
r12 = r6 + r7;
r12 = MULSHIFT32(r3, r12);
r7 = MULSHIFT32(r2, r7) + r12;
r2 += 2*r3;
r6 = MULSHIFT32(r2, r6) - r12;
r2 = r1[4];
r3 = r1[5];
r8 = r0[48];
r9 = r0[49];
r12 = r8 + r9;
r12 = MULSHIFT32(r3, r12);
r9 = MULSHIFT32(r2, r9) + r12;
r2 += 2*r3;
r8 = MULSHIFT32(r2, r8) - r12;
r2 = r0[0];
r3 = r0[1];
r12 = r6 + r8;
r8 = r6 - r8;
r14 = r9 - r7;
r9 = r9 + r7;
r6 = (r2 >> 2) - r4;
r7 = (r3 >> 2) - r5;
r4 += (r2 >> 2);
r5 += (r3 >> 2);
r2 = r4 + r12;
r3 = r5 + r9;
r0[0] = r2;
r0[1] = r3;
r2 = r6 - r14;
r3 = r7 - r8;
r0[16] = r2;
r0[17] = r3;
r2 = r4 - r12;
r3 = r5 - r9;
r0[32] = r2;
r0[33] = r3;
r2 = r6 + r14;
r3 = r7 + r8;
r0[48] = r2;
r0[49] = r3;
r0 += 2;
r1 += 6;
r10--;
} while (r10 != 0);
}
/**************************************************************************************
* Function: FFT32C
*
* Description: Ken's very fast in-place radix-4 decimation-in-time FFT
*
* Inputs: buffer of 32 complex samples (before bit-reversal)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 3 guard bits in, gains 3 integer bits
* guard bits out = guard bits in - 2
* (guard bit analysis includes assumptions about steps immediately
* before and after, i.e. PreMul and PostMul for DCT)
**************************************************************************************/
void FFT32C(int *x)
{
/* decimation in time */
BitReverse32(x);
/* 32-point complex FFT */
R8FirstPass32(x); /* gain 1 int bit, lose 2 GB (making assumptions about input) */
R4Core32(x); /* gain 2 int bits, lose 0 GB (making assumptions about input) */
}

View File

@@ -1,641 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrfreq.c,v 1.2 2005/05/20 18:05:41 jrecker 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
*
* sbrfreq.c - frequency band table calculation for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/**************************************************************************************
* Function: BubbleSort
*
* Description: in-place sort of unsigned chars
*
* Inputs: buffer of elements to sort
* number of elements to sort
*
* Outputs: sorted buffer
*
* Return: none
**************************************************************************************/
static void BubbleSort(unsigned char *v, int nItems)
{
int i;
unsigned char t;
while (nItems >= 2) {
for (i = 0; i < nItems-1; i++) {
if (v[i+1] < v[i]) {
t = v[i+1];
v[i+1] = v[i];
v[i] = t;
}
}
nItems--;
}
}
/**************************************************************************************
* Function: VMin
*
* Description: find smallest element in a buffer of unsigned chars
*
* Inputs: buffer of elements to search
* number of elements to search
*
* Outputs: none
*
* Return: smallest element in buffer
**************************************************************************************/
static unsigned char VMin(unsigned char *v, int nItems)
{
int i;
unsigned char vMin;
vMin = v[0];
for (i = 1; i < nItems; i++) {
if (v[i] < vMin)
vMin = v[i];
}
return vMin;
}
/**************************************************************************************
* Function: VMax
*
* Description: find largest element in a buffer of unsigned chars
*
* Inputs: buffer of elements to search
* number of elements to search
*
* Outputs: none
*
* Return: largest element in buffer
**************************************************************************************/
static unsigned char VMax(unsigned char *v, int nItems)
{
int i;
unsigned char vMax;
vMax = v[0];
for (i = 1; i < nItems; i++) {
if (v[i] > vMax)
vMax = v[i];
}
return vMax;
}
/**************************************************************************************
* Function: CalcFreqMasterScaleZero
*
* Description: calculate master frequency table when freqScale == 0
* (4.6.18.3.2.1, figure 4.39)
*
* Inputs: alterScale flag
* index of first QMF subband in master freq table (k0)
* index of last QMF subband (k2)
*
* Outputs: master frequency table
*
* Return: number of bands in master frequency table
*
* Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
**************************************************************************************/
static int CalcFreqMasterScaleZero(unsigned char *freqMaster, int alterScale, int k0, int k2)
{
int nMaster, k, nBands, k2Achieved, dk, vDk[64], k2Diff;
if (alterScale) {
dk = 2;
nBands = 2 * ((k2 - k0 + 2) >> 2);
} else {
dk = 1;
nBands = 2 * ((k2 - k0) >> 1);
}
if (nBands <= 0)
return 0;
k2Achieved = k0 + nBands * dk;
k2Diff = k2 - k2Achieved;
for (k = 0; k < nBands; k++)
vDk[k] = dk;
if (k2Diff > 0) {
k = nBands - 1;
while (k2Diff) {
vDk[k]++;
k--;
k2Diff--;
}
} else if (k2Diff < 0) {
k = 0;
while (k2Diff) {
vDk[k]--;
k++;
k2Diff++;
}
}
nMaster = nBands;
freqMaster[0] = k0;
for (k = 1; k <= nBands; k++)
freqMaster[k] = freqMaster[k-1] + vDk[k-1];
return nMaster;
}
/* mBandTab[i] = temp1[i] / 2 */
static const int mBandTab[3] PROGMEM = {6, 5, 4};
/* invWarpTab[i] = 1.0 / temp2[i], Q30 (see 4.6.18.3.2.1) */
static const int invWarpTab[2] PROGMEM = {0x40000000, 0x313b13b1};
/**************************************************************************************
* Function: CalcFreqMasterScale
*
* Description: calculate master frequency table when freqScale > 0
* (4.6.18.3.2.1, figure 4.39)
*
* Inputs: alterScale flag
* freqScale flag
* index of first QMF subband in master freq table (k0)
* index of last QMF subband (k2)
*
* Outputs: master frequency table
*
* Return: number of bands in master frequency table
*
* Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
**************************************************************************************/
static int CalcFreqMaster(unsigned char *freqMaster, int freqScale, int alterScale, int k0, int k2)
{
int bands, twoRegions, k, k1, t, vLast, vCurr, pCurr;
int invWarp, nBands0, nBands1, change;
unsigned char vDk1Min, vDk0Max;
unsigned char *vDelta;
if (freqScale < 1 || freqScale > 3)
return -1;
bands = mBandTab[freqScale - 1];
invWarp = invWarpTab[alterScale];
/* tested for all k0 = [5, 64], k2 = [k0, 64] */
if (k2*10000 > 22449*k0) {
twoRegions = 1;
k1 = 2*k0;
} else {
twoRegions = 0;
k1 = k2;
}
/* tested for all k0 = [5, 64], k1 = [k0, 64], freqScale = [1,3] */
t = (log2Tab[k1] - log2Tab[k0]) >> 3; /* log2(k1/k0), Q28 to Q25 */
nBands0 = 2 * (((bands * t) + (1 << 24)) >> 25); /* multiply by bands/2, round to nearest int (mBandTab has factor of 1/2 rolled in) */
/* tested for all valid combinations of k0, k1, nBands (from sampRate, freqScale, alterScale)
* roundoff error can be a problem with fixpt (e.g. pCurr = 12.499999 instead of 12.50003)
* because successive multiplication always undershoots a little bit, but this
* doesn't occur in any of the ratios we encounter from the valid k0/k1 bands in the spec
*/
t = RatioPowInv(k1, k0, nBands0);
pCurr = k0 << 24;
vLast = k0;
vDelta = freqMaster + 1; /* operate in-place */
for (k = 0; k < nBands0; k++) {
pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
vCurr = (pCurr + (1 << 23)) >> 24;
vDelta[k] = (vCurr - vLast);
vLast = vCurr;
}
/* sort the deltas and find max delta for first region */
BubbleSort(vDelta, nBands0);
vDk0Max = VMax(vDelta, nBands0);
/* fill master frequency table with bands from first region */
freqMaster[0] = k0;
for (k = 1; k <= nBands0; k++)
freqMaster[k] += freqMaster[k-1];
/* if only one region, then the table is complete */
if (!twoRegions)
return nBands0;
/* tested for all k1 = [10, 64], k2 = [k0, 64], freqScale = [1,3] */
t = (log2Tab[k2] - log2Tab[k1]) >> 3; /* log2(k1/k0), Q28 to Q25 */
t = MULSHIFT32(bands * t, invWarp) << 2; /* multiply by bands/2, divide by warp factor, keep Q25 */
nBands1 = 2 * ((t + (1 << 24)) >> 25); /* round to nearest int */
/* see comments above for calculations in first region */
t = RatioPowInv(k2, k1, nBands1);
pCurr = k1 << 24;
vLast = k1;
vDelta = freqMaster + nBands0 + 1; /* operate in-place */
for (k = 0; k < nBands1; k++) {
pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
vCurr = (pCurr + (1 << 23)) >> 24;
vDelta[k] = (vCurr - vLast);
vLast = vCurr;
}
/* sort the deltas, adjusting first and last if the second region has smaller deltas than the first */
vDk1Min = VMin(vDelta, nBands1);
if (vDk1Min < vDk0Max) {
BubbleSort(vDelta, nBands1);
change = vDk0Max - vDelta[0];
if (change > ((vDelta[nBands1 - 1] - vDelta[0]) >> 1))
change = ((vDelta[nBands1 - 1] - vDelta[0]) >> 1);
vDelta[0] += change;
vDelta[nBands1-1] -= change;
}
BubbleSort(vDelta, nBands1);
/* fill master frequency table with bands from second region
* Note: freqMaster[nBands0] = k1
*/
for (k = 1; k <= nBands1; k++)
freqMaster[k + nBands0] += freqMaster[k + nBands0 - 1];
return (nBands0 + nBands1);
}
/**************************************************************************************
* Function: CalcFreqHigh
*
* Description: calculate high resolution frequency table (4.6.18.3.2.2)
*
* Inputs: master frequency table
* number of bands in master frequency table
* crossover band from header
*
* Outputs: high resolution frequency table
*
* Return: number of bands in high resolution frequency table
**************************************************************************************/
static int CalcFreqHigh(unsigned char *freqHigh, unsigned char *freqMaster, int nMaster, int crossOverBand)
{
int k, nHigh;
nHigh = nMaster - crossOverBand;
for (k = 0; k <= nHigh; k++)
freqHigh[k] = freqMaster[k + crossOverBand];
return nHigh;
}
/**************************************************************************************
* Function: CalcFreqLow
*
* Description: calculate low resolution frequency table (4.6.18.3.2.2)
*
* Inputs: high resolution frequency table
* number of bands in high resolution frequency table
*
* Outputs: low resolution frequency table
*
* Return: number of bands in low resolution frequency table
**************************************************************************************/
static int CalcFreqLow(unsigned char *freqLow, unsigned char *freqHigh, int nHigh)
{
int k, nLow, oddFlag;
nLow = nHigh - (nHigh >> 1);
freqLow[0] = freqHigh[0];
oddFlag = nHigh & 0x01;
for (k = 1; k <= nLow; k++)
freqLow[k] = freqHigh[2*k - oddFlag];
return nLow;
}
/**************************************************************************************
* Function: CalcFreqNoise
*
* Description: calculate noise floor frequency table (4.6.18.3.2.2)
*
* Inputs: low resolution frequency table
* number of bands in low resolution frequency table
* index of starting QMF subband for SBR (kStart)
* index of last QMF subband (k2)
* number of noise bands
*
* Outputs: noise floor frequency table
*
* Return: number of bands in noise floor frequency table
**************************************************************************************/
static int CalcFreqNoise(unsigned char *freqNoise, unsigned char *freqLow, int nLow, int kStart, int k2, int noiseBands)
{
int i, iLast, k, nQ, lTop, lBottom;
lTop = log2Tab[k2];
lBottom = log2Tab[kStart];
nQ = noiseBands*((lTop - lBottom) >> 2); /* Q28 to Q26, noiseBands = [0,3] */
nQ = (nQ + (1 << 25)) >> 26;
if (nQ < 1)
nQ = 1;
ASSERT(nQ <= MAX_NUM_NOISE_FLOOR_BANDS); /* required from 4.6.18.3.6 */
iLast = 0;
freqNoise[0] = freqLow[0];
for (k = 1; k <= nQ; k++) {
i = iLast + (nLow - iLast) / (nQ + 1 - k); /* truncating division */
freqNoise[k] = freqLow[i];
iLast = i;
}
return nQ;
}
/**************************************************************************************
* Function: BuildPatches
*
* Description: build high frequency patches (4.6.18.6.3)
*
* Inputs: master frequency table
* number of bands in low resolution frequency table
* index of first QMF subband in master freq table (k0)
* index of starting QMF subband for SBR (kStart)
* number of QMF bands in high resolution frequency table
* sample rate index
*
* Outputs: starting subband for each patch
* number of subbands in each patch
*
* Return: number of patches
**************************************************************************************/
static int BuildPatches(unsigned char *patchNumSubbands, unsigned char *patchStartSubband, unsigned char *freqMaster,
int nMaster, int k0, int kStart, int numQMFBands, int sampRateIdx)
{
int i, j, k;
int msb, sb, usb, numPatches, goalSB, oddFlag;
msb = k0;
usb = kStart;
numPatches = 0;
goalSB = goalSBTab[sampRateIdx];
if (nMaster == 0) {
patchNumSubbands[0] = 0;
patchStartSubband[0] = 0;
return 0;
}
if (goalSB < kStart + numQMFBands) {
k = 0;
for (i = 0; freqMaster[i] < goalSB; i++)
k = i+1;
} else {
k = nMaster;
}
do {
j = k+1;
do {
j--;
sb = freqMaster[j];
oddFlag = (sb - 2 + k0) & 0x01;
} while (sb > k0 - 1 + msb - oddFlag);
patchNumSubbands[numPatches] = MAX(sb - usb, 0);
patchStartSubband[numPatches] = k0 - oddFlag - patchNumSubbands[numPatches];
/* from MPEG reference code - slightly different from spec */
if ((patchNumSubbands[numPatches] < 3) && (numPatches > 0))
break;
if (patchNumSubbands[numPatches] > 0) {
usb = sb;
msb = sb;
numPatches++;
} else {
msb = kStart;
}
if (freqMaster[k] - sb < 3)
k = nMaster;
} while (sb != (kStart + numQMFBands) && numPatches <= MAX_NUM_PATCHES);
return numPatches;
}
/**************************************************************************************
* Function: FindFreq
*
* Description: search buffer of unsigned chars for a specific value
*
* Inputs: buffer of elements to search
* number of elements to search
* value to search for
*
* Outputs: none
*
* Return: non-zero if the value is found anywhere in the buffer, zero otherwise
**************************************************************************************/
static int FindFreq(unsigned char *freq, int nFreq, unsigned char val)
{
int k;
for (k = 0; k < nFreq; k++) {
if (freq[k] == val)
return 1;
}
return 0;
}
/**************************************************************************************
* Function: RemoveFreq
*
* Description: remove one element from a buffer of unsigned chars
*
* Inputs: buffer of elements
* number of elements
* index of element to remove
*
* Outputs: new buffer of length nFreq-1
*
* Return: none
**************************************************************************************/
static void RemoveFreq(unsigned char *freq, int nFreq, int removeIdx)
{
int k;
if (removeIdx >= nFreq)
return;
for (k = removeIdx; k < nFreq - 1; k++)
freq[k] = freq[k+1];
}
/**************************************************************************************
* Function: CalcFreqLimiter
*
* Description: calculate limiter frequency table (4.6.18.3.2.3)
*
* Inputs: number of subbands in each patch
* low resolution frequency table
* number of bands in low resolution frequency table
* index of starting QMF subband for SBR (kStart)
* number of limiter bands
* number of patches
*
* Outputs: limiter frequency table
*
* Return: number of bands in limiter frequency table
**************************************************************************************/
static int CalcFreqLimiter(unsigned char *freqLimiter, unsigned char *patchNumSubbands, unsigned char *freqLow,
int nLow, int kStart, int limiterBands, int numPatches)
{
int k, bands, nLimiter, nOctaves;
int limBandsPerOctave[3] = {120, 200, 300}; /* [1.2, 2.0, 3.0] * 100 */
unsigned char patchBorders[MAX_NUM_PATCHES + 1];
/* simple case */
if (limiterBands == 0) {
freqLimiter[0] = freqLow[0] - kStart;
freqLimiter[1] = freqLow[nLow] - kStart;
return 1;
}
bands = limBandsPerOctave[limiterBands - 1];
patchBorders[0] = kStart;
/* from MPEG reference code - slightly different from spec (top border) */
for (k = 1; k < numPatches; k++)
patchBorders[k] = patchBorders[k-1] + patchNumSubbands[k-1];
patchBorders[k] = freqLow[nLow];
for (k = 0; k <= nLow; k++)
freqLimiter[k] = freqLow[k];
for (k = 1; k < numPatches; k++)
freqLimiter[k+nLow] = patchBorders[k];
k = 1;
nLimiter = nLow + numPatches - 1;
BubbleSort(freqLimiter, nLimiter + 1);
while (k <= nLimiter) {
nOctaves = log2Tab[freqLimiter[k]] - log2Tab[freqLimiter[k-1]]; /* Q28 */
nOctaves = (nOctaves >> 9) * bands; /* Q19, max bands = 300 < 2^9 */
if (nOctaves < (49 << 19)) { /* compare with 0.49*100, in Q19 */
if (freqLimiter[k] == freqLimiter[k-1] || FindFreq(patchBorders, numPatches + 1, freqLimiter[k]) == 0) {
RemoveFreq(freqLimiter, nLimiter + 1, k);
nLimiter--;
} else if (FindFreq(patchBorders, numPatches + 1, freqLimiter[k-1]) == 0) {
RemoveFreq(freqLimiter, nLimiter + 1, k-1);
nLimiter--;
} else {
k++;
}
} else {
k++;
}
}
/* store limiter boundaries as offsets from kStart */
for (k = 0; k <= nLimiter; k++)
freqLimiter[k] -= kStart;
return nLimiter;
}
/**************************************************************************************
* Function: CalcFreqTables
*
* Description: calulate master and derived frequency tables, and patches
*
* Inputs: initialized SBRHeader struct for this SCE/CPE block
* initialized SBRFreq struct for this SCE/CPE block
* sample rate index of output sample rate (after SBR)
*
* Outputs: master and derived frequency tables, and patches
*
* Return: non-zero if error, zero otherwise
**************************************************************************************/
int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx)
{
int k0, k2;
k0 = k0Tab[sampRateIdx][sbrHdr->startFreq];
if (sbrHdr->stopFreq == 14)
k2 = 2*k0;
else if (sbrHdr->stopFreq == 15)
k2 = 3*k0;
else
k2 = k2Tab[sampRateIdx][sbrHdr->stopFreq];
if (k2 > 64)
k2 = 64;
/* calculate master frequency table */
if (sbrHdr->freqScale == 0)
sbrFreq->nMaster = CalcFreqMasterScaleZero(sbrFreq->freqMaster, sbrHdr->alterScale, k0, k2);
else
sbrFreq->nMaster = CalcFreqMaster(sbrFreq->freqMaster, sbrHdr->freqScale, sbrHdr->alterScale, k0, k2);
/* calculate high frequency table and related parameters */
sbrFreq->nHigh = CalcFreqHigh(sbrFreq->freqHigh, sbrFreq->freqMaster, sbrFreq->nMaster, sbrHdr->crossOverBand);
sbrFreq->numQMFBands = sbrFreq->freqHigh[sbrFreq->nHigh] - sbrFreq->freqHigh[0];
sbrFreq->kStart = sbrFreq->freqHigh[0];
/* calculate low frequency table */
sbrFreq->nLow = CalcFreqLow(sbrFreq->freqLow, sbrFreq->freqHigh, sbrFreq->nHigh);
/* calculate noise floor frequency table */
sbrFreq->numNoiseFloorBands = CalcFreqNoise(sbrFreq->freqNoise, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart, k2, sbrHdr->noiseBands);
/* calculate limiter table */
sbrFreq->numPatches = BuildPatches(sbrFreq->patchNumSubbands, sbrFreq->patchStartSubband, sbrFreq->freqMaster,
sbrFreq->nMaster, k0, sbrFreq->kStart, sbrFreq->numQMFBands, sampRateIdx);
sbrFreq->nLimiter = CalcFreqLimiter(sbrFreq->freqLimiter, sbrFreq->patchNumSubbands, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart,
sbrHdr->limiterBands, sbrFreq->numPatches);
return 0;
}

View File

@@ -1,853 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrhfadj.c,v 1.3 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
*
* sbrhfadj.c - high frequency adjustment for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/* invBandTab[i] = 1.0 / (i + 1), Q31 */
static const int invBandTab[64] PROGMEM = {
0x7fffffff, 0x40000000, 0x2aaaaaab, 0x20000000, 0x1999999a, 0x15555555, 0x12492492, 0x10000000,
0x0e38e38e, 0x0ccccccd, 0x0ba2e8ba, 0x0aaaaaab, 0x09d89d8a, 0x09249249, 0x08888889, 0x08000000,
0x07878788, 0x071c71c7, 0x06bca1af, 0x06666666, 0x06186186, 0x05d1745d, 0x0590b216, 0x05555555,
0x051eb852, 0x04ec4ec5, 0x04bda12f, 0x04924925, 0x0469ee58, 0x04444444, 0x04210842, 0x04000000,
0x03e0f83e, 0x03c3c3c4, 0x03a83a84, 0x038e38e4, 0x03759f23, 0x035e50d8, 0x03483483, 0x03333333,
0x031f3832, 0x030c30c3, 0x02fa0be8, 0x02e8ba2f, 0x02d82d83, 0x02c8590b, 0x02b93105, 0x02aaaaab,
0x029cbc15, 0x028f5c29, 0x02828283, 0x02762762, 0x026a439f, 0x025ed098, 0x0253c825, 0x02492492,
0x023ee090, 0x0234f72c, 0x022b63cc, 0x02222222, 0x02192e2a, 0x02108421, 0x02082082, 0x02000000,
};
/**************************************************************************************
* Function: EstimateEnvelope
*
* Description: estimate power of generated HF QMF bands in one time-domain envelope
* (4.6.18.7.3)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* index of current envelope
*
* Outputs: power of each QMF subband, stored as integer (Q0) * 2^N, N >= 0
*
* Return: none
**************************************************************************************/
static void EstimateEnvelope(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int env)
{
int i, m, iStart, iEnd, xre, xim, nScale, expMax;
int p, n, mStart, mEnd, invFact, t;
int *XBuf;
U64 eCurr;
unsigned char *freqBandTab;
/* estimate current envelope */
iStart = sbrGrid->envTimeBorder[env] + HF_ADJ;
iEnd = sbrGrid->envTimeBorder[env+1] + HF_ADJ;
if (sbrGrid->freqRes[env]) {
n = sbrFreq->nHigh;
freqBandTab = sbrFreq->freqHigh;
} else {
n = sbrFreq->nLow;
freqBandTab = sbrFreq->freqLow;
}
/* ADS should inline MADD64 (smlal) properly, but check to make sure */
expMax = 0;
if (sbrHdr->interpFreq) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
eCurr.w64 = 0;
XBuf = psi->XBuf[iStart][sbrFreq->kStart + m];
for (i = iStart; i < iEnd; i++) {
/* scale to int before calculating power (precision not critical, and avoids overflow) */
xre = (*XBuf) >> FBITS_OUT_QMFA; XBuf += 1;
xim = (*XBuf) >> FBITS_OUT_QMFA; XBuf += (2*64 - 1);
eCurr.w64 = MADD64(eCurr.w64, xre, xre);
eCurr.w64 = MADD64(eCurr.w64, xim, xim);
}
/* eCurr.w64 is now Q(64 - 2*FBITS_OUT_QMFA) (64-bit word)
* if energy is too big to fit in 32-bit word (> 2^31) scale down by power of 2
*/
nScale = 0;
if (eCurr.r.hi32) {
nScale = (32 - CLZ(eCurr.r.hi32)) + 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
t |= eCurr.r.hi32 << (32 - nScale);
} else if (eCurr.r.lo32 >> 31) {
nScale = 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
} else {
t = (int)eCurr.r.lo32;
}
invFact = invBandTab[(iEnd - iStart)-1];
psi->eCurr[m] = MULSHIFT32(t, invFact);
psi->eCurrExp[m] = nScale + 1; /* +1 for invFact = Q31 */
if (psi->eCurrExp[m] > expMax)
expMax = psi->eCurrExp[m];
}
} else {
for (p = 0; p < n; p++) {
mStart = freqBandTab[p];
mEnd = freqBandTab[p+1];
eCurr.w64 = 0;
for (i = iStart; i < iEnd; i++) {
XBuf = psi->XBuf[i][mStart];
for (m = mStart; m < mEnd; m++) {
xre = (*XBuf++) >> FBITS_OUT_QMFA;
xim = (*XBuf++) >> FBITS_OUT_QMFA;
eCurr.w64 = MADD64(eCurr.w64, xre, xre);
eCurr.w64 = MADD64(eCurr.w64, xim, xim);
}
}
nScale = 0;
if (eCurr.r.hi32) {
nScale = (32 - CLZ(eCurr.r.hi32)) + 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
t |= eCurr.r.hi32 << (32 - nScale);
} else if (eCurr.r.lo32 >> 31) {
nScale = 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
} else {
t = (int)eCurr.r.lo32;
}
invFact = invBandTab[(iEnd - iStart)-1];
invFact = MULSHIFT32(invBandTab[(mEnd - mStart)-1], invFact) << 1;
t = MULSHIFT32(t, invFact);
for (m = mStart; m < mEnd; m++) {
psi->eCurr[m - sbrFreq->kStart] = t;
psi->eCurrExp[m - sbrFreq->kStart] = nScale + 1; /* +1 for invFact = Q31 */
}
if (psi->eCurrExp[mStart - sbrFreq->kStart] > expMax)
expMax = psi->eCurrExp[mStart - sbrFreq->kStart];
}
}
psi->eCurrExpMax = expMax;
}
/**************************************************************************************
* Function: GetSMapped
*
* Description: calculate SMapped (4.6.18.7.2)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current envelope
* index of current QMF band
* la flag for this envelope
*
* Outputs: none
*
* Return: 1 if a sinusoid is present in this band, 0 if not
**************************************************************************************/
static int GetSMapped(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int band, int la)
{
int bandStart, bandEnd, oddFlag, r;
if (sbrGrid->freqRes[env]) {
/* high resolution */
bandStart = band;
bandEnd = band+1;
} else {
/* low resolution (see CalcFreqLow() for mapping) */
oddFlag = sbrFreq->nHigh & 0x01;
bandStart = (band > 0 ? 2*band - oddFlag : 0); /* starting index for freqLow[band] */
bandEnd = 2*(band+1) - oddFlag; /* ending index for freqLow[band+1] */
}
/* sMapped = 1 if sIndexMapped == 1 for any frequency in this band */
for (band = bandStart; band < bandEnd; band++) {
if (sbrChan->addHarmonic[1][band]) {
r = ((sbrFreq->freqHigh[band+1] + sbrFreq->freqHigh[band]) >> 1);
if (env >= la || sbrChan->addHarmonic[0][r] == 1)
return 1;
}
}
return 0;
}
#define GBOOST_MAX 0x2830afd3 /* Q28, 1.584893192 squared */
#define ACC_SCALE 6
/* squared version of table in 4.6.18.7.5 */
static const int limGainTab[4] PROGMEM = {0x20138ca7, 0x40000000, 0x7fb27dce, 0x80000000}; /* Q30 (0x80000000 = sentinel for GMAX) */
/**************************************************************************************
* Function: CalcMaxGain
*
* Description: calculate max gain in one limiter band (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
* index of current limiter band
* number of fraction bits in dequantized envelope
* (max = Q(FBITS_OUT_DQ_ENV - 6) = Q23, can go negative)
*
* Outputs: updated gainMax, gainMaxFBits, and sumEOrigMapped in PSInfoSBR struct
*
* Return: none
**************************************************************************************/
static void CalcMaxGain(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int ch, int env, int lim, int fbitsDQ)
{
int m, mStart, mEnd, q, z, r;
int sumEOrigMapped, sumECurr, gainMax, eOMGainMax, envBand;
unsigned char eCurrExpMax;
unsigned char *freqBandTab;
mStart = sbrFreq->freqLimiter[lim]; /* these are offsets from kStart */
mEnd = sbrFreq->freqLimiter[lim + 1];
freqBandTab = (sbrGrid->freqRes[env] ? sbrFreq->freqHigh : sbrFreq->freqLow);
/* calculate max gain to apply to signal in this limiter band */
sumECurr = 0;
sumEOrigMapped = 0;
eCurrExpMax = psi->eCurrExpMax;
eOMGainMax = psi->eOMGainMax;
envBand = psi->envBand;
for (m = mStart; m < mEnd; m++) {
/* map current QMF band to appropriate envelope band */
if (m == freqBandTab[envBand + 1] - sbrFreq->kStart) {
envBand++;
eOMGainMax = psi->envDataDequant[ch][env][envBand] >> ACC_SCALE; /* summing max 48 bands */
}
sumEOrigMapped += eOMGainMax;
/* easy test for overflow on ARM */
sumECurr += (psi->eCurr[m] >> (eCurrExpMax - psi->eCurrExp[m]));
if (sumECurr >> 30) {
sumECurr >>= 1;
eCurrExpMax++;
}
}
psi->eOMGainMax = eOMGainMax;
psi->envBand = envBand;
psi->gainMaxFBits = 30; /* Q30 tables */
if (sumECurr == 0) {
/* any non-zero numerator * 1/EPS_0 is > G_MAX */
gainMax = (sumEOrigMapped == 0 ? (int)limGainTab[sbrHdr->limiterGains] : (int)0x80000000);
} else if (sumEOrigMapped == 0) {
/* 1/(any non-zero denominator) * EPS_0 * limGainTab[x] is appx. 0 */
gainMax = 0;
} else {
/* sumEOrigMapped = Q(fbitsDQ - ACC_SCALE), sumECurr = Q(-eCurrExpMax) */
gainMax = limGainTab[sbrHdr->limiterGains];
if (sbrHdr->limiterGains != 3) {
q = MULSHIFT32(sumEOrigMapped, gainMax); /* Q(fbitsDQ - ACC_SCALE - 2), gainMax = Q30 */
z = CLZ(sumECurr) - 1;
r = InvRNormalized(sumECurr << z); /* in = Q(z - eCurrExpMax), out = Q(29 + 31 - z + eCurrExpMax) */
gainMax = MULSHIFT32(q, r); /* Q(29 + 31 - z + eCurrExpMax + fbitsDQ - ACC_SCALE - 2 - 32) */
psi->gainMaxFBits = 26 - z + eCurrExpMax + fbitsDQ - ACC_SCALE;
}
}
psi->sumEOrigMapped = sumEOrigMapped;
psi->gainMax = gainMax;
}
/**************************************************************************************
* Function: CalcNoiseDivFactors
*
* Description: calculate 1/(1+Q) and Q/(1+Q) (4.6.18.7.4; 4.6.18.7.5)
*
* Inputs: dequantized noise floor scalefactor
*
* Outputs: 1/(1+Q) and Q/(1+Q), format = Q31
*
* Return: none
**************************************************************************************/
static void CalcNoiseDivFactors(int q, int *qp1Inv, int *qqp1Inv)
{
int z, qp1, t, s;
/* 1 + Q_orig */
qp1 = (q >> 1);
qp1 += (1 << (FBITS_OUT_DQ_NOISE - 1)); /* >> 1 to avoid overflow when adding 1.0 */
z = CLZ(qp1) - 1; /* z <= 31 - FBITS_OUT_DQ_NOISE */
qp1 <<= z; /* Q(FBITS_OUT_DQ_NOISE + z) = Q31 * 2^-(31 - (FBITS_OUT_DQ_NOISE + z)) */
t = InvRNormalized(qp1) << 1; /* Q30 * 2^(31 - (FBITS_OUT_DQ_NOISE + z)), guaranteed not to overflow */
/* normalize to Q31 */
s = (31 - (FBITS_OUT_DQ_NOISE - 1) - z - 1); /* clearly z >= 0, z <= (30 - (FBITS_OUT_DQ_NOISE - 1)) */
*qp1Inv = (t >> s); /* s = [0, 31 - FBITS_OUT_DQ_NOISE] */
*qqp1Inv = MULSHIFT32(t, q) << (32 - FBITS_OUT_DQ_NOISE - s);
}
/**************************************************************************************
* Function: CalcComponentGains
*
* Description: calculate gain of envelope, sinusoids, and noise in one limiter band
* (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
* index of current limiter band
* number of fraction bits in dequantized envelope
*
* Outputs: gains for envelope, sinusoids and noise
* number of fraction bits for envelope gain
* sum of the total gain for each component in this band
* other updated state variables
*
* Return: none
**************************************************************************************/
static void CalcComponentGains(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch, int env, int lim, int fbitsDQ)
{
int d, m, mStart, mEnd, q, qm, noiseFloor, sIndexMapped;
int shift, eCurr, maxFlag, gainMax, gainMaxFBits;
int gain, sm, z, r, fbitsGain, gainScale;
unsigned char *freqBandTab;
mStart = sbrFreq->freqLimiter[lim]; /* these are offsets from kStart */
mEnd = sbrFreq->freqLimiter[lim + 1];
gainMax = psi->gainMax;
gainMaxFBits = psi->gainMaxFBits;
d = (env == psi->la || env == sbrChan->laPrev ? 0 : 1);
freqBandTab = (sbrGrid->freqRes[env] ? sbrFreq->freqHigh : sbrFreq->freqLow);
/* figure out which noise floor this envelope is in (only 1 or 2 noise floors allowed) */
noiseFloor = 0;
if (sbrGrid->numNoiseFloors == 2 && sbrGrid->noiseTimeBorder[1] <= sbrGrid->envTimeBorder[env])
noiseFloor++;
psi->sumECurrGLim = 0;
psi->sumSM = 0;
psi->sumQM = 0;
/* calculate energy of noise to add in this limiter band */
for (m = mStart; m < mEnd; m++) {
if (m == sbrFreq->freqNoise[psi->noiseFloorBand + 1] - sbrFreq->kStart) {
/* map current QMF band to appropriate noise floor band (NOTE: freqLimiter[0] == freqLow[0] = freqHigh[0]) */
psi->noiseFloorBand++;
CalcNoiseDivFactors(psi->noiseDataDequant[ch][noiseFloor][psi->noiseFloorBand], &(psi->qp1Inv), &(psi->qqp1Inv));
}
if (m == sbrFreq->freqHigh[psi->highBand + 1] - sbrFreq->kStart)
psi->highBand++;
if (m == freqBandTab[psi->sBand + 1] - sbrFreq->kStart) {
psi->sBand++;
psi->sMapped = GetSMapped(sbrGrid, sbrFreq, sbrChan, env, psi->sBand, psi->la);
}
/* get sIndexMapped for this QMF subband */
sIndexMapped = 0;
r = ((sbrFreq->freqHigh[psi->highBand+1] + sbrFreq->freqHigh[psi->highBand]) >> 1);
if (m + sbrFreq->kStart == r) {
/* r = center frequency, deltaStep = (env >= la || sIndexMapped'(r, numEnv'-1) == 1) */
if (env >= psi->la || sbrChan->addHarmonic[0][r] == 1)
sIndexMapped = sbrChan->addHarmonic[1][psi->highBand];
}
/* save sine flags from last envelope in this frame:
* addHarmonic[0][0...63] = saved sine present flag from previous frame, for each QMF subband
* addHarmonic[1][0...nHigh-1] = addHarmonic bit from current frame, for each high-res frequency band
* from MPEG reference code - slightly different from spec
* (sIndexMapped'(m,LE'-1) can still be 0 when numEnv == psi->la)
*/
if (env == sbrGrid->numEnv - 1) {
if (m + sbrFreq->kStart == r)
sbrChan->addHarmonic[0][m + sbrFreq->kStart] = sbrChan->addHarmonic[1][psi->highBand];
else
sbrChan->addHarmonic[0][m + sbrFreq->kStart] = 0;
}
gain = psi->envDataDequant[ch][env][psi->sBand];
qm = MULSHIFT32(gain, psi->qqp1Inv) << 1;
sm = (sIndexMapped ? MULSHIFT32(gain, psi->qp1Inv) << 1 : 0);
/* three cases: (sMapped == 0 && delta == 1), (sMapped == 0 && delta == 0), (sMapped == 1) */
if (d == 1 && psi->sMapped == 0)
gain = MULSHIFT32(psi->qp1Inv, gain) << 1;
else if (psi->sMapped != 0)
gain = MULSHIFT32(psi->qqp1Inv, gain) << 1;
/* gain, qm, sm = Q(fbitsDQ), gainMax = Q(fbitsGainMax) */
eCurr = psi->eCurr[m];
if (eCurr) {
z = CLZ(eCurr) - 1;
r = InvRNormalized(eCurr << z); /* in = Q(z - eCurrExp), out = Q(29 + 31 - z + eCurrExp) */
gainScale = MULSHIFT32(gain, r); /* out = Q(29 + 31 - z + eCurrExp + fbitsDQ - 32) */
fbitsGain = 29 + 31 - z + psi->eCurrExp[m] + fbitsDQ - 32;
} else {
/* if eCurr == 0, then gain is unchanged (divide by EPS = 1) */
gainScale = gain;
fbitsGain = fbitsDQ;
}
/* see if gain for this band exceeds max gain */
maxFlag = 0;
if (gainMax != (int)0x80000000) {
if (fbitsGain >= gainMaxFBits) {
shift = MIN(fbitsGain - gainMaxFBits, 31);
maxFlag = ((gainScale >> shift) > gainMax ? 1 : 0);
} else {
shift = MIN(gainMaxFBits - fbitsGain, 31);
maxFlag = (gainScale > (gainMax >> shift) ? 1 : 0);
}
}
if (maxFlag) {
/* gainScale > gainMax, calculate ratio with 32/16 division */
q = 0;
r = gainScale; /* guaranteed > 0, else maxFlag could not have been set */
z = CLZ(r);
if (z < 16) {
q = 16 - z;
r >>= q; /* out = Q(fbitsGain - q) */
}
z = CLZ(gainMax) - 1;
r = (gainMax << z) / r; /* out = Q((fbitsGainMax + z) - (fbitsGain - q)) */
q = (gainMaxFBits + z) - (fbitsGain - q); /* r = Q(q) */
if (q > 30) {
r >>= MIN(q - 30, 31);
} else {
z = MIN(30 - q, 30);
CLIP_2N_SHIFT30(r, z); /* let r = Q30 since range = [0.0, 1.0) (clip to 0x3fffffff = 0.99999) */
}
qm = MULSHIFT32(qm, r) << 2;
gain = MULSHIFT32(gain, r) << 2;
psi->gLimBuf[m] = gainMax;
psi->gLimFbits[m] = gainMaxFBits;
} else {
psi->gLimBuf[m] = gainScale;
psi->gLimFbits[m] = fbitsGain;
}
/* sumSM, sumQM, sumECurrGLim = Q(fbitsDQ - ACC_SCALE) */
psi->smBuf[m] = sm;
psi->sumSM += (sm >> ACC_SCALE);
psi->qmLimBuf[m] = qm;
if (env != psi->la && env != sbrChan->laPrev && sm == 0)
psi->sumQM += (qm >> ACC_SCALE);
/* eCurr * gain^2 same as gain^2, before division by eCurr
* (but note that gain != 0 even if eCurr == 0, since it's divided by eps)
*/
if (eCurr)
psi->sumECurrGLim += (gain >> ACC_SCALE);
}
}
/**************************************************************************************
* Function: ApplyBoost
*
* Description: calculate and apply boost factor for envelope, sinusoids, and noise
* in this limiter band (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRFreq struct for this SCE/CPE block
* index of current limiter band
* number of fraction bits in dequantized envelope
*
* Outputs: envelope gain, sinusoids and noise after scaling by gBoost
* format = Q(FBITS_GLIM_BOOST) for envelope gain,
* = Q(FBITS_QLIM_BOOST) for noise
* = Q(FBITS_OUT_QMFA) for sinusoids
*
* Return: none
*
* Notes: after scaling, each component has at least 1 GB
**************************************************************************************/
static void ApplyBoost(PSInfoSBR *psi, SBRFreq *sbrFreq, int lim, int fbitsDQ)
{
int m, mStart, mEnd, q, z, r;
int sumEOrigMapped, gBoost;
mStart = sbrFreq->freqLimiter[lim]; /* these are offsets from kStart */
mEnd = sbrFreq->freqLimiter[lim + 1];
sumEOrigMapped = psi->sumEOrigMapped >> 1;
r = (psi->sumECurrGLim >> 1) + (psi->sumSM >> 1) + (psi->sumQM >> 1); /* 1 GB fine (sm and qm are mutually exclusive in acc) */
if (r < (1 << (31-28))) {
/* any non-zero numerator * 1/EPS_0 is > GBOOST_MAX
* round very small r to zero to avoid scaling problems
*/
gBoost = (sumEOrigMapped == 0 ? (1 << 28) : GBOOST_MAX);
z = 0;
} else if (sumEOrigMapped == 0) {
/* 1/(any non-zero denominator) * EPS_0 is appx. 0 */
gBoost = 0;
z = 0;
} else {
/* numerator (sumEOrigMapped) and denominator (r) have same Q format (before << z) */
z = CLZ(r) - 1; /* z = [0, 27] */
r = InvRNormalized(r << z);
gBoost = MULSHIFT32(sumEOrigMapped, r);
}
/* gBoost = Q(28 - z) */
if (gBoost > (GBOOST_MAX >> z)) {
gBoost = GBOOST_MAX;
z = 0;
}
gBoost <<= z; /* gBoost = Q28, minimum 1 GB */
/* convert gain, noise, sinusoids to fixed Q format, clipping if necessary
* (rare, usually only happens at very low bitrates, introduces slight
* distortion into final HF mapping, but should be inaudible)
*/
for (m = mStart; m < mEnd; m++) {
/* let gLimBoost = Q24, since in practice the max values are usually 16 to 20
* unless limiterGains == 3 (limiter off) and eCurr ~= 0 (i.e. huge gain, but only
* because the envelope has 0 power anyway)
*/
q = MULSHIFT32(psi->gLimBuf[m], gBoost) << 2; /* Q(gLimFbits) * Q(28) --> Q(gLimFbits[m]-2) */
r = SqrtFix(q, psi->gLimFbits[m] - 2, &z);
z -= FBITS_GLIM_BOOST;
if (z >= 0) {
psi->gLimBoost[m] = r >> MIN(z, 31);
} else {
z = MIN(30, -z);
CLIP_2N_SHIFT30(r, z);
psi->gLimBoost[m] = r;
}
q = MULSHIFT32(psi->qmLimBuf[m], gBoost) << 2; /* Q(fbitsDQ) * Q(28) --> Q(fbitsDQ-2) */
r = SqrtFix(q, fbitsDQ - 2, &z);
z -= FBITS_QLIM_BOOST; /* << by 14, since integer sqrt of x < 2^16, and we want to leave 1 GB */
if (z >= 0) {
psi->qmLimBoost[m] = r >> MIN(31, z);
} else {
z = MIN(30, -z);
CLIP_2N_SHIFT30(r, z);
psi->qmLimBoost[m] = r;
}
q = MULSHIFT32(psi->smBuf[m], gBoost) << 2; /* Q(fbitsDQ) * Q(28) --> Q(fbitsDQ-2) */
r = SqrtFix(q, fbitsDQ - 2, &z);
z -= FBITS_OUT_QMFA; /* justify for adding to signal (xBuf) later */
if (z >= 0) {
psi->smBoost[m] = r >> MIN(31, z);
} else {
z = MIN(30, -z);
CLIP_2N_SHIFT30(r, z);
psi->smBoost[m] = r;
}
}
}
/**************************************************************************************
* Function: CalcGain
*
* Description: calculate and apply proper gain to HF components in one envelope
* (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
*
* Outputs: envelope gain, sinusoids and noise after scaling
*
* Return: none
**************************************************************************************/
static void CalcGain(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch, int env)
{
int lim, fbitsDQ;
/* initialize to -1 so that mapping limiter bands to env/noise bands works right on first pass */
psi->envBand = -1;
psi->noiseFloorBand = -1;
psi->sBand = -1;
psi->highBand = -1;
fbitsDQ = (FBITS_OUT_DQ_ENV - psi->envDataDequantScale[ch][env]); /* Q(29 - optional scalefactor) */
for (lim = 0; lim < sbrFreq->nLimiter; lim++) {
/* the QMF bands are divided into lim regions (consecutive, non-overlapping) */
CalcMaxGain(psi, sbrHdr, sbrGrid, sbrFreq, ch, env, lim, fbitsDQ);
CalcComponentGains(psi, sbrGrid, sbrFreq, sbrChan, ch, env, lim, fbitsDQ);
ApplyBoost(psi, sbrFreq, lim, fbitsDQ);
}
}
/* hSmooth table from 4.7.18.7.6, format = Q31 */
static const int hSmoothCoef[MAX_NUM_SMOOTH_COEFS] PROGMEM = {
0x2aaaaaab, 0x2697a512, 0x1becfa68, 0x0ebdb043, 0x04130598,
};
/**************************************************************************************
* Function: MapHF
*
* Description: map HF components to proper QMF bands, with optional gain smoothing
* filter (4.6.18.7.6)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current envelope
* reset flag (can be non-zero for first envelope only)
*
* Outputs: complete reconstructed subband QMF samples for this envelope
*
* Return: none
*
* Notes: ensures that output has >= MIN_GBITS_IN_QMFS guard bits,
* so it's not necessary to check anything in the synth QMF
**************************************************************************************/
static void MapHF(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int hfReset)
{
int noiseTabIndex, sinIndex, gainNoiseIndex, hSL;
int i, iStart, iEnd, m, idx, j, s, n, smre, smim;
int gFilt, qFilt, xre, xim, gbMask, gbIdx;
int *XBuf;
noiseTabIndex = sbrChan->noiseTabIndex;
sinIndex = sbrChan->sinIndex;
gainNoiseIndex = sbrChan->gainNoiseIndex; /* oldest entries in filter delay buffer */
if (hfReset)
noiseTabIndex = 2; /* starts at 1, double since complex */
hSL = (sbrHdr->smoothMode ? 0 : 4);
if (hfReset) {
for (i = 0; i < hSL; i++) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
sbrChan->gTemp[gainNoiseIndex][m] = psi->gLimBoost[m];
sbrChan->qTemp[gainNoiseIndex][m] = psi->qmLimBoost[m];
}
gainNoiseIndex++;
if (gainNoiseIndex == MAX_NUM_SMOOTH_COEFS)
gainNoiseIndex = 0;
}
ASSERT(env == 0); /* should only be reset when env == 0 */
}
iStart = sbrGrid->envTimeBorder[env];
iEnd = sbrGrid->envTimeBorder[env+1];
for (i = iStart; i < iEnd; i++) {
/* save new values in temp buffers (delay)
* we only store MAX_NUM_SMOOTH_COEFS most recent values,
* so don't keep storing the same value over and over
*/
if (i - iStart < MAX_NUM_SMOOTH_COEFS) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
sbrChan->gTemp[gainNoiseIndex][m] = psi->gLimBoost[m];
sbrChan->qTemp[gainNoiseIndex][m] = psi->qmLimBoost[m];
}
}
/* see 4.6.18.7.6 */
XBuf = psi->XBuf[i + HF_ADJ][sbrFreq->kStart];
gbMask = 0;
for (m = 0; m < sbrFreq->numQMFBands; m++) {
if (env == psi->la || env == sbrChan->laPrev) {
/* no smoothing filter for gain, and qFilt = 0 (only need to do once) */
if (i == iStart) {
psi->gFiltLast[m] = sbrChan->gTemp[gainNoiseIndex][m];
psi->qFiltLast[m] = 0;
}
} else if (hSL == 0) {
/* no smoothing filter for gain, (only need to do once) */
if (i == iStart) {
psi->gFiltLast[m] = sbrChan->gTemp[gainNoiseIndex][m];
psi->qFiltLast[m] = sbrChan->qTemp[gainNoiseIndex][m];
}
} else {
/* apply smoothing filter to gain and noise (after MAX_NUM_SMOOTH_COEFS, it's always the same) */
if (i - iStart < MAX_NUM_SMOOTH_COEFS) {
gFilt = 0;
qFilt = 0;
idx = gainNoiseIndex;
for (j = 0; j < MAX_NUM_SMOOTH_COEFS; j++) {
/* sum(abs(hSmoothCoef[j])) for all j < 1.0 */
gFilt += MULSHIFT32(sbrChan->gTemp[idx][m], hSmoothCoef[j]);
qFilt += MULSHIFT32(sbrChan->qTemp[idx][m], hSmoothCoef[j]);
idx--;
if (idx < 0)
idx += MAX_NUM_SMOOTH_COEFS;
}
psi->gFiltLast[m] = gFilt << 1; /* restore to Q(FBITS_GLIM_BOOST) (gain of filter < 1.0, so no overflow) */
psi->qFiltLast[m] = qFilt << 1; /* restore to Q(FBITS_QLIM_BOOST) */
}
}
if (psi->smBoost[m] != 0) {
/* add scaled signal and sinusoid, don't add noise (qFilt = 0) */
smre = psi->smBoost[m];
smim = smre;
/* sinIndex: [0] xre += sm [1] xim += sm*s [2] xre -= sm [3] xim -= sm*s */
s = (sinIndex >> 1); /* if 2 or 3, flip sign to subtract sm */
s <<= 31;
smre ^= (s >> 31);
smre -= (s >> 31);
s ^= ((m + sbrFreq->kStart) << 31);
smim ^= (s >> 31);
smim -= (s >> 31);
/* if sinIndex == 0 or 2, smim = 0; if sinIndex == 1 or 3, smre = 0 */
s = sinIndex << 31;
smim &= (s >> 31);
s ^= 0x80000000;
smre &= (s >> 31);
noiseTabIndex += 2; /* noise filtered by 0, but still need to bump index */
} else {
/* add scaled signal and scaled noise */
qFilt = psi->qFiltLast[m];
n = noiseTab[noiseTabIndex++];
smre = MULSHIFT32(n, qFilt) >> (FBITS_QLIM_BOOST - 1 - FBITS_OUT_QMFA);
n = noiseTab[noiseTabIndex++];
smim = MULSHIFT32(n, qFilt) >> (FBITS_QLIM_BOOST - 1 - FBITS_OUT_QMFA);
}
noiseTabIndex &= 1023; /* 512 complex numbers */
gFilt = psi->gFiltLast[m];
xre = MULSHIFT32(gFilt, XBuf[0]);
xim = MULSHIFT32(gFilt, XBuf[1]);
CLIP_2N_SHIFT30(xre, 32 - FBITS_GLIM_BOOST);
CLIP_2N_SHIFT30(xim, 32 - FBITS_GLIM_BOOST);
xre += smre; *XBuf++ = xre;
xim += smim; *XBuf++ = xim;
gbMask |= FASTABS(xre);
gbMask |= FASTABS(xim);
}
/* update circular buffer index */
gainNoiseIndex++;
if (gainNoiseIndex == MAX_NUM_SMOOTH_COEFS)
gainNoiseIndex = 0;
sinIndex++;
sinIndex &= 3;
/* ensure MIN_GBITS_IN_QMFS guard bits in output
* almost never occurs in practice, but checking here makes synth QMF logic very simple
*/
if (gbMask >> (31 - MIN_GBITS_IN_QMFS)) {
XBuf = psi->XBuf[i + HF_ADJ][sbrFreq->kStart];
for (m = 0; m < sbrFreq->numQMFBands; m++) {
xre = XBuf[0]; xim = XBuf[1];
CLIP_2N(xre, (31 - MIN_GBITS_IN_QMFS));
CLIP_2N(xim, (31 - MIN_GBITS_IN_QMFS));
*XBuf++ = xre; *XBuf++ = xim;
}
CLIP_2N(gbMask, (31 - MIN_GBITS_IN_QMFS));
}
gbIdx = ((i + HF_ADJ) >> 5) & 0x01;
sbrChan->gbMask[gbIdx] |= gbMask;
}
sbrChan->noiseTabIndex = noiseTabIndex;
sbrChan->sinIndex = sinIndex;
sbrChan->gainNoiseIndex = gainNoiseIndex;
}
/**************************************************************************************
* Function: AdjustHighFreq
*
* Description: adjust high frequencies and add noise and sinusoids (4.6.18.7)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: complete reconstructed subband QMF samples for this channel
*
* Return: none
**************************************************************************************/
void AdjustHighFreq(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int i, env, hfReset;
unsigned char frameClass, pointer;
frameClass = sbrGrid->frameClass;
pointer = sbrGrid->pointer;
/* derive la from table 4.159 */
if ((frameClass == SBR_GRID_FIXVAR || frameClass == SBR_GRID_VARVAR) && pointer > 0)
psi->la = sbrGrid->numEnv + 1 - pointer;
else if (frameClass == SBR_GRID_VARFIX && pointer > 1)
psi->la = pointer - 1;
else
psi->la = -1;
/* for each envelope, estimate gain and adjust SBR QMF bands */
hfReset = sbrChan->reset;
for (env = 0; env < sbrGrid->numEnv; env++) {
EstimateEnvelope(psi, sbrHdr, sbrGrid, sbrFreq, env);
CalcGain(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch, env);
MapHF(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, env, hfReset);
hfReset = 0; /* only set for first envelope after header reset */
}
/* set saved sine flags to 0 for QMF bands outside of current frequency range */
for (i = 0; i < sbrFreq->freqLimiter[0] + sbrFreq->kStart; i++)
sbrChan->addHarmonic[0][i] = 0;
for (i = sbrFreq->freqLimiter[sbrFreq->nLimiter] + sbrFreq->kStart; i < 64; i++)
sbrChan->addHarmonic[0][i] = 0;
sbrChan->addHarmonicFlag[0] = sbrChan->addHarmonicFlag[1];
/* save la for next frame */
if (psi->la == sbrGrid->numEnv)
sbrChan->laPrev = 0;
else
sbrChan->laPrev = -1;
}

View File

@@ -1,616 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrhfgen.c,v 1.2 2005/05/19 20:45:20 jrecker 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
*
* sbrhfgen.c - high frequency generation for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
#define FBITS_LPCOEFS 29 /* Q29 for range of (-4, 4) */
#define MAG_16 (16 * (1 << (32 - (2*(32-FBITS_LPCOEFS))))) /* i.e. 16 in Q26 format */
#define RELAX_COEF 0x7ffff79c /* 1.0 / (1.0 + 1e-6), Q31 */
/* newBWTab[prev invfMode][curr invfMode], format = Q31 (table 4.158)
* sample file which uses all of these: al_sbr_sr_64_2_fsaac32.aac
*/
static const int newBWTab[4][4] PROGMEM = {
{0x00000000, 0x4ccccccd, 0x73333333, 0x7d70a3d7},
{0x4ccccccd, 0x60000000, 0x73333333, 0x7d70a3d7},
{0x00000000, 0x60000000, 0x73333333, 0x7d70a3d7},
{0x00000000, 0x60000000, 0x73333333, 0x7d70a3d7},
};
/**************************************************************************************
* Function: CVKernel1
*
* Description: kernel of covariance matrix calculation for p01, p11, p12, p22
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
*
* Outputs: 64-bit accumulators for p01re, p01im, p12re, p12im, p11re, p22re
* stored in accBuf
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrcov.s when building for ARM!
**************************************************************************************/
#if (defined (XXXX__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(XXXX__arm__))
#ifdef __cplusplus
extern "C"
#endif
void CVKernel1(int *XBuf, int *accBuf);
#else
void CVKernel1(int *XBuf, int *accBuf)
{
U64 p01re, p01im, p12re, p12im, p11re, p22re;
int n, x0re, x0im, x1re, x1im;
x0re = XBuf[0];
x0im = XBuf[1];
XBuf += (2*64);
x1re = XBuf[0];
x1im = XBuf[1];
XBuf += (2*64);
p01re.w64 = p01im.w64 = 0;
p12re.w64 = p12im.w64 = 0;
p11re.w64 = 0;
p22re.w64 = 0;
p12re.w64 = MADD64(p12re.w64, x1re, x0re);
p12re.w64 = MADD64(p12re.w64, x1im, x0im);
p12im.w64 = MADD64(p12im.w64, x0re, x1im);
p12im.w64 = MADD64(p12im.w64, -x0im, x1re);
p22re.w64 = MADD64(p22re.w64, x0re, x0re);
p22re.w64 = MADD64(p22re.w64, x0im, x0im);
for (n = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6); n != 0; n--) {
/* 4 input, 3*2 acc, 1 ptr, 1 loop counter = 12 registers (use same for x0im, -x0im) */
x0re = x1re;
x0im = x1im;
x1re = XBuf[0];
x1im = XBuf[1];
p01re.w64 = MADD64(p01re.w64, x1re, x0re);
p01re.w64 = MADD64(p01re.w64, x1im, x0im);
p01im.w64 = MADD64(p01im.w64, x0re, x1im);
p01im.w64 = MADD64(p01im.w64, -x0im, x1re);
p11re.w64 = MADD64(p11re.w64, x0re, x0re);
p11re.w64 = MADD64(p11re.w64, x0im, x0im);
XBuf += (2*64);
}
/* these can be derived by slight changes to account for boundary conditions */
p12re.w64 += p01re.w64;
p12re.w64 = MADD64(p12re.w64, x1re, -x0re);
p12re.w64 = MADD64(p12re.w64, x1im, -x0im);
p12im.w64 += p01im.w64;
p12im.w64 = MADD64(p12im.w64, x0re, -x1im);
p12im.w64 = MADD64(p12im.w64, x0im, x1re);
p22re.w64 += p11re.w64;
p22re.w64 = MADD64(p22re.w64, x0re, -x0re);
p22re.w64 = MADD64(p22re.w64, x0im, -x0im);
accBuf[0] = p01re.r.lo32; accBuf[1] = p01re.r.hi32;
accBuf[2] = p01im.r.lo32; accBuf[3] = p01im.r.hi32;
accBuf[4] = p11re.r.lo32; accBuf[5] = p11re.r.hi32;
accBuf[6] = p12re.r.lo32; accBuf[7] = p12re.r.hi32;
accBuf[8] = p12im.r.lo32; accBuf[9] = p12im.r.hi32;
accBuf[10] = p22re.r.lo32; accBuf[11] = p22re.r.hi32;
}
#endif
/**************************************************************************************
* Function: CalcCovariance1
*
* Description: calculate covariance matrix for p01, p12, p11, p22 (4.6.18.6.2)
*
* Inputs: buffer of low-freq samples, starting at time index 0,
* freq index = patch subband
*
* Outputs: complex covariance elements p01re, p01im, p12re, p12im, p11re, p22re
* (p11im = p22im = 0)
* format = integer (Q0) * 2^N, with scalefactor N >= 0
*
* Return: scalefactor N
*
* Notes: outputs are normalized to have 1 GB (sign in at least top 2 bits)
**************************************************************************************/
static int CalcCovariance1(int *XBuf, int *p01reN, int *p01imN, int *p12reN, int *p12imN, int *p11reN, int *p22reN)
{
int accBuf[2*6];
int n, z, s, loShift, hiShift, gbMask;
U64 p01re, p01im, p12re, p12im, p11re, p22re;
CVKernel1(XBuf, accBuf);
p01re.r.lo32 = accBuf[0]; p01re.r.hi32 = accBuf[1];
p01im.r.lo32 = accBuf[2]; p01im.r.hi32 = accBuf[3];
p11re.r.lo32 = accBuf[4]; p11re.r.hi32 = accBuf[5];
p12re.r.lo32 = accBuf[6]; p12re.r.hi32 = accBuf[7];
p12im.r.lo32 = accBuf[8]; p12im.r.hi32 = accBuf[9];
p22re.r.lo32 = accBuf[10]; p22re.r.hi32 = accBuf[11];
/* 64-bit accumulators now have 2*FBITS_OUT_QMFA fraction bits
* want to scale them down to integers (32-bit signed, Q0)
* with scale factor of 2^n, n >= 0
* leave 2 GB's for calculating determinant, so take top 30 non-zero bits
*/
gbMask = ((p01re.r.hi32) ^ (p01re.r.hi32 >> 31)) | ((p01im.r.hi32) ^ (p01im.r.hi32 >> 31));
gbMask |= ((p12re.r.hi32) ^ (p12re.r.hi32 >> 31)) | ((p12im.r.hi32) ^ (p12im.r.hi32 >> 31));
gbMask |= ((p11re.r.hi32) ^ (p11re.r.hi32 >> 31)) | ((p22re.r.hi32) ^ (p22re.r.hi32 >> 31));
if (gbMask == 0) {
s = p01re.r.hi32 >> 31; gbMask = (p01re.r.lo32 ^ s) - s;
s = p01im.r.hi32 >> 31; gbMask |= (p01im.r.lo32 ^ s) - s;
s = p12re.r.hi32 >> 31; gbMask |= (p12re.r.lo32 ^ s) - s;
s = p12im.r.hi32 >> 31; gbMask |= (p12im.r.lo32 ^ s) - s;
s = p11re.r.hi32 >> 31; gbMask |= (p11re.r.lo32 ^ s) - s;
s = p22re.r.hi32 >> 31; gbMask |= (p22re.r.lo32 ^ s) - s;
z = 32 + CLZ(gbMask);
} else {
gbMask = FASTABS(p01re.r.hi32) | FASTABS(p01im.r.hi32);
gbMask |= FASTABS(p12re.r.hi32) | FASTABS(p12im.r.hi32);
gbMask |= FASTABS(p11re.r.hi32) | FASTABS(p22re.r.hi32);
z = CLZ(gbMask);
}
n = 64 - z; /* number of non-zero bits in bottom of 64-bit word */
if (n <= 30) {
loShift = (30 - n);
*p01reN = p01re.r.lo32 << loShift; *p01imN = p01im.r.lo32 << loShift;
*p12reN = p12re.r.lo32 << loShift; *p12imN = p12im.r.lo32 << loShift;
*p11reN = p11re.r.lo32 << loShift; *p22reN = p22re.r.lo32 << loShift;
return -(loShift + 2*FBITS_OUT_QMFA);
} else if (n < 32 + 30) {
loShift = (n - 30);
hiShift = 32 - loShift;
*p01reN = (p01re.r.hi32 << hiShift) | (p01re.r.lo32 >> loShift);
*p01imN = (p01im.r.hi32 << hiShift) | (p01im.r.lo32 >> loShift);
*p12reN = (p12re.r.hi32 << hiShift) | (p12re.r.lo32 >> loShift);
*p12imN = (p12im.r.hi32 << hiShift) | (p12im.r.lo32 >> loShift);
*p11reN = (p11re.r.hi32 << hiShift) | (p11re.r.lo32 >> loShift);
*p22reN = (p22re.r.hi32 << hiShift) | (p22re.r.lo32 >> loShift);
return (loShift - 2*FBITS_OUT_QMFA);
} else {
hiShift = n - (32 + 30);
*p01reN = p01re.r.hi32 >> hiShift; *p01imN = p01im.r.hi32 >> hiShift;
*p12reN = p12re.r.hi32 >> hiShift; *p12imN = p12im.r.hi32 >> hiShift;
*p11reN = p11re.r.hi32 >> hiShift; *p22reN = p22re.r.hi32 >> hiShift;
return (32 - 2*FBITS_OUT_QMFA - hiShift);
}
return 0;
}
/**************************************************************************************
* Function: CVKernel2
*
* Description: kernel of covariance matrix calculation for p02
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
*
* Outputs: 64-bit accumulators for p02re, p02im stored in accBuf
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrcov.s when building for ARM!
**************************************************************************************/
#if (defined (XXXX__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(XXXX__arm__))
#ifdef __cplusplus
extern "C"
#endif
void CVKernel2(int *XBuf, int *accBuf);
#else
void CVKernel2(int *XBuf, int *accBuf)
{
U64 p02re, p02im;
int n, x0re, x0im, x1re, x1im, x2re, x2im;
p02re.w64 = p02im.w64 = 0;
x0re = XBuf[0];
x0im = XBuf[1];
XBuf += (2*64);
x1re = XBuf[0];
x1im = XBuf[1];
XBuf += (2*64);
for (n = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6); n != 0; n--) {
/* 6 input, 2*2 acc, 1 ptr, 1 loop counter = 12 registers (use same for x0im, -x0im) */
x2re = XBuf[0];
x2im = XBuf[1];
p02re.w64 = MADD64(p02re.w64, x2re, x0re);
p02re.w64 = MADD64(p02re.w64, x2im, x0im);
p02im.w64 = MADD64(p02im.w64, x0re, x2im);
p02im.w64 = MADD64(p02im.w64, -x0im, x2re);
x0re = x1re;
x0im = x1im;
x1re = x2re;
x1im = x2im;
XBuf += (2*64);
}
accBuf[0] = p02re.r.lo32;
accBuf[1] = p02re.r.hi32;
accBuf[2] = p02im.r.lo32;
accBuf[3] = p02im.r.hi32;
}
#endif
/**************************************************************************************
* Function: CalcCovariance2
*
* Description: calculate covariance matrix for p02 (4.6.18.6.2)
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
*
* Outputs: complex covariance element p02re, p02im
* format = integer (Q0) * 2^N, with scalefactor N >= 0
*
* Return: scalefactor N
*
* Notes: outputs are normalized to have 1 GB (sign in at least top 2 bits)
**************************************************************************************/
static int CalcCovariance2(int *XBuf, int *p02reN, int *p02imN)
{
U64 p02re, p02im;
int n, z, s, loShift, hiShift, gbMask;
int accBuf[2*2];
CVKernel2(XBuf, accBuf);
p02re.r.lo32 = accBuf[0];
p02re.r.hi32 = accBuf[1];
p02im.r.lo32 = accBuf[2];
p02im.r.hi32 = accBuf[3];
/* 64-bit accumulators now have 2*FBITS_OUT_QMFA fraction bits
* want to scale them down to integers (32-bit signed, Q0)
* with scale factor of 2^n, n >= 0
* leave 1 GB for calculating determinant, so take top 30 non-zero bits
*/
gbMask = ((p02re.r.hi32) ^ (p02re.r.hi32 >> 31)) | ((p02im.r.hi32) ^ (p02im.r.hi32 >> 31));
if (gbMask == 0) {
s = p02re.r.hi32 >> 31; gbMask = (p02re.r.lo32 ^ s) - s;
s = p02im.r.hi32 >> 31; gbMask |= (p02im.r.lo32 ^ s) - s;
z = 32 + CLZ(gbMask);
} else {
gbMask = FASTABS(p02re.r.hi32) | FASTABS(p02im.r.hi32);
z = CLZ(gbMask);
}
n = 64 - z; /* number of non-zero bits in bottom of 64-bit word */
if (n <= 30) {
loShift = (30 - n);
*p02reN = p02re.r.lo32 << loShift;
*p02imN = p02im.r.lo32 << loShift;
return -(loShift + 2*FBITS_OUT_QMFA);
} else if (n < 32 + 30) {
loShift = (n - 30);
hiShift = 32 - loShift;
*p02reN = (p02re.r.hi32 << hiShift) | (p02re.r.lo32 >> loShift);
*p02imN = (p02im.r.hi32 << hiShift) | (p02im.r.lo32 >> loShift);
return (loShift - 2*FBITS_OUT_QMFA);
} else {
hiShift = n - (32 + 30);
*p02reN = p02re.r.hi32 >> hiShift;
*p02imN = p02im.r.hi32 >> hiShift;
return (32 - 2*FBITS_OUT_QMFA - hiShift);
}
return 0;
}
/**************************************************************************************
* Function: CalcLPCoefs
*
* Description: calculate linear prediction coefficients for one subband (4.6.18.6.2)
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
* number of guard bits in input sample buffer
*
* Outputs: complex LP coefficients a0re, a0im, a1re, a1im, format = Q29
*
* Return: none
*
* Notes: output coefficients (a0re, a0im, a1re, a1im) clipped to range (-4, 4)
* if the comples coefficients have magnitude >= 4.0, they are all
* set to 0 (see spec)
**************************************************************************************/
static void CalcLPCoefs(int *XBuf, int *a0re, int *a0im, int *a1re, int *a1im, int gb)
{
int zFlag, n1, n2, nd, d, dInv, tre, tim;
int p01re, p01im, p02re, p02im, p12re, p12im, p11re, p22re;
/* pre-scale to avoid overflow - probably never happens in practice (see QMFA)
* max bit growth per accumulator = 38*2 = 76 mul-adds (X * X)
* using 64-bit MADD, so if X has n guard bits, X*X has 2n+1 guard bits
* gain 1 extra sign bit per multiply, so ensure ceil(log2(76/2) / 2) = 3 guard bits on inputs
*/
if (gb < 3) {
nd = 3 - gb;
for (n1 = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6 + 2); n1 != 0; n1--) {
XBuf[0] >>= nd; XBuf[1] >>= nd;
XBuf += (2*64);
}
XBuf -= (2*64*(NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6 + 2));
}
/* calculate covariance elements */
n1 = CalcCovariance1(XBuf, &p01re, &p01im, &p12re, &p12im, &p11re, &p22re);
n2 = CalcCovariance2(XBuf, &p02re, &p02im);
/* normalize everything to larger power of 2 scalefactor, call it n1 */
if (n1 < n2) {
nd = MIN(n2 - n1, 31);
p01re >>= nd; p01im >>= nd;
p12re >>= nd; p12im >>= nd;
p11re >>= nd; p22re >>= nd;
n1 = n2;
} else if (n1 > n2) {
nd = MIN(n1 - n2, 31);
p02re >>= nd; p02im >>= nd;
}
/* calculate determinant of covariance matrix (at least 1 GB in pXX) */
d = MULSHIFT32(p12re, p12re) + MULSHIFT32(p12im, p12im);
d = MULSHIFT32(d, RELAX_COEF) << 1;
d = MULSHIFT32(p11re, p22re) - d;
ASSERT(d >= 0); /* should never be < 0 */
zFlag = 0;
*a0re = *a0im = 0;
*a1re = *a1im = 0;
if (d > 0) {
/* input = Q31 d = Q(-2*n1 - 32 + nd) = Q31 * 2^(31 + 2*n1 + 32 - nd)
* inverse = Q29 dInv = Q29 * 2^(-31 - 2*n1 - 32 + nd) = Q(29 + 31 + 2*n1 + 32 - nd)
*
* numerator has same Q format as d, since it's sum of normalized squares
* so num * inverse = Q(-2*n1 - 32) * Q(29 + 31 + 2*n1 + 32 - nd)
* = Q(29 + 31 - nd), drop low 32 in MULSHIFT32
* = Q(29 + 31 - 32 - nd) = Q(28 - nd)
*/
nd = CLZ(d) - 1;
d <<= nd;
dInv = InvRNormalized(d);
/* 1 GB in pXX */
tre = MULSHIFT32(p01re, p12re) - MULSHIFT32(p01im, p12im) - MULSHIFT32(p02re, p11re);
tre = MULSHIFT32(tre, dInv);
tim = MULSHIFT32(p01re, p12im) + MULSHIFT32(p01im, p12re) - MULSHIFT32(p02im, p11re);
tim = MULSHIFT32(tim, dInv);
/* if d is extremely small, just set coefs to 0 (would have poor precision anyway) */
if (nd > 28 || (FASTABS(tre) >> (28 - nd)) >= 4 || (FASTABS(tim) >> (28 - nd)) >= 4) {
zFlag = 1;
} else {
*a1re = tre << (FBITS_LPCOEFS - 28 + nd); /* i.e. convert Q(28 - nd) to Q(29) */
*a1im = tim << (FBITS_LPCOEFS - 28 + nd);
}
}
if (p11re) {
/* input = Q31 p11re = Q(-n1 + nd) = Q31 * 2^(31 + n1 - nd)
* inverse = Q29 dInv = Q29 * 2^(-31 - n1 + nd) = Q(29 + 31 + n1 - nd)
*
* numerator is Q(-n1 - 3)
* so num * inverse = Q(-n1 - 3) * Q(29 + 31 + n1 - nd)
* = Q(29 + 31 - 3 - nd), drop low 32 in MULSHIFT32
* = Q(29 + 31 - 3 - 32 - nd) = Q(25 - nd)
*/
nd = CLZ(p11re) - 1; /* assume positive */
p11re <<= nd;
dInv = InvRNormalized(p11re);
/* a1re, a1im = Q29, so scaled by (n1 + 3) */
tre = (p01re >> 3) + MULSHIFT32(p12re, *a1re) + MULSHIFT32(p12im, *a1im);
tre = -MULSHIFT32(tre, dInv);
tim = (p01im >> 3) - MULSHIFT32(p12im, *a1re) + MULSHIFT32(p12re, *a1im);
tim = -MULSHIFT32(tim, dInv);
if (nd > 25 || (FASTABS(tre) >> (25 - nd)) >= 4 || (FASTABS(tim) >> (25 - nd)) >= 4) {
zFlag = 1;
} else {
*a0re = tre << (FBITS_LPCOEFS - 25 + nd); /* i.e. convert Q(25 - nd) to Q(29) */
*a0im = tim << (FBITS_LPCOEFS - 25 + nd);
}
}
/* see 4.6.18.6.2 - if magnitude of a0 or a1 >= 4 then a0 = a1 = 0
* i.e. a0re < 4, a0im < 4, a1re < 4, a1im < 4
* Q29*Q29 = Q26
*/
if (zFlag || MULSHIFT32(*a0re, *a0re) + MULSHIFT32(*a0im, *a0im) >= MAG_16 || MULSHIFT32(*a1re, *a1re) + MULSHIFT32(*a1im, *a1im) >= MAG_16) {
*a0re = *a0im = 0;
*a1re = *a1im = 0;
}
/* no need to clip - we never changed the XBuf data, just used it to calculate a0 and a1 */
if (gb < 3) {
nd = 3 - gb;
for (n1 = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6 + 2); n1 != 0; n1--) {
XBuf[0] <<= nd; XBuf[1] <<= nd;
XBuf += (2*64);
}
}
}
/**************************************************************************************
* Function: GenerateHighFreq
*
* Description: generate high frequencies with SBR (4.6.18.6)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: new high frequency samples starting at frequency kStart
*
* Return: none
**************************************************************************************/
void GenerateHighFreq(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int band, newBW, c, t, gb, gbMask, gbIdx;
int currPatch, p, x, k, g, i, iStart, iEnd, bw, bwsq;
int a0re, a0im, a1re, a1im;
int x1re, x1im, x2re, x2im;
int ACCre, ACCim;
int *XBufLo, *XBufHi;
(void) ch;
/* calculate array of chirp factors */
for (band = 0; band < sbrFreq->numNoiseFloorBands; band++) {
c = sbrChan->chirpFact[band]; /* previous (bwArray') */
newBW = newBWTab[sbrChan->invfMode[0][band]][sbrChan->invfMode[1][band]];
/* weighted average of new and old (can't overflow - total gain = 1.0) */
if (newBW < c)
t = MULSHIFT32(newBW, 0x60000000) + MULSHIFT32(0x20000000, c); /* new is smaller: 0.75*new + 0.25*old */
else
t = MULSHIFT32(newBW, 0x74000000) + MULSHIFT32(0x0c000000, c); /* new is larger: 0.90625*new + 0.09375*old */
t <<= 1;
if (t < 0x02000000) /* below 0.015625, clip to 0 */
t = 0;
if (t > 0x7f800000) /* clip to 0.99609375 */
t = 0x7f800000;
/* save curr as prev for next time */
sbrChan->chirpFact[band] = t;
sbrChan->invfMode[0][band] = sbrChan->invfMode[1][band];
}
iStart = sbrGrid->envTimeBorder[0] + HF_ADJ;
iEnd = sbrGrid->envTimeBorder[sbrGrid->numEnv] + HF_ADJ;
/* generate new high freqs from low freqs, patches, and chirp factors */
k = sbrFreq->kStart;
g = 0;
bw = sbrChan->chirpFact[g];
bwsq = MULSHIFT32(bw, bw) << 1;
gbMask = (sbrChan->gbMask[0] | sbrChan->gbMask[1]); /* older 32 | newer 8 */
gb = CLZ(gbMask) - 1;
for (currPatch = 0; currPatch < sbrFreq->numPatches; currPatch++) {
for (x = 0; x < sbrFreq->patchNumSubbands[currPatch]; x++) {
/* map k to corresponding noise floor band */
if (k >= sbrFreq->freqNoise[g+1]) {
g++;
bw = sbrChan->chirpFact[g]; /* Q31 */
bwsq = MULSHIFT32(bw, bw) << 1; /* Q31 */
}
p = sbrFreq->patchStartSubband[currPatch] + x; /* low QMF band */
XBufHi = psi->XBuf[iStart][k];
if (bw) {
CalcLPCoefs(psi->XBuf[0][p], &a0re, &a0im, &a1re, &a1im, gb);
a0re = MULSHIFT32(bw, a0re); /* Q31 * Q29 = Q28 */
a0im = MULSHIFT32(bw, a0im);
a1re = MULSHIFT32(bwsq, a1re);
a1im = MULSHIFT32(bwsq, a1im);
XBufLo = psi->XBuf[iStart-2][p];
x2re = XBufLo[0]; /* RE{XBuf[n-2]} */
x2im = XBufLo[1]; /* IM{XBuf[n-2]} */
XBufLo += (64*2);
x1re = XBufLo[0]; /* RE{XBuf[n-1]} */
x1im = XBufLo[1]; /* IM{XBuf[n-1]} */
XBufLo += (64*2);
for (i = iStart; i < iEnd; i++) {
/* a0re/im, a1re/im are Q28 with at least 1 GB,
* so the summing for AACre/im is fine (1 GB in, plus 1 from MULSHIFT32)
*/
ACCre = MULSHIFT32(x2re, a1re) - MULSHIFT32(x2im, a1im);
ACCim = MULSHIFT32(x2re, a1im) + MULSHIFT32(x2im, a1re);
x2re = x1re;
x2im = x1im;
ACCre += MULSHIFT32(x1re, a0re) - MULSHIFT32(x1im, a0im);
ACCim += MULSHIFT32(x1re, a0im) + MULSHIFT32(x1im, a0re);
x1re = XBufLo[0]; /* RE{XBuf[n]} */
x1im = XBufLo[1]; /* IM{XBuf[n]} */
XBufLo += (64*2);
/* lost 4 fbits when scaling by a0re/im, a1re/im (Q28) */
CLIP_2N_SHIFT30(ACCre, 4);
ACCre += x1re;
CLIP_2N_SHIFT30(ACCim, 4);
ACCim += x1im;
XBufHi[0] = ACCre;
XBufHi[1] = ACCim;
XBufHi += (64*2);
/* update guard bit masks */
gbMask = FASTABS(ACCre);
gbMask |= FASTABS(ACCim);
gbIdx = (i >> 5) & 0x01; /* 0 if i < 32, 1 if i >= 32 */
sbrChan->gbMask[gbIdx] |= gbMask;
}
} else {
XBufLo = (int *)psi->XBuf[iStart][p];
for (i = iStart; i < iEnd; i++) {
XBufHi[0] = XBufLo[0];
XBufHi[1] = XBufLo[1];
XBufLo += (64*2);
XBufHi += (64*2);
}
}
k++; /* high QMF band */
}
}
}

View File

@@ -1,476 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrhuff.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrhuff.c - functions for unpacking Huffman-coded envelope and noise data
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/**************************************************************************************
* Function: DecodeHuffmanScalar
*
* Description: decode one Huffman symbol from bitstream
*
* Inputs: pointers to Huffman table and info struct
* left-aligned bit buffer with >= huffTabInfo->maxBits bits
*
* Outputs: decoded symbol in *val
*
* Return: number of bits in symbol
*
* Notes: assumes canonical Huffman codes:
* first CW always 0, we have "count" CW's of length "nBits" bits
* starting CW for codes of length nBits+1 =
* (startCW[nBits] + count[nBits]) << 1
* if there are no codes at nBits, then we just keep << 1 each time
* (since count[nBits] = 0)
**************************************************************************************/
static int DecodeHuffmanScalar(const signed /*short*/ int *huffTab, const HuffInfo *huffTabInfo, unsigned int bitBuf, signed int *val)
{
unsigned int count, start, shift, t;
const unsigned int /*char*/ *countPtr;
const signed int /*short*/ *map;
map = huffTab + huffTabInfo->offset;
countPtr = huffTabInfo->count;
start = 0;
count = 0;
shift = 32;
do {
start += count;
start <<= 1;
map += count;
count = *countPtr++;
shift--;
t = (bitBuf >> shift) - start;
} while (t >= count);
*val = (signed int)map[t];
return (countPtr - huffTabInfo->count);
}
/**************************************************************************************
* Function: DecodeOneSymbol
*
* Description: dequantize one Huffman symbol from bitstream,
* using table huffTabSBR[huffTabIndex]
*
* Inputs: BitStreamInfo struct pointing to start of next Huffman codeword
* index of Huffman table
*
* Outputs: bitstream advanced by number of bits in codeword
*
* Return: one decoded symbol
**************************************************************************************/
static int DecodeOneSymbol(BitStreamInfo *bsi, int huffTabIndex)
{
int nBits, val;
unsigned int bitBuf;
const HuffInfo *hi;
hi = &(huffTabSBRInfo[huffTabIndex]);
bitBuf = GetBitsNoAdvance(bsi, hi->maxBits) << (32 - hi->maxBits);
nBits = DecodeHuffmanScalar(huffTabSBR, hi, bitBuf, &val);
AdvanceBitstream(bsi, nBits);
return val;
}
/* [1.0, sqrt(2)], format = Q29 (one guard bit for decoupling) */
static const int envDQTab[2] PROGMEM = {0x20000000, 0x2d413ccc};
/**************************************************************************************
* Function: DequantizeEnvelope
*
* Description: dequantize envelope scalefactors
*
* Inputs: number of scalefactors to process
* amplitude resolution flag for this frame (0 or 1)
* quantized envelope scalefactors
*
* Outputs: dequantized envelope scalefactors
*
* Return: extra int bits in output (6 + expMax)
* in other words, output format = Q(FBITS_OUT_DQ_ENV - (6 + expMax))
*
* Notes: dequantized scalefactors have at least 2 GB
**************************************************************************************/
static int DequantizeEnvelope(int nBands, int ampRes, signed char *envQuant, int *envDequant)
{
int exp, expMax, i, scalei;
if (nBands <= 0)
return 0;
/* scan for largest dequant value (do separately from envelope decoding to keep code cleaner) */
expMax = 0;
for (i = 0; i < nBands; i++) {
if (envQuant[i] > expMax)
expMax = envQuant[i];
}
/* dequantized envelope gains
* envDequant = 64*2^(envQuant / alpha) = 2^(6 + envQuant / alpha)
* if ampRes == 0, alpha = 2 and range of envQuant = [0, 127]
* if ampRes == 1, alpha = 1 and range of envQuant = [0, 63]
* also if coupling is on, envDequant is scaled by something in range [0, 2]
* so range of envDequant = [2^6, 2^69] (no coupling), [2^6, 2^70] (with coupling)
*
* typical range (from observation) of envQuant/alpha = [0, 27] --> largest envQuant ~= 2^33
* output: Q(29 - (6 + expMax))
*
* reference: 14496-3:2001(E)/4.6.18.3.5 and 14496-4:200X/FPDAM8/5.6.5.1.2.1.5
*/
if (ampRes) {
do {
exp = *envQuant++;
scalei = MIN(expMax - exp, 31);
*envDequant++ = envDQTab[0] >> scalei;
} while (--nBands);
return (6 + expMax);
} else {
expMax >>= 1;
do {
exp = *envQuant++;
scalei = MIN(expMax - (exp >> 1), 31);
*envDequant++ = envDQTab[exp & 0x01] >> scalei;
} while (--nBands);
return (6 + expMax);
}
}
/**************************************************************************************
* Function: DequantizeNoise
*
* Description: dequantize noise scalefactors
*
* Inputs: number of scalefactors to process
* quantized noise scalefactors
*
* Outputs: dequantized noise scalefactors, format = Q(FBITS_OUT_DQ_NOISE)
*
* Return: none
*
* Notes: dequantized scalefactors have at least 2 GB
**************************************************************************************/
static void DequantizeNoise(int nBands, signed char *noiseQuant, int *noiseDequant)
{
int exp, scalei;
if (nBands <= 0)
return;
/* dequantize noise floor gains (4.6.18.3.5):
* noiseDequant = 2^(NOISE_FLOOR_OFFSET - noiseQuant)
*
* range of noiseQuant = [0, 30] (see 4.6.18.3.6), NOISE_FLOOR_OFFSET = 6
* so range of noiseDequant = [2^-24, 2^6]
*/
do {
exp = *noiseQuant++;
scalei = NOISE_FLOOR_OFFSET - exp + FBITS_OUT_DQ_NOISE; /* 6 + 24 - exp, exp = [0,30] */
if (scalei < 0)
*noiseDequant++ = 0;
else if (scalei < 30)
*noiseDequant++ = 1 << scalei;
else
*noiseDequant++ = 0x3fffffff; /* leave 2 GB */
} while (--nBands);
}
/**************************************************************************************
* Function: DecodeSBREnvelope
*
* Description: decode delta Huffman coded envelope scalefactors from bitstream
*
* Inputs: BitStreamInfo struct pointing to start of env data
* initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: dequantized env scalefactors for left channel (before decoupling)
* dequantized env scalefactors for right channel (if coupling off)
* or raw decoded env scalefactors for right channel (if coupling on)
*
* Return: none
**************************************************************************************/
void DecodeSBREnvelope(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int huffIndexTime, huffIndexFreq, env, envStartBits, band, nBands, sf, lastEnv;
int freqRes, freqResPrev, dShift, i;
if (psi->couplingFlag && ch) {
dShift = 1;
if (sbrGrid->ampResFrame) {
huffIndexTime = HuffTabSBR_tEnv30b;
huffIndexFreq = HuffTabSBR_fEnv30b;
envStartBits = 5;
} else {
huffIndexTime = HuffTabSBR_tEnv15b;
huffIndexFreq = HuffTabSBR_fEnv15b;
envStartBits = 6;
}
} else {
dShift = 0;
if (sbrGrid->ampResFrame) {
huffIndexTime = HuffTabSBR_tEnv30;
huffIndexFreq = HuffTabSBR_fEnv30;
envStartBits = 6;
} else {
huffIndexTime = HuffTabSBR_tEnv15;
huffIndexFreq = HuffTabSBR_fEnv15;
envStartBits = 7;
}
}
/* range of envDataQuant[] = [0, 127] (see comments in DequantizeEnvelope() for reference) */
for (env = 0; env < sbrGrid->numEnv; env++) {
nBands = (sbrGrid->freqRes[env] ? sbrFreq->nHigh : sbrFreq->nLow);
freqRes = (sbrGrid->freqRes[env]);
freqResPrev = (env == 0 ? sbrGrid->freqResPrev : sbrGrid->freqRes[env-1]);
lastEnv = (env == 0 ? sbrGrid->numEnvPrev-1 : env-1);
if (lastEnv < 0)
lastEnv = 0; /* first frame */
ASSERT(nBands <= MAX_QMF_BANDS);
if (sbrChan->deltaFlagEnv[env] == 0) {
/* delta coding in freq */
sf = GetBits(bsi, envStartBits) << dShift;
sbrChan->envDataQuant[env][0] = sf;
for (band = 1; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexFreq) << dShift;
sbrChan->envDataQuant[env][band] = sf + sbrChan->envDataQuant[env][band-1];
}
} else if (freqRes == freqResPrev) {
/* delta coding in time - same freq resolution for both frames */
for (band = 0; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->envDataQuant[env][band] = sf + sbrChan->envDataQuant[lastEnv][band];
}
} else if (freqRes == 0 && freqResPrev == 1) {
/* delta coding in time - low freq resolution for new frame, high freq resolution for old frame */
for (band = 0; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->envDataQuant[env][band] = sf;
for (i = 0; i < sbrFreq->nHigh; i++) {
if (sbrFreq->freqHigh[i] == sbrFreq->freqLow[band]) {
sbrChan->envDataQuant[env][band] += sbrChan->envDataQuant[lastEnv][i];
break;
}
}
}
} else if (freqRes == 1 && freqResPrev == 0) {
/* delta coding in time - high freq resolution for new frame, low freq resolution for old frame */
for (band = 0; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->envDataQuant[env][band] = sf;
for (i = 0; i < sbrFreq->nLow; i++) {
if (sbrFreq->freqLow[i] <= sbrFreq->freqHigh[band] && sbrFreq->freqHigh[band] < sbrFreq->freqLow[i+1] ) {
sbrChan->envDataQuant[env][band] += sbrChan->envDataQuant[lastEnv][i];
break;
}
}
}
}
/* skip coupling channel */
if (ch != 1 || psi->couplingFlag != 1)
psi->envDataDequantScale[ch][env] = DequantizeEnvelope(nBands, sbrGrid->ampResFrame, sbrChan->envDataQuant[env], psi->envDataDequant[ch][env]);
}
sbrGrid->numEnvPrev = sbrGrid->numEnv;
sbrGrid->freqResPrev = sbrGrid->freqRes[sbrGrid->numEnv-1];
}
/**************************************************************************************
* Function: DecodeSBRNoise
*
* Description: decode delta Huffman coded noise scalefactors from bitstream
*
* Inputs: BitStreamInfo struct pointing to start of noise data
* initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: dequantized noise scalefactors for left channel (before decoupling)
* dequantized noise scalefactors for right channel (if coupling off)
* or raw decoded noise scalefactors for right channel (if coupling on)
*
* Return: none
**************************************************************************************/
void DecodeSBRNoise(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int huffIndexTime, huffIndexFreq, noiseFloor, band, dShift, sf, lastNoiseFloor;
if (psi->couplingFlag && ch) {
dShift = 1;
huffIndexTime = HuffTabSBR_tNoise30b;
huffIndexFreq = HuffTabSBR_fNoise30b;
} else {
dShift = 0;
huffIndexTime = HuffTabSBR_tNoise30;
huffIndexFreq = HuffTabSBR_fNoise30;
}
for (noiseFloor = 0; noiseFloor < sbrGrid->numNoiseFloors; noiseFloor++) {
lastNoiseFloor = (noiseFloor == 0 ? sbrGrid->numNoiseFloorsPrev-1 : noiseFloor-1);
if (lastNoiseFloor < 0)
lastNoiseFloor = 0; /* first frame */
ASSERT(sbrFreq->numNoiseFloorBands <= MAX_QMF_BANDS);
if (sbrChan->deltaFlagNoise[noiseFloor] == 0) {
/* delta coding in freq */
sbrChan->noiseDataQuant[noiseFloor][0] = GetBits(bsi, 5) << dShift;
for (band = 1; band < sbrFreq->numNoiseFloorBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexFreq) << dShift;
sbrChan->noiseDataQuant[noiseFloor][band] = sf + sbrChan->noiseDataQuant[noiseFloor][band-1];
}
} else {
/* delta coding in time */
for (band = 0; band < sbrFreq->numNoiseFloorBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->noiseDataQuant[noiseFloor][band] = sf + sbrChan->noiseDataQuant[lastNoiseFloor][band];
}
}
/* skip coupling channel */
if (ch != 1 || psi->couplingFlag != 1)
DequantizeNoise(sbrFreq->numNoiseFloorBands, sbrChan->noiseDataQuant[noiseFloor], psi->noiseDataDequant[ch][noiseFloor]);
}
sbrGrid->numNoiseFloorsPrev = sbrGrid->numNoiseFloors;
}
/* dqTabCouple[i] = 2 / (1 + 2^(12 - i)), format = Q30 */
static const int dqTabCouple[25] PROGMEM = {
0x0007ff80, 0x000ffe00, 0x001ff802, 0x003fe010, 0x007f8080, 0x00fe03f8, 0x01f81f82, 0x03e0f83e,
0x07878788, 0x0e38e38e, 0x1999999a, 0x2aaaaaab, 0x40000000, 0x55555555, 0x66666666, 0x71c71c72,
0x78787878, 0x7c1f07c2, 0x7e07e07e, 0x7f01fc08, 0x7f807f80, 0x7fc01ff0, 0x7fe007fe, 0x7ff00200,
0x7ff80080,
};
/**************************************************************************************
* Function: UncoupleSBREnvelope
*
* Description: scale dequantized envelope scalefactors according to channel
* coupling rules
*
* Inputs: initialized PSInfoSBR struct including
* dequantized envelope data for left channel
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for right channel including
* quantized envelope scalefactors
*
* Outputs: dequantized envelope data for left channel (after decoupling)
* dequantized envelope data for right channel (after decoupling)
*
* Return: none
**************************************************************************************/
void UncoupleSBREnvelope(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR)
{
int env, band, nBands, scalei, E_1;
scalei = (sbrGrid->ampResFrame ? 0 : 1);
for (env = 0; env < sbrGrid->numEnv; env++) {
nBands = (sbrGrid->freqRes[env] ? sbrFreq->nHigh : sbrFreq->nLow);
psi->envDataDequantScale[1][env] = psi->envDataDequantScale[0][env]; /* same scalefactor for L and R */
for (band = 0; band < nBands; band++) {
/* clip E_1 to [0, 24] (scalefactors approach 0 or 2) */
E_1 = sbrChanR->envDataQuant[env][band] >> scalei;
if (E_1 < 0) E_1 = 0;
if (E_1 > 24) E_1 = 24;
/* envDataDequant[0] has 1 GB, so << by 2 is okay */
psi->envDataDequant[1][env][band] = MULSHIFT32(psi->envDataDequant[0][env][band], dqTabCouple[24 - E_1]) << 2;
psi->envDataDequant[0][env][band] = MULSHIFT32(psi->envDataDequant[0][env][band], dqTabCouple[E_1]) << 2;
}
}
}
/**************************************************************************************
* Function: UncoupleSBRNoise
*
* Description: scale dequantized noise floor scalefactors according to channel
* coupling rules
*
* Inputs: initialized PSInfoSBR struct including
* dequantized noise data for left channel
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel including
* quantized noise scalefactors
*
* Outputs: dequantized noise data for left channel (after decoupling)
* dequantized noise data for right channel (after decoupling)
*
* Return: none
**************************************************************************************/
void UncoupleSBRNoise(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR)
{
int noiseFloor, band, Q_1;
for (noiseFloor = 0; noiseFloor < sbrGrid->numNoiseFloors; noiseFloor++) {
for (band = 0; band < sbrFreq->numNoiseFloorBands; band++) {
/* Q_1 should be in range [0, 24] according to 4.6.18.3.6, but check to make sure */
Q_1 = sbrChanR->noiseDataQuant[noiseFloor][band];
if (Q_1 < 0) Q_1 = 0;
if (Q_1 > 24) Q_1 = 24;
/* noiseDataDequant[0] has 1 GB, so << by 2 is okay */
psi->noiseDataDequant[1][noiseFloor][band] = MULSHIFT32(psi->noiseDataDequant[0][noiseFloor][band], dqTabCouple[24 - Q_1]) << 2;
psi->noiseDataDequant[0][noiseFloor][band] = MULSHIFT32(psi->noiseDataDequant[0][noiseFloor][band], dqTabCouple[Q_1]) << 2;
}
}
}

View File

@@ -1,447 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrimdct.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrimdct.c - inverse MDCT without clipping or interleaving, for input to SBR
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: DecWindowOverlapNoClip
*
* Description: apply synthesis window, do overlap-add without clipping,
* for winSequence LONG-LONG
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
out1 = out0 + 1024 - 1;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
if (winTypeCurr == winTypePrev) {
/* cut window loads in half since current and overlap sections use same symmetric window */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
} else {
/* different windows for current and overlap parts - should still fit in registers on ARM w/o stack spill */
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
}
/**************************************************************************************
* Function: DecWindowOverlapLongStart
*
* Description: apply synthesis window, do overlap-add, without clipping
* for winSequence LONG-START
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapLongStartNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
out1 = out0 + 1024 - 1;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
in = *buf1--;
*over1-- = 0; /* Wn = 0 for n = (2047, 2046, ... 1600) */
*over0++ = in >> 1; /* Wn = 1 for n = (1024, 1025, ... 1471) */
} while (--i);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++; /* W[0], W[1], ... --> W[255], W[254], ... */
w1 = *wndCurr++; /* W[127], W[126], ... --> W[128], W[129], ... */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* Wn = short window for n = (1599, 1598, ... , 1536) */
*over0++ = MULSHIFT32(w1, in); /* Wn = short window for n = (1472, 1473, ... , 1535) */
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapLongStop
*
* Description: apply synthesis window, do overlap-add, without clipping
* for winSequence LONG-STOP
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapLongStopNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
out1 = out0 + 1024 - 1;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
/* Wn = 0 for n = (0, 1, ... 447) */
/* Wn = 1 for n = (576, 577, ... 1023) */
in = *buf0++;
f1 = in >> 1; /* scale since skipping multiply by Q31 */
in = *over0;
*out0++ = in;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (--i);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapShort
*
* Description: apply synthesis window, do overlap-add, without clipping
* for winSequence EIGHT-SHORT (does all 8 short blocks)
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapShortNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* pcm[0-447] = 0 + overlap[0-447] */
i = 448;
do {
f0 = *over0++;
f1 = *over0++;
*out0++ = f0;
*out0++ = f1;
i -= 2;
} while (i);
/* pcm[448-575] = Wp[0-127] * block0[0-127] + overlap[448-575] */
out1 = out0 + (128 - 1);
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
/* save over0/over1 for next short block, in the slots just vacated */
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
/* pcm[576-703] = Wc[128-255] * block0[128-255] + Wc[0-127] * block1[0-127] + overlap[576-703]
* pcm[704-831] = Wc[128-255] * block1[128-255] + Wc[0-127] * block2[0-127] + overlap[704-831]
* pcm[832-959] = Wc[128-255] * block2[128-255] + Wc[0-127] * block3[0-127] + overlap[832-959]
*/
for (i = 0; i < 3; i++) {
out0 += 64;
out1 = out0 + 128 - 1;
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 - 128); /* from last short block */
in += *(over0 + 0); /* from last full frame */
*out0++ = in - f0;
in = *(over1 - 128); /* from last short block */
in += *(over1 + 0); /* from last full frame */
*out1-- = in + f1;
/* save over0/over1 for next short block, in the slots just vacated */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* pcm[960-1023] = Wc[128-191] * block3[128-191] + Wc[0-63] * block4[0-63] + overlap[960-1023]
* over[0-63] = Wc[192-255] * block3[192-255] + Wc[64-127] * block4[64-127]
*/
out0 += 64;
over0 -= 832; /* points at overlap[64] */
over1 = over0 + 128 - 1; /* points at overlap[191] */
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 + 768); /* from last short block */
in += *(over0 + 896); /* from last full frame */
*out0++ = in - f0;
in = *(over1 + 768); /* from last short block */
*(over1 - 128) = in + f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* save in overlap[128-191] */
*over0++ = MULSHIFT32(w1, in); /* save in overlap[64-127] */
} while (over0 < over1);
/* over0 now points at overlap[128] */
/* over[64-191] = Wc[128-255] * block4[128-255] + Wc[0-127] * block5[0-127]
* over[192-319] = Wc[128-255] * block5[128-255] + Wc[0-127] * block6[0-127]
* over[320-447] = Wc[128-255] * block6[128-255] + Wc[0-127] * block7[0-127]
* over[448-576] = Wc[128-255] * block7[128-255]
*/
for (i = 0; i < 3; i++) {
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
/* from last short block */
*(over0 - 128) -= f0;
*(over1 - 128)+= f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* over[576-1024] = 0 */
i = 448;
over0 += 64;
do {
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
i -= 4;
} while (i);
}

View File

@@ -1,195 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrmath.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrmath.c - fixed-point math functions for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
#define Q28_2 0x20000000 /* Q28: 2.0 */
#define Q28_15 0x30000000 /* Q28: 1.5 */
#define NUM_ITER_IRN 5
/**************************************************************************************
* Function: InvRNormalized
*
* Description: use Newton's method to solve for x = 1/r
*
* Inputs: r = Q31, range = [0.5, 1) (normalize your inputs to this range)
*
* Outputs: none
*
* Return: x = Q29, range ~= [1.0, 2.0]
*
* Notes: guaranteed to converge and not overflow for any r in [0.5, 1)
*
* xn+1 = xn - f(xn)/f'(xn)
* f(x) = 1/r - x = 0 (find root)
* = 1/x - r
* f'(x) = -1/x^2
*
* so xn+1 = xn - (1/xn - r) / (-1/xn^2)
* = xn * (2 - r*xn)
*
* NUM_ITER_IRN = 2, maxDiff = 6.2500e-02 (precision of about 4 bits)
* NUM_ITER_IRN = 3, maxDiff = 3.9063e-03 (precision of about 8 bits)
* NUM_ITER_IRN = 4, maxDiff = 1.5288e-05 (precision of about 16 bits)
* NUM_ITER_IRN = 5, maxDiff = 3.0034e-08 (precision of about 24 bits)
**************************************************************************************/
int InvRNormalized(int r)
{
int i, xn, t;
/* r = [0.5, 1.0)
* 1/r = (1.0, 2.0]
* so use 1.5 as initial guess
*/
xn = Q28_15;
/* xn = xn*(2.0 - r*xn) */
for (i = NUM_ITER_IRN; i != 0; i--) {
t = MULSHIFT32(r, xn); /* Q31*Q29 = Q28 */
t = Q28_2 - t; /* Q28 */
xn = MULSHIFT32(xn, t) << 4; /* Q29*Q28 << 4 = Q29 */
}
return xn;
}
#define NUM_TERMS_RPI 5
#define LOG2_EXP_INV 0x58b90bfc /* 1/log2(e), Q31 */
/* invTab[x] = 1/(x+1), format = Q30 */
static const int invTab[NUM_TERMS_RPI] PROGMEM = {0x40000000, 0x20000000, 0x15555555, 0x10000000, 0x0ccccccd};
/**************************************************************************************
* Function: RatioPowInv
*
* Description: use Taylor (MacLaurin) series expansion to calculate (a/b) ^ (1/c)
*
* Inputs: a = [1, 64], b = [1, 64], c = [1, 64], a >= b
*
* Outputs: none
*
* Return: y = Q24, range ~= [0.015625, 64]
**************************************************************************************/
int RatioPowInv(int a, int b, int c)
{
int lna, lnb, i, p, t, y;
if (a < 1 || b < 1 || c < 1 || a > 64 || b > 64 || c > 64 || a < b)
return 0;
lna = MULSHIFT32(log2Tab[a], LOG2_EXP_INV) << 1; /* ln(a), Q28 */
lnb = MULSHIFT32(log2Tab[b], LOG2_EXP_INV) << 1; /* ln(b), Q28 */
p = (lna - lnb) / c; /* Q28 */
/* sum in Q24 */
y = (1 << 24);
t = p >> 4; /* t = p^1 * 1/1! (Q24)*/
y += t;
for (i = 2; i <= NUM_TERMS_RPI; i++) {
t = MULSHIFT32(invTab[i-1], t) << 2;
t = MULSHIFT32(p, t) << 4; /* t = p^i * 1/i! (Q24) */
y += t;
}
return y;
}
/**************************************************************************************
* Function: SqrtFix
*
* Description: use binary search to calculate sqrt(q)
*
* Inputs: q = Q30
* number of fraction bits in input
*
* Outputs: number of fraction bits in output
*
* Return: lo = Q(fBitsOut)
*
* Notes: absolute precision varies depending on fBitsIn
* normalizes input to range [0x200000000, 0x7fffffff] and takes
* floor(sqrt(input)), and sets fBitsOut appropriately
**************************************************************************************/
int SqrtFix(int q, int fBitsIn, int *fBitsOut)
{
int z, lo, hi, mid;
if (q <= 0) {
*fBitsOut = fBitsIn;
return 0;
}
/* force even fBitsIn */
z = fBitsIn & 0x01;
q >>= z;
fBitsIn -= z;
/* for max precision, normalize to [0x20000000, 0x7fffffff] */
z = (CLZ(q) - 1);
z >>= 1;
q <<= (2*z);
/* choose initial bounds */
lo = 1;
if (q >= 0x10000000)
lo = 16384; /* (int)sqrt(0x10000000) */
hi = 46340; /* (int)sqrt(0x7fffffff) */
/* do binary search with 32x32->32 multiply test */
do {
mid = (lo + hi) >> 1;
if (mid*mid > q)
hi = mid - 1;
else
lo = mid + 1;
} while (hi >= lo);
lo--;
*fBitsOut = ((fBitsIn + 2*z) >> 1);
return lo;
}

View File

@@ -1,527 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrqmf.c,v 1.2 2005/05/19 20:45:20 jrecker 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
*
* sbrqmf.c - analysis and synthesis QMF filters for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/* PreMultiply64() table
* format = Q30
* reordered for sequential access
*
* for (i = 0; i < 64/4; i++) {
* angle = (i + 0.25) * M_PI / nmdct;
* x = (cos(angle) + sin(angle));
* x = sin(angle);
*
* angle = (nmdct/2 - 1 - i + 0.25) * M_PI / nmdct;
* x = (cos(angle) + sin(angle));
* x = sin(angle);
* }
*/
static const int cos4sin4tab64[64] PROGMEM = {
0x40c7d2bd, 0x00c90e90, 0x424ff28f, 0x3ff4e5e0, 0x43cdd89a, 0x03ecadcf, 0x454149fc, 0x3fc395f9,
0x46aa0d6d, 0x070de172, 0x4807eb4b, 0x3f6af2e3, 0x495aada2, 0x0a2abb59, 0x4aa22036, 0x3eeb3347,
0x4bde1089, 0x0d415013, 0x4d0e4de2, 0x3e44a5ef, 0x4e32a956, 0x104fb80e, 0x4f4af5d1, 0x3d77b192,
0x50570819, 0x135410c3, 0x5156b6d9, 0x3c84d496, 0x5249daa2, 0x164c7ddd, 0x53304df6, 0x3b6ca4c4,
0x5409ed4b, 0x19372a64, 0x54d69714, 0x3a2fcee8, 0x55962bc0, 0x1c1249d8, 0x56488dc5, 0x38cf1669,
0x56eda1a0, 0x1edc1953, 0x57854ddd, 0x374b54ce, 0x580f7b19, 0x2192e09b, 0x588c1404, 0x35a5793c,
0x58fb0568, 0x2434f332, 0x595c3e2a, 0x33de87de, 0x59afaf4c, 0x26c0b162, 0x59f54bee, 0x31f79948,
0x5a2d0957, 0x29348937, 0x5a56deec, 0x2ff1d9c7, 0x5a72c63b, 0x2b8ef77d, 0x5a80baf6, 0x2dce88aa,
};
/* PostMultiply64() table
* format = Q30
* reordered for sequential access
*
* for (i = 0; i <= (32/2); i++) {
* angle = i * M_PI / 64;
* x = (cos(angle) + sin(angle));
* x = sin(angle);
* }
*/
static const int cos1sin1tab64[34] PROGMEM = {
0x40000000, 0x00000000, 0x43103085, 0x0323ecbe, 0x45f704f7, 0x0645e9af, 0x48b2b335, 0x09640837,
0x4b418bbe, 0x0c7c5c1e, 0x4da1fab5, 0x0f8cfcbe, 0x4fd288dc, 0x1294062f, 0x51d1dc80, 0x158f9a76,
0x539eba45, 0x187de2a7, 0x553805f2, 0x1b5d100a, 0x569cc31b, 0x1e2b5d38, 0x57cc15bc, 0x20e70f32,
0x58c542c5, 0x238e7673, 0x5987b08a, 0x261feffa, 0x5a12e720, 0x2899e64a, 0x5a6690ae, 0x2afad269,
0x5a82799a, 0x2d413ccd,
};
/**************************************************************************************
* Function: PreMultiply64
*
* Description: pre-twiddle stage of 64-point DCT-IV
*
* Inputs: buffer of 64 samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out, gains 2 int bits
* gbOut = gbIn + 1
* output is limited to sqrt(2)/2 plus GB in full GB
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
static void PreMultiply64(int *zbuf1)
{
int i, ar1, ai1, ar2, ai2, z1, z2;
int t, cms2, cps2a, sin2a, cps2b, sin2b;
int *zbuf2;
const int *csptr;
zbuf2 = zbuf1 + 64 - 1;
csptr = cos4sin4tab64;
/* whole thing should fit in registers - verify that compiler does this */
for (i = 64 >> 2; i != 0; i--) {
/* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin) */
cps2a = *csptr++;
sin2a = *csptr++;
cps2b = *csptr++;
sin2b = *csptr++;
ar1 = *(zbuf1 + 0);
ai2 = *(zbuf1 + 1);
ai1 = *(zbuf2 + 0);
ar2 = *(zbuf2 - 1);
/* gain 2 ints bit from MULSHIFT32 by Q30
* max per-sample gain (ignoring implicit scaling) = MAX(sin(angle)+cos(angle)) = 1.414
* i.e. gain 1 GB since worst case is sin(angle) = cos(angle) = 0.707 (Q30), gain 2 from
* extra sign bits, and eat one in adding
*/
t = MULSHIFT32(sin2a, ar1 + ai1);
z2 = MULSHIFT32(cps2a, ai1) - t;
cms2 = cps2a - 2*sin2a;
z1 = MULSHIFT32(cms2, ar1) + t;
*zbuf1++ = z1; /* cos*ar1 + sin*ai1 */
*zbuf1++ = z2; /* cos*ai1 - sin*ar1 */
t = MULSHIFT32(sin2b, ar2 + ai2);
z2 = MULSHIFT32(cps2b, ai2) - t;
cms2 = cps2b - 2*sin2b;
z1 = MULSHIFT32(cms2, ar2) + t;
*zbuf2-- = z2; /* cos*ai2 - sin*ar2 */
*zbuf2-- = z1; /* cos*ar2 + sin*ai2 */
}
}
/**************************************************************************************
* Function: PostMultiply64
*
* Description: post-twiddle stage of 64-point type-IV DCT
*
* Inputs: buffer of 64 samples
* number of output samples to calculate
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out, gains 2 int bits
* gbOut = gbIn + 1
* output is limited to sqrt(2)/2 plus GB in full GB
* nSampsOut is rounded up to next multiple of 4, since we calculate
* 4 samples per loop
**************************************************************************************/
static void PostMultiply64(int *fft1, int nSampsOut)
{
int i, ar1, ai1, ar2, ai2;
int t, cms2, cps2, sin2;
int *fft2;
const int *csptr;
csptr = cos1sin1tab64;
fft2 = fft1 + 64 - 1;
/* load coeffs for first pass
* cps2 = (cos+sin)/2, sin2 = sin/2, cms2 = (cos-sin)/2
*/
cps2 = *csptr++;
sin2 = *csptr++;
cms2 = cps2 - 2*sin2;
for (i = (nSampsOut + 3) >> 2; i != 0; i--) {
ar1 = *(fft1 + 0);
ai1 = *(fft1 + 1);
ar2 = *(fft2 - 1);
ai2 = *(fft2 + 0);
/* gain 2 int bits (multiplying by Q30), max gain = sqrt(2) */
t = MULSHIFT32(sin2, ar1 + ai1);
*fft2-- = t - MULSHIFT32(cps2, ai1);
*fft1++ = t + MULSHIFT32(cms2, ar1);
cps2 = *csptr++;
sin2 = *csptr++;
ai2 = -ai2;
t = MULSHIFT32(sin2, ar2 + ai2);
*fft2-- = t - MULSHIFT32(cps2, ai2);
cms2 = cps2 - 2*sin2;
*fft1++ = t + MULSHIFT32(cms2, ar2);
}
}
/**************************************************************************************
* Function: QMFAnalysisConv
*
* Description: convolution kernel for analysis QMF
*
* Inputs: pointer to coefficient table, reordered for sequential access
* delay buffer of size 32*10 = 320 real-valued PCM samples
* index for delay ring buffer (range = [0, 9])
*
* Outputs: 64 consecutive 32-bit samples
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrqmfak.s when building for ARM!
**************************************************************************************/
#if (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM))
#ifdef __cplusplus
extern "C"
#endif
void QMFAnalysisConv(int *cTab, int *delay, int dIdx, int *uBuf);
#else
void QMFAnalysisConv(int *cTab, int *delay, int dIdx, int *uBuf)
{
int k, dOff;
int *cPtr0, *cPtr1;
U64 u64lo, u64hi;
dOff = dIdx*32 + 31;
cPtr0 = cTab;
cPtr1 = cTab + 33*5 - 1;
/* special first pass since we need to flip sign to create cTab[384], cTab[512] */
u64lo.w64 = 0;
u64hi.w64 = 0;
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, -(*cPtr1--), delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, -(*cPtr1--), delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
uBuf[0] = u64lo.r.hi32;
uBuf[32] = u64hi.r.hi32;
uBuf++;
dOff--;
/* max gain for any sample in uBuf, after scaling by cTab, ~= 0.99
* so we can just sum the uBuf values with no overflow problems
*/
for (k = 1; k <= 31; k++) {
u64lo.w64 = 0;
u64hi.w64 = 0;
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
uBuf[0] = u64lo.r.hi32;
uBuf[32] = u64hi.r.hi32;
uBuf++;
dOff--;
}
}
#endif
/**************************************************************************************
* Function: QMFAnalysis
*
* Description: 32-subband analysis QMF (4.6.18.4.1)
*
* Inputs: 32 consecutive samples of decoded 32-bit PCM, format = Q(fBitsIn)
* delay buffer of size 32*10 = 320 PCM samples
* number of fraction bits in input PCM
* index for delay ring buffer (range = [0, 9])
* number of subbands to calculate (range = [0, 32])
*
* Outputs: qmfaBands complex subband samples, format = Q(FBITS_OUT_QMFA)
* updated delay buffer
* updated delay index
*
* Return: guard bit mask
*
* Notes: output stored as RE{X0}, IM{X0}, RE{X1}, IM{X1}, ... RE{X31}, IM{X31}
* output stored in int buffer of size 64*2 = 128
* (zero-filled from XBuf[2*qmfaBands] to XBuf[127])
**************************************************************************************/
int QMFAnalysis(int *inbuf, int *delay, int *XBuf, int fBitsIn, int *delayIdx, int qmfaBands)
{
int n, y, shift, gbMask;
int *delayPtr, *uBuf, *tBuf;
/* use XBuf[128] as temp buffer for reordering */
uBuf = XBuf; /* first 64 samples */
tBuf = XBuf + 64; /* second 64 samples */
/* overwrite oldest PCM with new PCM
* delay[n] has 1 GB after shifting (either << or >>)
*/
delayPtr = delay + (*delayIdx * 32);
if (fBitsIn > FBITS_IN_QMFA) {
shift = MIN(fBitsIn - FBITS_IN_QMFA, 31);
for (n = 32; n != 0; n--) {
y = (*inbuf) >> shift;
inbuf++;
*delayPtr++ = y;
}
} else {
shift = MIN(FBITS_IN_QMFA - fBitsIn, 30);
for (n = 32; n != 0; n--) {
y = *inbuf++;
CLIP_2N_SHIFT30(y, shift);
*delayPtr++ = y;
}
}
QMFAnalysisConv((int *)cTabA, delay, *delayIdx, uBuf);
/* uBuf has at least 2 GB right now (1 from clipping to Q(FBITS_IN_QMFA), one from
* the scaling by cTab (MULSHIFT32(*delayPtr--, *cPtr++), with net gain of < 1.0)
* TODO - fuse with QMFAnalysisConv to avoid separate reordering
*/
tBuf[2*0 + 0] = uBuf[0];
tBuf[2*0 + 1] = uBuf[1];
for (n = 1; n < 31; n++) {
tBuf[2*n + 0] = -uBuf[64-n];
tBuf[2*n + 1] = uBuf[n+1];
}
tBuf[2*31 + 1] = uBuf[32];
tBuf[2*31 + 0] = -uBuf[33];
/* fast in-place DCT-IV - only need 2*qmfaBands output samples */
PreMultiply64(tBuf); /* 2 GB in, 3 GB out */
FFT32C(tBuf); /* 3 GB in, 1 GB out */
PostMultiply64(tBuf, qmfaBands*2); /* 1 GB in, 2 GB out */
/* TODO - roll into PostMultiply (if enough registers) */
gbMask = 0;
for (n = 0; n < qmfaBands; n++) {
XBuf[2*n+0] = tBuf[ n + 0]; /* implicit scaling of 2 in our output Q format */
gbMask |= FASTABS(XBuf[2*n+0]);
XBuf[2*n+1] = -tBuf[63 - n];
gbMask |= FASTABS(XBuf[2*n+1]);
}
/* fill top section with zeros for HF generation */
for ( ; n < 64; n++) {
XBuf[2*n+0] = 0;
XBuf[2*n+1] = 0;
}
*delayIdx = (*delayIdx == NUM_QMF_DELAY_BUFS - 1 ? 0 : *delayIdx + 1);
/* minimum of 2 GB in output */
return gbMask;
}
/* lose FBITS_LOST_DCT4_64 in DCT4, gain 6 for implicit scaling by 1/64, lose 1 for cTab multiply (Q31) */
#define FBITS_OUT_QMFS (FBITS_IN_QMFS - FBITS_LOST_DCT4_64 + 6 - 1)
#define RND_VAL (1 << (FBITS_OUT_QMFS-1))
/**************************************************************************************
* Function: QMFSynthesisConv
*
* Description: final convolution kernel for synthesis QMF
*
* Inputs: pointer to coefficient table, reordered for sequential access
* delay buffer of size 64*10 = 640 complex samples (1280 ints)
* index for delay ring buffer (range = [0, 9])
* number of QMF subbands to process (range = [0, 64])
* number of channels
*
* Outputs: 64 consecutive 16-bit PCM samples, interleaved by factor of nChans
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrqmfsk.s when building for ARM!
**************************************************************************************/
#if (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM))
#ifdef __cplusplus
extern "C"
#endif
void QMFSynthesisConv(int *cPtr, int *delay, int dIdx, short *outbuf, int nChans);
#else
void QMFSynthesisConv(int *cPtr, int *delay, int dIdx, short *outbuf, int nChans)
{
int k, dOff0, dOff1;
U64 sum64;
dOff0 = (dIdx)*128;
dOff1 = dOff0 - 1;
if (dOff1 < 0)
dOff1 += 1280;
/* scaling note: total gain of coefs (cPtr[0]-cPtr[9] for any k) is < 2.0, so 1 GB in delay values is adequate */
for (k = 0; k <= 63; k++) {
sum64.w64 = 0;
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
dOff0++;
dOff1--;
*outbuf = CLIPTOSHORT((sum64.r.hi32 + RND_VAL) >> FBITS_OUT_QMFS);
outbuf += nChans;
}
}
#endif
/**************************************************************************************
* Function: QMFSynthesis
*
* Description: 64-subband synthesis QMF (4.6.18.4.2)
*
* Inputs: 64 consecutive complex subband QMF samples, format = Q(FBITS_IN_QMFS)
* delay buffer of size 64*10 = 640 complex samples (1280 ints)
* index for delay ring buffer (range = [0, 9])
* number of QMF subbands to process (range = [0, 64])
* number of channels
*
* Outputs: 64 consecutive 16-bit PCM samples, interleaved by factor of nChans
* updated delay buffer
* updated delay index
*
* Return: none
*
* Notes: assumes MIN_GBITS_IN_QMFS guard bits in input, either from
* QMFAnalysis (if upsampling only) or from MapHF (if SBR on)
**************************************************************************************/
void QMFSynthesis(int *inbuf, int *delay, int *delayIdx, int qmfsBands, short *outbuf, int nChans)
{
int n, a0, a1, b0, b1, dOff0, dOff1, dIdx;
int *tBufLo, *tBufHi;
dIdx = *delayIdx;
tBufLo = delay + dIdx*128 + 0;
tBufHi = delay + dIdx*128 + 127;
/* reorder inputs to DCT-IV, only use first qmfsBands (complex) samples
* TODO - fuse with PreMultiply64 to avoid separate reordering steps
*/
for (n = 0; n < qmfsBands >> 1; n++) {
a0 = *inbuf++;
b0 = *inbuf++;
a1 = *inbuf++;
b1 = *inbuf++;
*tBufLo++ = a0;
*tBufLo++ = a1;
*tBufHi-- = b0;
*tBufHi-- = b1;
}
if (qmfsBands & 0x01) {
a0 = *inbuf++;
b0 = *inbuf++;
*tBufLo++ = a0;
*tBufHi-- = b0;
*tBufLo++ = 0;
*tBufHi-- = 0;
n++;
}
for ( ; n < 32; n++) {
*tBufLo++ = 0;
*tBufHi-- = 0;
*tBufLo++ = 0;
*tBufHi-- = 0;
}
tBufLo = delay + dIdx*128 + 0;
tBufHi = delay + dIdx*128 + 64;
/* 2 GB in, 3 GB out */
PreMultiply64(tBufLo);
PreMultiply64(tBufHi);
/* 3 GB in, 1 GB out */
FFT32C(tBufLo);
FFT32C(tBufHi);
/* 1 GB in, 2 GB out */
PostMultiply64(tBufLo, 64);
PostMultiply64(tBufHi, 64);
/* could fuse with PostMultiply64 to avoid separate pass */
dOff0 = dIdx*128;
dOff1 = dIdx*128 + 64;
for (n = 32; n != 0; n--) {
a0 = (*tBufLo++);
a1 = (*tBufLo++);
b0 = (*tBufHi++);
b1 = -(*tBufHi++);
delay[dOff0++] = (b0 - a0);
delay[dOff0++] = (b1 - a1);
delay[dOff1++] = (b0 + a0);
delay[dOff1++] = (b1 + a1);
}
QMFSynthesisConv((int *)cTabS, delay, dIdx, outbuf, nChans);
*delayIdx = (*delayIdx == NUM_QMF_DELAY_BUFS - 1 ? 0 : *delayIdx + 1);
}

View File

@@ -1,575 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrside.c,v 1.2 2005/05/24 16:01:55 albertofloyd Exp $
*
* Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file,
* are subject to the current version of the RealNetworks Public
* Source License (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the current version of the RealNetworks Community
* Source License (the "RCSL") available at
* http://www.helixcommunity.org/content/rcsl, in which case the RCSL
* will apply. You may also obtain the license terms directly from
* RealNetworks. You may not use this file except in compliance with
* the RPSL or, if you have a valid RCSL with RealNetworks applicable
* to this file, the RCSL. Please see the applicable RPSL or RCSL for
* the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the
* portions it created.
*
* This file, and the files included with this file, is distributed
* and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
* ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/**************************************************************************************
* Fixed-point HE-AAC decoder
* Jon Recker (jrecker@real.com)
* February 2005
*
* sbrside.c - functions for unpacking side info from SBR bitstream
**************************************************************************************/
#include "sbr.h"
/**************************************************************************************
* Function: GetSampRateIdx
*
* Description: get index of given sample rate
*
* Inputs: sample rate (in Hz)
*
* Outputs: none
*
* Return: index of sample rate (table 1.15 in 14496-3:2001(E))
* -1 if sample rate not found in table
**************************************************************************************/
int GetSampRateIdx(int sampRate)
{
int idx;
for (idx = 0; idx < NUM_SAMPLE_RATES; idx++) {
if (sampRate == sampRateTab[idx])
return idx;
}
return -1;
}
/**************************************************************************************
* Function: UnpackSBRHeader
*
* Description: unpack SBR header (table 4.56)
*
* Inputs: BitStreamInfo struct pointing to start of SBR header
*
* Outputs: initialized SBRHeader struct for this SCE/CPE block
*
* Return: non-zero if frame reset is triggered, zero otherwise
**************************************************************************************/
int UnpackSBRHeader(BitStreamInfo *bsi, SBRHeader *sbrHdr)
{
SBRHeader sbrHdrPrev;
/* save previous values so we know whether to reset decoder */
sbrHdrPrev.startFreq = sbrHdr->startFreq;
sbrHdrPrev.stopFreq = sbrHdr->stopFreq;
sbrHdrPrev.freqScale = sbrHdr->freqScale;
sbrHdrPrev.alterScale = sbrHdr->alterScale;
sbrHdrPrev.crossOverBand = sbrHdr->crossOverBand;
sbrHdrPrev.noiseBands = sbrHdr->noiseBands;
sbrHdr->ampRes = GetBits(bsi, 1);
sbrHdr->startFreq = GetBits(bsi, 4);
sbrHdr->stopFreq = GetBits(bsi, 4);
sbrHdr->crossOverBand = GetBits(bsi, 3);
sbrHdr->resBitsHdr = GetBits(bsi, 2);
sbrHdr->hdrExtra1 = GetBits(bsi, 1);
sbrHdr->hdrExtra2 = GetBits(bsi, 1);
if (sbrHdr->hdrExtra1) {
sbrHdr->freqScale = GetBits(bsi, 2);
sbrHdr->alterScale = GetBits(bsi, 1);
sbrHdr->noiseBands = GetBits(bsi, 2);
} else {
/* defaults */
sbrHdr->freqScale = 2;
sbrHdr->alterScale = 1;
sbrHdr->noiseBands = 2;
}
if (sbrHdr->hdrExtra2) {
sbrHdr->limiterBands = GetBits(bsi, 2);
sbrHdr->limiterGains = GetBits(bsi, 2);
sbrHdr->interpFreq = GetBits(bsi, 1);
sbrHdr->smoothMode = GetBits(bsi, 1);
} else {
/* defaults */
sbrHdr->limiterBands = 2;
sbrHdr->limiterGains = 2;
sbrHdr->interpFreq = 1;
sbrHdr->smoothMode = 1;
}
sbrHdr->count++;
/* if any of these have changed from previous frame, reset the SBR module */
if (sbrHdr->startFreq != sbrHdrPrev.startFreq || sbrHdr->stopFreq != sbrHdrPrev.stopFreq ||
sbrHdr->freqScale != sbrHdrPrev.freqScale || sbrHdr->alterScale != sbrHdrPrev.alterScale ||
sbrHdr->crossOverBand != sbrHdrPrev.crossOverBand || sbrHdr->noiseBands != sbrHdrPrev.noiseBands
)
return -1;
else
return 0;
}
/* cLog2[i] = ceil(log2(i)) (disregard i == 0) */
static const unsigned char cLog2[9] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
/**************************************************************************************
* Function: UnpackSBRGrid
*
* Description: unpack SBR grid (table 4.62)
*
* Inputs: BitStreamInfo struct pointing to start of SBR grid
* initialized SBRHeader struct for this SCE/CPE block
*
* Outputs: initialized SBRGrid struct for this channel
*
* Return: none
**************************************************************************************/
static void UnpackSBRGrid(BitStreamInfo *bsi, SBRHeader *sbrHdr, SBRGrid *sbrGrid)
{
int numEnvRaw, env, rel, pBits, border, middleBorder=0;
unsigned char relBordLead[MAX_NUM_ENV], relBordTrail[MAX_NUM_ENV];
unsigned char relBorder0[3], relBorder1[3], relBorder[3];
unsigned char numRelBorder0, numRelBorder1, numRelBorder, numRelLead=0, numRelTrail;
unsigned char absBordLead=0, absBordTrail=0, absBorder;
sbrGrid->ampResFrame = sbrHdr->ampRes;
sbrGrid->frameClass = GetBits(bsi, 2);
switch (sbrGrid->frameClass) {
case SBR_GRID_FIXFIX:
numEnvRaw = GetBits(bsi, 2);
sbrGrid->numEnv = (1 << numEnvRaw);
if (sbrGrid->numEnv == 1)
sbrGrid->ampResFrame = 0;
ASSERT(sbrGrid->numEnv == 1 || sbrGrid->numEnv == 2 || sbrGrid->numEnv == 4);
sbrGrid->freqRes[0] = GetBits(bsi, 1);
for (env = 1; env < sbrGrid->numEnv; env++)
sbrGrid->freqRes[env] = sbrGrid->freqRes[0];
absBordLead = 0;
absBordTrail = NUM_TIME_SLOTS;
numRelLead = sbrGrid->numEnv - 1;
numRelTrail = 0;
/* numEnv = 1, 2, or 4 */
if (sbrGrid->numEnv == 1) border = NUM_TIME_SLOTS / 1;
else if (sbrGrid->numEnv == 2) border = NUM_TIME_SLOTS / 2;
else border = NUM_TIME_SLOTS / 4;
for (rel = 0; rel < numRelLead; rel++)
relBordLead[rel] = border;
middleBorder = (sbrGrid->numEnv >> 1);
break;
case SBR_GRID_FIXVAR:
absBorder = GetBits(bsi, 2) + NUM_TIME_SLOTS;
numRelBorder = GetBits(bsi, 2);
sbrGrid->numEnv = numRelBorder + 1;
for (rel = 0; rel < numRelBorder; rel++)
relBorder[rel] = 2*GetBits(bsi, 2) + 2;
pBits = cLog2[sbrGrid->numEnv + 1];
sbrGrid->pointer = GetBits(bsi, pBits);
for (env = sbrGrid->numEnv - 1; env >= 0; env--)
sbrGrid->freqRes[env] = GetBits(bsi, 1);
absBordLead = 0;
absBordTrail = absBorder;
numRelLead = 0;
numRelTrail = numRelBorder;
for (rel = 0; rel < numRelTrail; rel++)
relBordTrail[rel] = relBorder[rel];
if (sbrGrid->pointer > 1) middleBorder = sbrGrid->numEnv + 1 - sbrGrid->pointer;
else middleBorder = sbrGrid->numEnv - 1;
break;
case SBR_GRID_VARFIX:
absBorder = GetBits(bsi, 2);
numRelBorder = GetBits(bsi, 2);
sbrGrid->numEnv = numRelBorder + 1;
for (rel = 0; rel < numRelBorder; rel++)
relBorder[rel] = 2*GetBits(bsi, 2) + 2;
pBits = cLog2[sbrGrid->numEnv + 1];
sbrGrid->pointer = GetBits(bsi, pBits);
for (env = 0; env < sbrGrid->numEnv; env++)
sbrGrid->freqRes[env] = GetBits(bsi, 1);
absBordLead = absBorder;
absBordTrail = NUM_TIME_SLOTS;
numRelLead = numRelBorder;
numRelTrail = 0;
for (rel = 0; rel < numRelLead; rel++)
relBordLead[rel] = relBorder[rel];
if (sbrGrid->pointer == 0) middleBorder = 1;
else if (sbrGrid->pointer == 1) middleBorder = sbrGrid->numEnv - 1;
else middleBorder = sbrGrid->pointer - 1;
break;
case SBR_GRID_VARVAR:
absBordLead = GetBits(bsi, 2); /* absBorder0 */
absBordTrail = GetBits(bsi, 2) + NUM_TIME_SLOTS; /* absBorder1 */
numRelBorder0 = GetBits(bsi, 2);
numRelBorder1 = GetBits(bsi, 2);
sbrGrid->numEnv = numRelBorder0 + numRelBorder1 + 1;
ASSERT(sbrGrid->numEnv <= 5);
for (rel = 0; rel < numRelBorder0; rel++)
relBorder0[rel] = 2*GetBits(bsi, 2) + 2;
for (rel = 0; rel < numRelBorder1; rel++)
relBorder1[rel] = 2*GetBits(bsi, 2) + 2;
pBits = cLog2[numRelBorder0 + numRelBorder1 + 2];
sbrGrid->pointer = GetBits(bsi, pBits);
for (env = 0; env < sbrGrid->numEnv; env++)
sbrGrid->freqRes[env] = GetBits(bsi, 1);
numRelLead = numRelBorder0;
numRelTrail = numRelBorder1;
for (rel = 0; rel < numRelLead; rel++)
relBordLead[rel] = relBorder0[rel];
for (rel = 0; rel < numRelTrail; rel++)
relBordTrail[rel] = relBorder1[rel];
if (sbrGrid->pointer > 1) middleBorder = sbrGrid->numEnv + 1 - sbrGrid->pointer;
else middleBorder = sbrGrid->numEnv - 1;
break;
}
/* build time border vector */
sbrGrid->envTimeBorder[0] = absBordLead * SAMPLES_PER_SLOT;
rel = 0;
border = absBordLead;
for (env = 1; env <= numRelLead; env++) {
border += relBordLead[rel++];
sbrGrid->envTimeBorder[env] = border * SAMPLES_PER_SLOT;
}
rel = 0;
border = absBordTrail;
for (env = sbrGrid->numEnv - 1; env > numRelLead; env--) {
border -= relBordTrail[rel++];
sbrGrid->envTimeBorder[env] = border * SAMPLES_PER_SLOT;
}
sbrGrid->envTimeBorder[sbrGrid->numEnv] = absBordTrail * SAMPLES_PER_SLOT;
if (sbrGrid->numEnv > 1) {
sbrGrid->numNoiseFloors = 2;
sbrGrid->noiseTimeBorder[0] = sbrGrid->envTimeBorder[0];
sbrGrid->noiseTimeBorder[1] = sbrGrid->envTimeBorder[middleBorder];
sbrGrid->noiseTimeBorder[2] = sbrGrid->envTimeBorder[sbrGrid->numEnv];
} else {
sbrGrid->numNoiseFloors = 1;
sbrGrid->noiseTimeBorder[0] = sbrGrid->envTimeBorder[0];
sbrGrid->noiseTimeBorder[1] = sbrGrid->envTimeBorder[1];
}
}
/**************************************************************************************
* Function: UnpackDeltaTimeFreq
*
* Description: unpack time/freq flags for delta coding of SBR envelopes (table 4.63)
*
* Inputs: BitStreamInfo struct pointing to start of dt/df flags
* number of envelopes
* number of noise floors
*
* Outputs: delta flags for envelope and noise floors
*
* Return: none
**************************************************************************************/
static void UnpackDeltaTimeFreq(BitStreamInfo *bsi, int numEnv, unsigned char *deltaFlagEnv,
int numNoiseFloors, unsigned char *deltaFlagNoise)
{
int env, noiseFloor;
for (env = 0; env < numEnv; env++)
deltaFlagEnv[env] = GetBits(bsi, 1);
for (noiseFloor = 0; noiseFloor < numNoiseFloors; noiseFloor++)
deltaFlagNoise[noiseFloor] = GetBits(bsi, 1);
}
/**************************************************************************************
* Function: UnpackInverseFilterMode
*
* Description: unpack invf flags for chirp factor calculation (table 4.64)
*
* Inputs: BitStreamInfo struct pointing to start of invf flags
* number of noise floor bands
*
* Outputs: invf flags for noise floor bands
*
* Return: none
**************************************************************************************/
static void UnpackInverseFilterMode(BitStreamInfo *bsi, int numNoiseFloorBands, unsigned char *mode)
{
int n;
for (n = 0; n < numNoiseFloorBands; n++)
mode[n] = GetBits(bsi, 2);
}
/**************************************************************************************
* Function: UnpackSinusoids
*
* Description: unpack sinusoid (harmonic) flags for each SBR subband (table 4.67)
*
* Inputs: BitStreamInfo struct pointing to start of sinusoid flags
* number of high resolution SBR subbands (nHigh)
*
* Outputs: sinusoid flags for each SBR subband, zero-filled above nHigh
*
* Return: none
**************************************************************************************/
static void UnpackSinusoids(BitStreamInfo *bsi, int nHigh, int addHarmonicFlag, unsigned char *addHarmonic)
{
int n;
n = 0;
if (addHarmonicFlag) {
for ( ; n < nHigh; n++)
addHarmonic[n] = GetBits(bsi, 1);
}
/* zero out unused bands */
for ( ; n < MAX_QMF_BANDS; n++)
addHarmonic[n] = 0;
}
/**************************************************************************************
* Function: CopyCouplingGrid
*
* Description: copy grid parameters from left to right for channel coupling
*
* Inputs: initialized SBRGrid struct for left channel
*
* Outputs: initialized SBRGrid struct for right channel
*
* Return: none
**************************************************************************************/
static void CopyCouplingGrid(SBRGrid *sbrGridLeft, SBRGrid *sbrGridRight)
{
int env, noiseFloor;
sbrGridRight->frameClass = sbrGridLeft->frameClass;
sbrGridRight->ampResFrame = sbrGridLeft->ampResFrame;
sbrGridRight->pointer = sbrGridLeft->pointer;
sbrGridRight->numEnv = sbrGridLeft->numEnv;
for (env = 0; env < sbrGridLeft->numEnv; env++) {
sbrGridRight->envTimeBorder[env] = sbrGridLeft->envTimeBorder[env];
sbrGridRight->freqRes[env] = sbrGridLeft->freqRes[env];
}
sbrGridRight->envTimeBorder[env] = sbrGridLeft->envTimeBorder[env]; /* borders are [0, numEnv] inclusive */
sbrGridRight->numNoiseFloors = sbrGridLeft->numNoiseFloors;
for (noiseFloor = 0; noiseFloor <= sbrGridLeft->numNoiseFloors; noiseFloor++)
sbrGridRight->noiseTimeBorder[noiseFloor] = sbrGridLeft->noiseTimeBorder[noiseFloor];
/* numEnvPrev, numNoiseFloorsPrev, freqResPrev are updated in DecodeSBREnvelope() and DecodeSBRNoise() */
}
/**************************************************************************************
* Function: CopyCouplingInverseFilterMode
*
* Description: copy invf flags from left to right for channel coupling
*
* Inputs: invf flags for left channel
* number of noise floor bands
*
* Outputs: invf flags for right channel
*
* Return: none
**************************************************************************************/
static void CopyCouplingInverseFilterMode(int numNoiseFloorBands, unsigned char *modeLeft, unsigned char *modeRight)
{
int band;
for (band = 0; band < numNoiseFloorBands; band++)
modeRight[band] = modeLeft[band];
}
/**************************************************************************************
* Function: UnpackSBRSingleChannel
*
* Description: unpack sideband info (grid, delta flags, invf flags, envelope and
* noise floor configuration, sinusoids) for a single channel
*
* Inputs: BitStreamInfo struct pointing to start of sideband info
* initialized PSInfoSBR struct (after parsing SBR header and building
* frequency tables)
* base output channel (range = [0, nChans-1])
*
* Outputs: updated PSInfoSBR struct (SBRGrid and SBRChan)
*
* Return: none
**************************************************************************************/
void UnpackSBRSingleChannel(BitStreamInfo *bsi, PSInfoSBR *psi, int chBase)
{
int bitsLeft;
SBRHeader *sbrHdr = &(psi->sbrHdr[chBase]);
SBRGrid *sbrGridL = &(psi->sbrGrid[chBase+0]);
SBRFreq *sbrFreq = &(psi->sbrFreq[chBase]);
SBRChan *sbrChanL = &(psi->sbrChan[chBase+0]);
psi->dataExtra = GetBits(bsi, 1);
if (psi->dataExtra)
psi->resBitsData = GetBits(bsi, 4);
UnpackSBRGrid(bsi, sbrHdr, sbrGridL);
UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);
DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
sbrChanL->addHarmonicFlag[1] = GetBits(bsi, 1);
UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanL->addHarmonicFlag[1], sbrChanL->addHarmonic[1]);
psi->extendedDataPresent = GetBits(bsi, 1);
if (psi->extendedDataPresent) {
psi->extendedDataSize = GetBits(bsi, 4);
if (psi->extendedDataSize == 15)
psi->extendedDataSize += GetBits(bsi, 8);
bitsLeft = 8 * psi->extendedDataSize;
/* get ID, unpack extension info, do whatever is necessary with it... */
while (bitsLeft > 0) {
GetBits(bsi, 8);
bitsLeft -= 8;
}
}
}
/**************************************************************************************
* Function: UnpackSBRChannelPair
*
* Description: unpack sideband info (grid, delta flags, invf flags, envelope and
* noise floor configuration, sinusoids) for a channel pair
*
* Inputs: BitStreamInfo struct pointing to start of sideband info
* initialized PSInfoSBR struct (after parsing SBR header and building
* frequency tables)
* base output channel (range = [0, nChans-1])
*
* Outputs: updated PSInfoSBR struct (SBRGrid and SBRChan for both channels)
*
* Return: none
**************************************************************************************/
void UnpackSBRChannelPair(BitStreamInfo *bsi, PSInfoSBR *psi, int chBase)
{
int bitsLeft;
SBRHeader *sbrHdr = &(psi->sbrHdr[chBase]);
SBRGrid *sbrGridL = &(psi->sbrGrid[chBase+0]), *sbrGridR = &(psi->sbrGrid[chBase+1]);
SBRFreq *sbrFreq = &(psi->sbrFreq[chBase]);
SBRChan *sbrChanL = &(psi->sbrChan[chBase+0]), *sbrChanR = &(psi->sbrChan[chBase+1]);
psi->dataExtra = GetBits(bsi, 1);
if (psi->dataExtra) {
psi->resBitsData = GetBits(bsi, 4);
psi->resBitsData = GetBits(bsi, 4);
}
psi->couplingFlag = GetBits(bsi, 1);
if (psi->couplingFlag) {
UnpackSBRGrid(bsi, sbrHdr, sbrGridL);
CopyCouplingGrid(sbrGridL, sbrGridR);
UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);
UnpackDeltaTimeFreq(bsi, sbrGridR->numEnv, sbrChanR->deltaFlagEnv, sbrGridR->numNoiseFloors, sbrChanR->deltaFlagNoise);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);
CopyCouplingInverseFilterMode(sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1], sbrChanR->invfMode[1]);
DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBREnvelope(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
DecodeSBRNoise(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
/* pass RIGHT sbrChan struct */
UncoupleSBREnvelope(psi, sbrGridL, sbrFreq, sbrChanR);
UncoupleSBRNoise(psi, sbrGridL, sbrFreq, sbrChanR);
} else {
UnpackSBRGrid(bsi, sbrHdr, sbrGridL);
UnpackSBRGrid(bsi, sbrHdr, sbrGridR);
UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);
UnpackDeltaTimeFreq(bsi, sbrGridR->numEnv, sbrChanR->deltaFlagEnv, sbrGridR->numNoiseFloors, sbrChanR->deltaFlagNoise);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanR->invfMode[1]);
DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBREnvelope(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBRNoise(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
}
sbrChanL->addHarmonicFlag[1] = GetBits(bsi, 1);
UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanL->addHarmonicFlag[1], sbrChanL->addHarmonic[1]);
sbrChanR->addHarmonicFlag[1] = GetBits(bsi, 1);
UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanR->addHarmonicFlag[1], sbrChanR->addHarmonic[1]);
psi->extendedDataPresent = GetBits(bsi, 1);
if (psi->extendedDataPresent) {
psi->extendedDataSize = GetBits(bsi, 4);
if (psi->extendedDataSize == 15)
psi->extendedDataSize += GetBits(bsi, 8);
bitsLeft = 8 * psi->extendedDataSize;
/* get ID, unpack extension info, do whatever is necessary with it... */
while (bitsLeft > 0) {
GetBits(bsi, 8);
bitsLeft -= 8;
}
}
}

View File

@@ -1,400 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrtabs.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrtabs.c - platform-independent tables for SBR (global, read-only)
**************************************************************************************/
#include "sbr.h"
/* k0Tab[sampRateIdx][k] = k0 = startMin + offset(bs_start_freq) for given sample rate (4.6.18.3.2.1)
* downsampled (single-rate) SBR not currently supported
*/
const unsigned char k0Tab[NUM_SAMPLE_RATES_SBR][16] = {
{ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31 }, /* 96 kHz */
{ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31 }, /* 88 kHz */
{ 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 26, 30 }, /* 64 kHz */
{ 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 27, 31 }, /* 48 kHz */
{ 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 28, 32 }, /* 44 kHz */
{ 10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32 }, /* 32 kHz */
{ 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32 }, /* 24 kHz */
{ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30 }, /* 22 kHz */
{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }, /* 16 kHz */
};
/* k2Tab[sampRateIdx][k] = stopVector(bs_stop_freq) for given sample rate, bs_stop_freq = [0, 13] (4.6.18.3.2.1)
* generated with Matlab script calc_stopvec.m
* downsampled (single-rate) SBR not currently supported
*/
const unsigned char k2Tab[NUM_SAMPLE_RATES_SBR][14] = {
{ 13, 15, 17, 19, 21, 24, 27, 31, 35, 39, 44, 50, 57, 64 }, /* 96 kHz */
{ 15, 17, 19, 21, 23, 26, 29, 33, 37, 41, 46, 51, 57, 64 }, /* 88 kHz */
{ 20, 22, 24, 26, 28, 31, 34, 37, 41, 45, 49, 54, 59, 64 }, /* 64 kHz */
{ 21, 23, 25, 27, 29, 32, 35, 38, 41, 45, 49, 54, 59, 64 }, /* 48 kHz */
{ 23, 25, 27, 29, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64 }, /* 44 kHz */
{ 32, 34, 36, 38, 40, 42, 44, 46, 49, 52, 55, 58, 61, 64 }, /* 32 kHz */
{ 32, 34, 36, 38, 40, 42, 44, 46, 49, 52, 55, 58, 61, 64 }, /* 24 kHz */
{ 35, 36, 38, 40, 42, 44, 46, 48, 50, 52, 55, 58, 61, 64 }, /* 22 kHz */
{ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62, 64 }, /* 16 kHz */
};
/* NINT(2.048E6 / Fs) (figure 4.47)
* downsampled (single-rate) SBR not currently supported
*/
const unsigned char goalSBTab[NUM_SAMPLE_RATES_SBR] = {
21, 23, 32, 43, 46, 64, 85, 93, 128
};
const HuffInfo huffTabSBRInfo[10] PROGMEM = {
{19, { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 2, 7, 4, 8, 72, 0}, 0},
{20, { 0, 2, 2, 2, 2, 2, 1, 3, 3, 2, 4, 4, 4, 3, 2, 5, 6, 13, 15, 46}, 121},
{17, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 0, 0, 1, 25, 10, 0, 0, 0}, 242},
{19, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, 0, 1, 1, 2, 1, 29, 2, 0}, 291},
{19, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 2, 5, 1, 4, 2, 3, 34, 0}, 340},
{20, { 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 1, 2, 3, 4, 4, 7, 10, 16}, 403},
{14, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 13, 2, 0, 0, 0, 0, 0, 0}, 466},
{14, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 6, 8, 0, 0, 0, 0, 0, 0}, 491},
{14, { 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 0, 51, 2, 0, 0, 0, 0, 0, 0}, 516},
{ 8, { 1, 1, 1, 0, 1, 1, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 579},
};
/* Huffman tables from appendix 4.A.6.1, includes offset of -LAV[i] for table i */
const signed int /*short*/ huffTabSBR[604] PROGMEM = {
/* SBR table sbr_tenv15 [121] (signed) */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8,
-9, 8, -10, 9, -11, 10, -12, -13, 11, -14, 12, -15, -16, 13, -19, -18,
-17, 14, -24, -20, 16, -26, -21, 15, -23, -25, -22, -60, -59, -58, -57, -56,
-55, -54, -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40,
-39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60,
/* SBR table sbr_fenv15 [121] (signed) */
0, -1, 1, -2, -3, 2, -4, 3, -5, 4, -6, 5, -7, 6, -8, 7,
-9, 8, -10, 9, -11, 10, 11, -12, 12, -13, 13, 14, -14, -15, 15, 16,
17, -16, -17, -18, -19, 18, 19, -20, -21, 20, 21, -24, -23, -22, -26, -28,
22, 23, 25, -41, -25, 26, 27, -30, -27, 24, 28, 44, -51, -46, -44, -43,
-37, -33, -31, -29, 30, 37, 42, 47, 48, -60, -59, -58, -57, -56, -55, -54,
-53, -52, -50, -49, -48, -47, -45, -42, -40, -39, -38, -36, -35, -34, -32, 29,
31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 43, 45, 46, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60,
/* SBR table sbr_tenv15b [49] (signed) */
0, 1, -1, 2, -2, 3, -3, 4, -4, -5, 5, -6, 6, 7, -7, 8,
-24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9,
-8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24,
/* SBR table sbr_fenv15b [49] (signed) */
0, -1, 1, -2, 2, 3, -3, -4, 4, -5, 5, -6, 6, -7, 7, 8,
-9, -8, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11,
-10, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24,
/* SBR table sbr_tenv30 [63] (signed) */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, -7, 6, -8, 7,
-9, -10, 8, 9, 10, -13, -11, -12, -14, 11, 12, -31, -30, -29, -28, -27,
-26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
/* SBR table sbr_fenv30 [63] (signed) */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8,
8, 9, -9, -10, 10, 11, -11, -12, 12, 13, -13, -15, 14, 15, -14, 18,
-18, -24, -19, 16, 17, -22, -21, -16, 20, 21, 22, 25, -23, -20, 24, -31,
-30, -29, -28, -27, -26, -25, -17, 19, 23, 26, 27, 28, 29, 30, 31,
/* SBR table sbr_tenv30b [25] (signed) */
0, 1, -1, -2, 2, 3, -3, -4, 4, -5, -12, -11, -10, -9, -8, -7,
-6, 5, 6, 7, 8, 9, 10, 11, 12,
/* SBR table sbr_fenv30b [25] (signed) */
0, -1, 1, -2, 2, 3, -3, -4, 4, -5, 5, 6, -12, -11, -10, -9,
-8, -7, -6, 7, 8, 9, 10, 11, 12,
/* SBR table sbr_tnoise30 [63] (signed) */
0, 1, -1, -2, 2, -3, 3, -4, 4, -5, 5, 11, -31, -30, -29, -28,
-27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12,
-11, -10, -9, -8, -7, -6, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
/* SBR table sbr_tnoise30b [25] (signed) */
0, -1, 1, -2, 2, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12,
};
/* log2Tab[x] = floor(log2(x)), format = Q28 */
const int log2Tab[65] PROGMEM = {
0x00000000, 0x00000000, 0x10000000, 0x195c01a3, 0x20000000, 0x25269e12, 0x295c01a3, 0x2ceaecfe,
0x30000000, 0x32b80347, 0x35269e12, 0x3759d4f8, 0x395c01a3, 0x3b350047, 0x3ceaecfe, 0x3e829fb6,
0x40000000, 0x41663f6f, 0x42b80347, 0x43f782d7, 0x45269e12, 0x4646eea2, 0x4759d4f8, 0x48608280,
0x495c01a3, 0x4a4d3c25, 0x4b350047, 0x4c1404ea, 0x4ceaecfe, 0x4dba4a47, 0x4e829fb6, 0x4f446359,
0x50000000, 0x50b5d69b, 0x51663f6f, 0x52118b11, 0x52b80347, 0x5359ebc5, 0x53f782d7, 0x549101ea,
0x55269e12, 0x55b88873, 0x5646eea2, 0x56d1fafd, 0x5759d4f8, 0x57dea15a, 0x58608280, 0x58df988f,
0x595c01a3, 0x59d5d9fd, 0x5a4d3c25, 0x5ac24113, 0x5b350047, 0x5ba58feb, 0x5c1404ea, 0x5c80730b,
0x5ceaecfe, 0x5d53847a, 0x5dba4a47, 0x5e1f4e51, 0x5e829fb6, 0x5ee44cd5, 0x5f446359, 0x5fa2f045,
0x60000000
};
/* coefficient table 4.A.87, format = Q31
* reordered as:
* cTab[0], cTab[64], cTab[128], cTab[192], cTab[256],
* cTab[2], cTab[66], cTab[130], cTab[194], cTab[258],
* ...
* cTab[64], cTab[128], cTab[192], cTab[256], cTab[320]
*
* NOTE: cTab[1, 2, ... , 318, 319] = cTab[639, 638, ... 322, 321]
* except cTab[384] = -cTab[256], cTab[512] = -cTab[128]
*/
const int cTabA[165] PROGMEM = {
0x00000000, 0x0055dba1, 0x01b2e41d, 0x09015651, 0x2e3a7532, 0xffed978a, 0x006090c4, 0x01fd3ba0, 0x08a24899, 0x311af3a4,
0xfff0065d, 0x006b47fa, 0x024bf7a1, 0x082f552e, 0x33ff670e, 0xffef7b8b, 0x0075fded, 0x029e35b4, 0x07a8127d, 0x36e69691,
0xffee1650, 0x00807994, 0x02f3e48d, 0x070bbf58, 0x39ce0477, 0xffecc31b, 0x008a7dd7, 0x034d01f0, 0x06593912, 0x3cb41219,
0xffeb50b2, 0x009424c6, 0x03a966bb, 0x0590a67d, 0x3f962fb8, 0xffe9ca76, 0x009d10bf, 0x04083fec, 0x04b0adcb, 0x4272a385,
0xffe88ba8, 0x00a520bb, 0x04694101, 0x03b8f8dc, 0x4547daea, 0xffe79e16, 0x00abe79e, 0x04cc2fcf, 0x02a99097, 0x4812f848,
0xffe6d466, 0x00b1978d, 0x05303f87, 0x01816e06, 0x4ad237a2, 0xffe65416, 0x00b5c867, 0x05950122, 0x0040c496, 0x4d83976c,
0xffe66dd0, 0x00b8394b, 0x05f9c051, 0xfee723c6, 0x5024d70e, 0xffe69423, 0x00b8c6b0, 0x065dd56a, 0xfd7475d8, 0x52b449de,
0xffe75361, 0x00b73ab0, 0x06c0f0c0, 0xfbe8f5bd, 0x552f8ff7, 0xffe85b4b, 0x00b36acd, 0x0721bf22, 0xfa44a069, 0x579505f5,
0xffea353a, 0x00acbd2f, 0x077fedb3, 0xf887507c, 0x59e2f69e, 0xffec8409, 0x00a3508f, 0x07da2b7f, 0xf6b1f3c3, 0x5c16d0ae,
0xffef2395, 0x0096dcc2, 0x08303897, 0xf4c473c6, 0x5e2f6367, 0xfff294c3, 0x00872c63, 0x0880ffdd, 0xf2bf6ea4, 0x602b0c7f,
0xfff681d6, 0x007400b8, 0x08cb4e23, 0xf0a3959f, 0x6207f220, 0xfffb42b0, 0x005d36df, 0x090ec1fc, 0xee71b2fe, 0x63c45243,
0x00007134, 0x00426f36, 0x0949eaac, 0xec2a3f5f, 0x655f63f2, 0x0006b1cf, 0x0023b989, 0x097c1ee8, 0xe9cea84a, 0x66d76725,
0x000d31b5, 0x0000e790, 0x09a3e163, 0xe75f8bb8, 0x682b39a4, 0x001471f8, 0xffda17f2, 0x09c0e59f, 0xe4de0cb0, 0x6959709d,
0x001c3549, 0xffaea5d6, 0x09d19ca9, 0xe24b8f66, 0x6a619c5e, 0x0024dd50, 0xff7ee3f1, 0x09d5560b, 0xdfa93ab5, 0x6b42a864,
0x002d8e42, 0xff4aabc8, 0x09caeb0f, 0xdcf898fb, 0x6bfbdd98, 0x003745f9, 0xff120d70, 0x09b18a1d, 0xda3b176a, 0x6c8c4c7a,
0x004103f4, 0xfed4bec3, 0x09881dc5, 0xd7722f04, 0x6cf4073e, 0x004b6c46, 0xfe933dc0, 0x094d7ec2, 0xd49fd55f, 0x6d32730f,
0x0055dba1, 0x01b2e41d, 0x09015651, 0x2e3a7532, 0x6d474e1d,
};
/* coefficient table 4.A.87, format = Q31
* reordered as cTab[0], cTab[64], cTab[128], ... cTab[576], cTab[1], cTab[65], cTab[129], ... cTab[639]
* keeping full table (not using symmetry) to allow sequential access in synth filter inner loop
* format = Q31
*/
const int cTabS[640] PROGMEM = {
0x00000000, 0x0055dba1, 0x01b2e41d, 0x09015651, 0x2e3a7532, 0x6d474e1d, 0xd1c58ace, 0x09015651, 0xfe4d1be3, 0x0055dba1,
0xffede50e, 0x005b5371, 0x01d78bfc, 0x08d3e41b, 0x2faa221c, 0x6d41d963, 0xd3337b3d, 0x09299ead, 0xfe70b8d1, 0x0050b177,
0xffed978a, 0x006090c4, 0x01fd3ba0, 0x08a24899, 0x311af3a4, 0x6d32730f, 0xd49fd55f, 0x094d7ec2, 0xfe933dc0, 0x004b6c46,
0xffefc9b9, 0x0065fde5, 0x02244a24, 0x086b1eeb, 0x328cc6f0, 0x6d18520e, 0xd60a46e5, 0x096d0e21, 0xfeb48d0d, 0x00465348,
0xfff0065d, 0x006b47fa, 0x024bf7a1, 0x082f552e, 0x33ff670e, 0x6cf4073e, 0xd7722f04, 0x09881dc5, 0xfed4bec3, 0x004103f4,
0xffeff6ca, 0x0070c8a5, 0x0274ba43, 0x07ee507c, 0x3572ec70, 0x6cc59bab, 0xd8d7f21f, 0x099ec3dc, 0xfef3f6ab, 0x003c1fa4,
0xffef7b8b, 0x0075fded, 0x029e35b4, 0x07a8127d, 0x36e69691, 0x6c8c4c7a, 0xda3b176a, 0x09b18a1d, 0xff120d70, 0x003745f9,
0xffeedfa4, 0x007b3875, 0x02c89901, 0x075ca90c, 0x385a49c4, 0x6c492217, 0xdb9b5b12, 0x09c018ce, 0xff2ef725, 0x00329ab6,
0xffee1650, 0x00807994, 0x02f3e48d, 0x070bbf58, 0x39ce0477, 0x6bfbdd98, 0xdcf898fb, 0x09caeb0f, 0xff4aabc8, 0x002d8e42,
0xffed651d, 0x0085c217, 0x03201116, 0x06b559c3, 0x3b415115, 0x6ba4629f, 0xde529086, 0x09d1fa23, 0xff6542d1, 0x00293718,
0xffecc31b, 0x008a7dd7, 0x034d01f0, 0x06593912, 0x3cb41219, 0x6b42a864, 0xdfa93ab5, 0x09d5560b, 0xff7ee3f1, 0x0024dd50,
0xffebe77b, 0x008f4bfc, 0x037ad438, 0x05f7fb90, 0x3e25b17e, 0x6ad73e8d, 0xe0fc421e, 0x09d52709, 0xff975c01, 0x002064f8,
0xffeb50b2, 0x009424c6, 0x03a966bb, 0x0590a67d, 0x3f962fb8, 0x6a619c5e, 0xe24b8f66, 0x09d19ca9, 0xffaea5d6, 0x001c3549,
0xffea9192, 0x0098b855, 0x03d8afe6, 0x05237f9d, 0x41058bc6, 0x69e29784, 0xe396a45d, 0x09cab9f2, 0xffc4e365, 0x0018703f,
0xffe9ca76, 0x009d10bf, 0x04083fec, 0x04b0adcb, 0x4272a385, 0x6959709d, 0xe4de0cb0, 0x09c0e59f, 0xffda17f2, 0x001471f8,
0xffe940f4, 0x00a1039c, 0x043889c6, 0x0437fb0a, 0x43de620a, 0x68c7269b, 0xe620c476, 0x09b3d77f, 0xffee183b, 0x0010bc63,
0xffe88ba8, 0x00a520bb, 0x04694101, 0x03b8f8dc, 0x4547daea, 0x682b39a4, 0xe75f8bb8, 0x09a3e163, 0x0000e790, 0x000d31b5,
0xffe83a07, 0x00a8739d, 0x049aa82f, 0x03343533, 0x46aea856, 0x6785c24d, 0xe89971b7, 0x099140a7, 0x00131c75, 0x0009aa3f,
0xffe79e16, 0x00abe79e, 0x04cc2fcf, 0x02a99097, 0x4812f848, 0x66d76725, 0xe9cea84a, 0x097c1ee8, 0x0023b989, 0x0006b1cf,
0xffe7746e, 0x00af374c, 0x04fe20be, 0x02186a91, 0x4973fef1, 0x661fd6b8, 0xeafee7f1, 0x0963ed46, 0x0033b927, 0x00039609,
0xffe6d466, 0x00b1978d, 0x05303f87, 0x01816e06, 0x4ad237a2, 0x655f63f2, 0xec2a3f5f, 0x0949eaac, 0x00426f36, 0x00007134,
0xffe6afee, 0x00b3d15c, 0x05626209, 0x00e42fa2, 0x4c2ca3df, 0x64964063, 0xed50a31d, 0x092d7970, 0x00504f41, 0xfffdfa25,
0xffe65416, 0x00b5c867, 0x05950122, 0x0040c496, 0x4d83976c, 0x63c45243, 0xee71b2fe, 0x090ec1fc, 0x005d36df, 0xfffb42b0,
0xffe681c6, 0x00b74c37, 0x05c76fed, 0xff96db90, 0x4ed62be3, 0x62ea6474, 0xef8d4d7b, 0x08edfeaa, 0x006928a0, 0xfff91fca,
0xffe66dd0, 0x00b8394b, 0x05f9c051, 0xfee723c6, 0x5024d70e, 0x6207f220, 0xf0a3959f, 0x08cb4e23, 0x007400b8, 0xfff681d6,
0xffe66fac, 0x00b8fe0d, 0x062bf5ec, 0xfe310657, 0x516eefb9, 0x611d58a3, 0xf1b461ab, 0x08a75da4, 0x007e0393, 0xfff48700,
0xffe69423, 0x00b8c6b0, 0x065dd56a, 0xfd7475d8, 0x52b449de, 0x602b0c7f, 0xf2bf6ea4, 0x0880ffdd, 0x00872c63, 0xfff294c3,
0xffe6fed4, 0x00b85f70, 0x068f8b44, 0xfcb1d740, 0x53f495aa, 0x5f30ff5f, 0xf3c4e887, 0x08594887, 0x008f87aa, 0xfff0e7ef,
0xffe75361, 0x00b73ab0, 0x06c0f0c0, 0xfbe8f5bd, 0x552f8ff7, 0x5e2f6367, 0xf4c473c6, 0x08303897, 0x0096dcc2, 0xffef2395,
0xffe80414, 0x00b58c8c, 0x06f1825d, 0xfb19b7bd, 0x56654bdd, 0x5d26be9b, 0xf5be0fa9, 0x08061671, 0x009da526, 0xffedc418,
0xffe85b4b, 0x00b36acd, 0x0721bf22, 0xfa44a069, 0x579505f5, 0x5c16d0ae, 0xf6b1f3c3, 0x07da2b7f, 0x00a3508f, 0xffec8409,
0xffe954d0, 0x00b06b68, 0x075112a2, 0xf96916f5, 0x58befacd, 0x5b001db8, 0xf79fa13a, 0x07ad8c26, 0x00a85e94, 0xffeb3849,
0xffea353a, 0x00acbd2f, 0x077fedb3, 0xf887507c, 0x59e2f69e, 0x59e2f69e, 0xf887507c, 0x077fedb3, 0x00acbd2f, 0xffea353a,
0xffeb3849, 0x00a85e94, 0x07ad8c26, 0xf79fa13a, 0x5b001db8, 0x58befacd, 0xf96916f5, 0x075112a2, 0x00b06b68, 0xffe954d0,
0xffec8409, 0x00a3508f, 0x07da2b7f, 0xf6b1f3c3, 0x5c16d0ae, 0x579505f5, 0xfa44a069, 0x0721bf22, 0x00b36acd, 0xffe85b4b,
0xffedc418, 0x009da526, 0x08061671, 0xf5be0fa9, 0x5d26be9b, 0x56654bdd, 0xfb19b7bd, 0x06f1825d, 0x00b58c8c, 0xffe80414,
0xffef2395, 0x0096dcc2, 0x08303897, 0xf4c473c6, 0x5e2f6367, 0x552f8ff7, 0xfbe8f5bd, 0x06c0f0c0, 0x00b73ab0, 0xffe75361,
0xfff0e7ef, 0x008f87aa, 0x08594887, 0xf3c4e887, 0x5f30ff5f, 0x53f495aa, 0xfcb1d740, 0x068f8b44, 0x00b85f70, 0xffe6fed4,
0xfff294c3, 0x00872c63, 0x0880ffdd, 0xf2bf6ea4, 0x602b0c7f, 0x52b449de, 0xfd7475d8, 0x065dd56a, 0x00b8c6b0, 0xffe69423,
0xfff48700, 0x007e0393, 0x08a75da4, 0xf1b461ab, 0x611d58a3, 0x516eefb9, 0xfe310657, 0x062bf5ec, 0x00b8fe0d, 0xffe66fac,
0xfff681d6, 0x007400b8, 0x08cb4e23, 0xf0a3959f, 0x6207f220, 0x5024d70e, 0xfee723c6, 0x05f9c051, 0x00b8394b, 0xffe66dd0,
0xfff91fca, 0x006928a0, 0x08edfeaa, 0xef8d4d7b, 0x62ea6474, 0x4ed62be3, 0xff96db90, 0x05c76fed, 0x00b74c37, 0xffe681c6,
0xfffb42b0, 0x005d36df, 0x090ec1fc, 0xee71b2fe, 0x63c45243, 0x4d83976c, 0x0040c496, 0x05950122, 0x00b5c867, 0xffe65416,
0xfffdfa25, 0x00504f41, 0x092d7970, 0xed50a31d, 0x64964063, 0x4c2ca3df, 0x00e42fa2, 0x05626209, 0x00b3d15c, 0xffe6afee,
0x00007134, 0x00426f36, 0x0949eaac, 0xec2a3f5f, 0x655f63f2, 0x4ad237a2, 0x01816e06, 0x05303f87, 0x00b1978d, 0xffe6d466,
0x00039609, 0x0033b927, 0x0963ed46, 0xeafee7f1, 0x661fd6b8, 0x4973fef1, 0x02186a91, 0x04fe20be, 0x00af374c, 0xffe7746e,
0x0006b1cf, 0x0023b989, 0x097c1ee8, 0xe9cea84a, 0x66d76725, 0x4812f848, 0x02a99097, 0x04cc2fcf, 0x00abe79e, 0xffe79e16,
0x0009aa3f, 0x00131c75, 0x099140a7, 0xe89971b7, 0x6785c24d, 0x46aea856, 0x03343533, 0x049aa82f, 0x00a8739d, 0xffe83a07,
0x000d31b5, 0x0000e790, 0x09a3e163, 0xe75f8bb8, 0x682b39a4, 0x4547daea, 0x03b8f8dc, 0x04694101, 0x00a520bb, 0xffe88ba8,
0x0010bc63, 0xffee183b, 0x09b3d77f, 0xe620c476, 0x68c7269b, 0x43de620a, 0x0437fb0a, 0x043889c6, 0x00a1039c, 0xffe940f4,
0x001471f8, 0xffda17f2, 0x09c0e59f, 0xe4de0cb0, 0x6959709d, 0x4272a385, 0x04b0adcb, 0x04083fec, 0x009d10bf, 0xffe9ca76,
0x0018703f, 0xffc4e365, 0x09cab9f2, 0xe396a45d, 0x69e29784, 0x41058bc6, 0x05237f9d, 0x03d8afe6, 0x0098b855, 0xffea9192,
0x001c3549, 0xffaea5d6, 0x09d19ca9, 0xe24b8f66, 0x6a619c5e, 0x3f962fb8, 0x0590a67d, 0x03a966bb, 0x009424c6, 0xffeb50b2,
0x002064f8, 0xff975c01, 0x09d52709, 0xe0fc421e, 0x6ad73e8d, 0x3e25b17e, 0x05f7fb90, 0x037ad438, 0x008f4bfc, 0xffebe77b,
0x0024dd50, 0xff7ee3f1, 0x09d5560b, 0xdfa93ab5, 0x6b42a864, 0x3cb41219, 0x06593912, 0x034d01f0, 0x008a7dd7, 0xffecc31b,
0x00293718, 0xff6542d1, 0x09d1fa23, 0xde529086, 0x6ba4629f, 0x3b415115, 0x06b559c3, 0x03201116, 0x0085c217, 0xffed651d,
0x002d8e42, 0xff4aabc8, 0x09caeb0f, 0xdcf898fb, 0x6bfbdd98, 0x39ce0477, 0x070bbf58, 0x02f3e48d, 0x00807994, 0xffee1650,
0x00329ab6, 0xff2ef725, 0x09c018ce, 0xdb9b5b12, 0x6c492217, 0x385a49c4, 0x075ca90c, 0x02c89901, 0x007b3875, 0xffeedfa4,
0x003745f9, 0xff120d70, 0x09b18a1d, 0xda3b176a, 0x6c8c4c7a, 0x36e69691, 0x07a8127d, 0x029e35b4, 0x0075fded, 0xffef7b8b,
0x003c1fa4, 0xfef3f6ab, 0x099ec3dc, 0xd8d7f21f, 0x6cc59bab, 0x3572ec70, 0x07ee507c, 0x0274ba43, 0x0070c8a5, 0xffeff6ca,
0x004103f4, 0xfed4bec3, 0x09881dc5, 0xd7722f04, 0x6cf4073e, 0x33ff670e, 0x082f552e, 0x024bf7a1, 0x006b47fa, 0xfff0065d,
0x00465348, 0xfeb48d0d, 0x096d0e21, 0xd60a46e5, 0x6d18520e, 0x328cc6f0, 0x086b1eeb, 0x02244a24, 0x0065fde5, 0xffefc9b9,
0x004b6c46, 0xfe933dc0, 0x094d7ec2, 0xd49fd55f, 0x6d32730f, 0x311af3a4, 0x08a24899, 0x01fd3ba0, 0x006090c4, 0xffed978a,
0x0050b177, 0xfe70b8d1, 0x09299ead, 0xd3337b3d, 0x6d41d963, 0x2faa221c, 0x08d3e41b, 0x01d78bfc, 0x005b5371, 0xffede50f,
};
/* noise table 4.A.88, format = Q31 */
const int noiseTab[512*2] PROGMEM = {
0x8010fd38, 0xb3dc7948, 0x7c4e2301, 0xa9904192, 0x121622a7, 0x86489625, 0xc3d53d25, 0xd0343fa9,
0x674d6f70, 0x25f4e9fd, 0xce1a8c8b, 0x72a726c5, 0xfea6efc6, 0xaa4adb1a, 0x8b2dd628, 0xf14029e4,
0x46321c1a, 0x604889a0, 0x33363b63, 0x815ed069, 0x802b4315, 0x8f2bf7f3, 0x85b86073, 0x745cfb46,
0xc57886b3, 0xb76731f0, 0xa2a66772, 0x828ca631, 0x60cc145e, 0x1ad1010f, 0x090c83d4, 0x9bd7ba87,
0x5f5aeea2, 0x8b4dbd99, 0x848e7b1e, 0x86bb9fa2, 0x26f18ae5, 0xc0b81194, 0x553407bf, 0x52c17953,
0x755f468d, 0x166b04f8, 0xa5687981, 0x4343248b, 0xa6558d5e, 0xc5f6fab7, 0x80a4fb8c, 0x8cb53cb7,
0x7da68a54, 0x9cd8df8a, 0xba05376c, 0xfcb58ee2, 0xfdd657a4, 0x005e35ca, 0x91c75c55, 0x367651e6,
0x816abf85, 0x8f831c4f, 0x423f9c9c, 0x55aa919e, 0x80779834, 0xb59f4244, 0x800a095c, 0x7de9e0cc,
0x46bda5cb, 0x4c184464, 0x2c438f71, 0x797216b5, 0x5035cee6, 0xa0c3a26e, 0x9d3f95fa, 0xd4a100c0,
0x8ac30dac, 0x04b87397, 0x9e5ac516, 0x8b0b442e, 0x66210ad6, 0x88ba7598, 0x45b9bd33, 0xf0be5087,
0x9261b85e, 0x364f6a31, 0x891c4b50, 0x23ad08ce, 0xf10366a6, 0x80414276, 0x1b562e06, 0x8be21591,
0x9e798195, 0x7fb4045c, 0x7d9506cf, 0x854e691f, 0x9207f092, 0x7a94c9d5, 0x88911536, 0x3f45cc61,
0x27059279, 0xa5b57109, 0x6d2bb67b, 0x3bdc5379, 0x74e662d8, 0x80348f8c, 0xf875e638, 0x5a8caea1,
0x2459ae75, 0x2c54b939, 0x79ee3203, 0xb9bc8683, 0x9b6f630c, 0x9f45b351, 0x8563b2b9, 0xe5dbba41,
0x697c7d0d, 0x7bb7c90e, 0xac900866, 0x8e6b5177, 0x8822dd37, 0x7fd5a91e, 0x7506da05, 0x82302aca,
0xa5e4be04, 0x4b4288eb, 0x00b8bc9f, 0x4f1033e4, 0x7200d612, 0x43900c8c, 0xa815b900, 0x676ed1d4,
0x5c5f23b2, 0xa758ee11, 0xaf73abfa, 0x11714ec0, 0x265239e0, 0xc50de679, 0x8a84e341, 0xa1438354,
0x7f1a341f, 0x343ec96b, 0x696e71b0, 0xa13bde39, 0x81e75094, 0x80091111, 0x853a73bf, 0x80f9c1ee,
0xe4980086, 0x886a8e28, 0xa7e89426, 0xdd93edd7, 0x7592100d, 0x0bfa8123, 0x850a26d4, 0x2e34f395,
0x421b6c00, 0xa4a462e4, 0x4e3f5090, 0x3c189f4c, 0x3c971a56, 0xdd0376d2, 0x747a5367, 0x7bcbc9d7,
0x3966be6a, 0x7efda616, 0x55445e15, 0x7ba2ab3f, 0x5fe684f2, 0x8cf42af9, 0x808c61c3, 0x4390c27b,
0x7cac62ff, 0xea6cab22, 0x5d0902ad, 0xc27b7208, 0x7a27389d, 0x5820a357, 0xa29bbe59, 0x9df0f1fd,
0x92bd67e5, 0x7195b587, 0x97cac65b, 0x8339807e, 0x8f72d832, 0x5fad8685, 0xa462d9d3, 0x81d46214,
0x6ae93e1d, 0x6b23a5b9, 0xc2732874, 0x81795268, 0x7c568cb6, 0x668513ea, 0x428d024e, 0x66b78b3a,
0xfee9ef03, 0x9ddcbb82, 0xa605f07e, 0x46dc55e0, 0x85415054, 0xc89ec271, 0x7c42edfb, 0x0befe59b,
0x89b8f607, 0x6d732a1a, 0xa7081ebd, 0x7e403258, 0x21feeb7b, 0x5dd7a1e7, 0x23e3a31a, 0x129bc896,
0xa11a6b54, 0x7f1e031c, 0xfdc1a4d1, 0x96402e53, 0xb9700f1a, 0x8168ecd6, 0x7d63d3cc, 0x87a70d65,
0x81075a7a, 0x55c8caa7, 0xa95d00b5, 0x102b1652, 0x0bb30215, 0xe5b63237, 0xa446ca44, 0x82d4c333,
0x67b2e094, 0x44c3d661, 0x33fd6036, 0xde1ea2a1, 0xa95e8e47, 0x78f66eb9, 0x6f2aef1e, 0xe8887247,
0x80a3b70e, 0xfca0d9d3, 0x6bf0fd20, 0x0d5226de, 0xf4341c87, 0x5902df05, 0x7ff1a38d, 0xf02e5a5b,
0x99f129af, 0x8ac63d01, 0x7b53f599, 0x7bb32532, 0x99ac59b0, 0x5255a80f, 0xf1320a41, 0x2497aa5c,
0xcce60bd8, 0x787c634b, 0x7ed58c5b, 0x8a28eb3a, 0x24a5e647, 0x8b79a2c1, 0x955f5ce5, 0xa9d12bc4,
0x7a1e20c6, 0x3eeda7ac, 0xf7be823a, 0x042924ce, 0x808b3f03, 0x364248da, 0xac2895e5, 0x69a8b5fa,
0x97fe8b63, 0xbdeac9aa, 0x8073e0ad, 0x6c25dba7, 0x005e51d2, 0x52e74389, 0x59d3988c, 0xe5d1f39c,
0x7b57dc91, 0x341adbe7, 0xa7d42b8d, 0x74e9f335, 0xd35bf7d8, 0x5b7c0a4b, 0x75bc0874, 0x552129bf,
0x8144b70d, 0x6de93bbb, 0x5825f14b, 0x473ec5ca, 0x80a8f37c, 0xe6552d69, 0x7898360b, 0x806379b0,
0xa9b59339, 0x3f6bf60c, 0xc367d731, 0x920ade99, 0x125592f7, 0x877e5ed1, 0xda895d95, 0x075f2ece,
0x380e5f5e, 0x9b006b62, 0xd17a6dd2, 0x530a0e13, 0xf4cc9a14, 0x7d0a0ed4, 0x847c6e3f, 0xbaee4975,
0x47131163, 0x64fb2cac, 0x5e2100a6, 0x7b756a42, 0xd87609f4, 0x98bfe48c, 0x0493745e, 0x836c5784,
0x7e5ccb40, 0x3df6b476, 0x97700d28, 0x8bbd93fd, 0x56de9cdb, 0x680b4e65, 0xebc3d90e, 0x6d286793,
0x6753712e, 0xe05c98a7, 0x3d2b6b85, 0xc4b18ddb, 0x7b59b869, 0x31435688, 0x811888e9, 0xe011ee7a,
0x6a5844f9, 0x86ae35ea, 0xb4cbc10b, 0x01a6f5d6, 0x7a49ed64, 0x927caa49, 0x847ddaed, 0xae0d9bb6,
0x836bdb04, 0x0fd810a6, 0x74fe126b, 0x4a346b5f, 0x80184d36, 0x5afd153c, 0x90cc8102, 0xe606d0e6,
0xde69aa58, 0xa89f1222, 0xe06df715, 0x8fd16144, 0x0317c3e8, 0x22ce92fc, 0x690c3eca, 0x93166f02,
0x71573414, 0x8d43cffb, 0xe8bd0bb6, 0xde86770f, 0x0bf99a41, 0x4633a661, 0xba064108, 0x7adafae3,
0x2f6cde5d, 0xb350a52c, 0xa5ebfb0b, 0x74c57b46, 0xd3b603b5, 0x80b70892, 0xa7f7fa53, 0xd94b566c,
0xdda3fd86, 0x6a635793, 0x3ed005ca, 0xc5f087d8, 0x31e3a746, 0x7a4278f9, 0x82def1f9, 0x06caa2b2,
0xe9d2c349, 0x8940e7f7, 0x7feef8dd, 0x4a9b01f0, 0xacde69f8, 0x57ddc280, 0xf09e4ba4, 0xb6d9f729,
0xb48c18f2, 0xd3654aa9, 0xca7a03c8, 0x14d57545, 0x7fda87a5, 0x0e411366, 0xb77d0df0, 0x8c2aa467,
0x787f2590, 0x2d292db1, 0x9f12682c, 0x44ac364d, 0x1a4b31a6, 0x871f7ded, 0x7ff99167, 0x6630a1d5,
0x25385eb9, 0x2d4dd549, 0xaf8a7004, 0x319ebe0f, 0x379ab730, 0x81dc56a4, 0x822d8523, 0x1ae8554c,
0x18fa0786, 0x875f7de4, 0x85ca350f, 0x7de818dc, 0x7786a38f, 0xa5456355, 0x92e60f88, 0xf5526122,
0x916039bc, 0xc561e2de, 0x31c42042, 0x7c82e290, 0x75d158b2, 0xb015bda1, 0x7220c750, 0x46565441,
0xd0da1fdd, 0x7b777481, 0x782e73c6, 0x8cd72b7b, 0x7f1006aa, 0xfb30e51e, 0x87994818, 0x34e7c7db,
0x7faae06b, 0xea74fbc0, 0xd20c7af4, 0xc44f396b, 0x06b4234e, 0xdf2e2a93, 0x2efb07c8, 0xce861911,
0x7550ea05, 0xd8d90bbb, 0x58522eec, 0x746b3520, 0xce844ce9, 0x7f5cacc3, 0xda8f17e0, 0x2fedf9cb,
0xb2f77ec4, 0x6f13f4c0, 0x834de085, 0x7b7ace4b, 0x713b16ac, 0x499c5ab0, 0x06a7961d, 0x1b39a48a,
0xbb853e6e, 0x7c781cc1, 0xc0baebf5, 0x7dace394, 0x815ceebc, 0xcc7b27d4, 0x8274b181, 0xa2be40a2,
0xdd01d5dc, 0x7fefeb14, 0x0813ec78, 0xba3077cc, 0xe5cf1e1c, 0xedcfacae, 0x54c43a9b, 0x5cd62a42,
0x93806b55, 0x03095c5b, 0x8e076ae3, 0x71bfcd2a, 0x7ac1989b, 0x623bc71a, 0x5e15d4d2, 0xfb341dd1,
0xd75dfbca, 0xd0da32be, 0xd4569063, 0x337869da, 0x3d30606a, 0xcd89cca2, 0x7dd2ae36, 0x028c03cd,
0xd85e052c, 0xe8dc9ec5, 0x7ffd9241, 0xde5bf4c6, 0x88c4b235, 0x8228be2e, 0x7fe6ec64, 0x996abe6a,
0xdeb0666d, 0x9eb86611, 0xd249b922, 0x18b3e26b, 0x80211168, 0x5f8bb99c, 0x6ecb0dd2, 0x4728ff8d,
0x2ac325b8, 0x6e5169d2, 0x7ebbd68d, 0x05e41d17, 0xaaa19f28, 0x8ab238a6, 0x51f105be, 0x140809cc,
0x7f7345d9, 0x3aae5a9d, 0xaecec6e4, 0x1afb3473, 0xf6229ed1, 0x8d55f467, 0x7e32003a, 0x70f30c14,
0x6686f33f, 0xd0d45ed8, 0x644fab57, 0x3a3fbbd3, 0x0b255fc4, 0x679a1701, 0x90e17b6e, 0x325d537b,
0xcd7b9b87, 0xaa7be2a2, 0x7d47c966, 0xa33dbce5, 0x8659c3bb, 0x72a41367, 0x15c446e0, 0x45fe8b0a,
0x9d8ddf26, 0x84d47643, 0x7fabe0da, 0x36a70122, 0x7a28ebfe, 0x7c29b8b8, 0x7f760406, 0xbabe4672,
0x23ea216e, 0x92bcc50a, 0x6d20dba2, 0xad5a7c7e, 0xbf3897f5, 0xabb793e1, 0x8391fc7e, 0xe270291c,
0x7a248d58, 0x80f8fd15, 0x83ef19f3, 0x5e6ece7d, 0x278430c1, 0x35239f4d, 0xe09c073b, 0x50e78cb5,
0xd4b811bd, 0xce834ee0, 0xf88aaa34, 0xf71da5a9, 0xe2b0a1d5, 0x7c3aef31, 0xe84eabca, 0x3ce25964,
0xf29336d3, 0x8fa78b2c, 0xa3fc3415, 0x63e1313d, 0x7fbc74e0, 0x7340bc93, 0x49ae583b, 0x8b79de4b,
0x25011ce9, 0x7b462279, 0x36007db0, 0x3da1599c, 0x77780772, 0xc845c9bb, 0x83ba68be, 0x6ee507d1,
0x2f0159b8, 0x5392c4ed, 0x98336ff6, 0x0b3c7f11, 0xde697aac, 0x893fc8d0, 0x6b83f8f3, 0x47799a0d,
0x801d9dfc, 0x8516a83e, 0x5f8d22ec, 0x0f8ba384, 0xa049dc4b, 0xdd920b05, 0x7a99bc9f, 0x9ad19344,
0x7a345dba, 0xf501a13f, 0x3e58bf19, 0x7fffaf9a, 0x3b4e1511, 0x0e08b991, 0x9e157620, 0x7230a326,
0x4977f9ff, 0x2d2bbae1, 0x607aa7fc, 0x7bc85d5f, 0xb441bbbe, 0x8d8fa5f2, 0x601cce26, 0xda1884f2,
0x81c82d64, 0x200b709c, 0xcbd36abe, 0x8cbdddd3, 0x55ab61d3, 0x7e3ee993, 0x833f18aa, 0xffc1aaea,
0x7362e16a, 0x7fb85db2, 0x904ee04c, 0x7f04dca6, 0x8ad7a046, 0xebe7d8f7, 0xfbc4c687, 0xd0609458,
0x093ed977, 0x8e546085, 0x7f5b8236, 0x7c47e118, 0xa01f2641, 0x7ffb3e48, 0x05de7cda, 0x7fc281b9,
0x8e0278fc, 0xd74e6d07, 0x94c24450, 0x7cf9e641, 0x2ad27871, 0x919fa815, 0x805fd205, 0x7758397f,
0xe2c7e02c, 0x1828e194, 0x5613d6fe, 0xfb55359f, 0xf9699516, 0x8978ee26, 0x7feebad9, 0x77d71d82,
0x55b28b60, 0x7e997600, 0x80821a6b, 0xc6d78af1, 0x691822ab, 0x7f6982a0, 0x7ef56f99, 0x5c307f40,
0xac6f8b76, 0x42cc8ba4, 0x782c61d9, 0xa0224dd0, 0x7bd234d1, 0x74576e3b, 0xe38cfe9a, 0x491e66ef,
0xc78291c5, 0x895bb87f, 0x924f7889, 0x71b89394, 0x757b779d, 0xc4a9c604, 0x5cdf7829, 0x8020e9df,
0x805e8245, 0x4a82c398, 0x6360bd62, 0x78bb60fc, 0x09e0d014, 0x4b0ea180, 0xb841978b, 0x69a0e864,
0x7df35977, 0x3284b0dd, 0x3cdc2efd, 0x57d31f5e, 0x541069cc, 0x1776e92e, 0x04309ea3, 0xa015eb2d,
0xce7bfabc, 0x41b638f8, 0x8365932e, 0x846ab44c, 0xbbcc80cb, 0x8afa6cac, 0x7fc422ea, 0x4e403fc0,
0xbfac9aee, 0x8e4c6709, 0x028e01fb, 0x6d160a9b, 0x7fe93004, 0x790f9cdc, 0x6a1f37a0, 0xf7e7ef30,
0xb4ea0f04, 0x7bf4c8e6, 0xe981701f, 0xc258a9d3, 0x6acbbfba, 0xef5479c7, 0x079c8bd8, 0x1a410f56,
0x6853b799, 0x86cd4f01, 0xc66e23b6, 0x34585565, 0x8d1fe00d, 0x7fcdba1a, 0x32c9717b, 0xa02f9f48,
0xf64940db, 0x5ed7d8f1, 0x61b823b2, 0x356f8918, 0xa0a7151e, 0x793fc969, 0x530beaeb, 0x34e93270,
0x4fc4ddb5, 0x88d58b6c, 0x36094774, 0xf620ac80, 0x03763a72, 0xf910c9a6, 0x6666fb2d, 0x752c8be8,
0x9a6dfdd8, 0xd1a7117d, 0x51c1b1d4, 0x0a67773d, 0x43b32a79, 0x4cdcd085, 0x5f067d30, 0x05bfe92a,
0x7ed7d203, 0xe71a3c85, 0x99127ce2, 0x8eb3cac4, 0xad4bbcea, 0x5c6a0fd0, 0x0eec04af, 0x94e95cd4,
0x8654f921, 0x83eabb5d, 0xb058d7ca, 0x69f12d3c, 0x03d881b2, 0x80558ef7, 0x82938cb3, 0x2ec0e1d6,
0x80044422, 0xd1e47051, 0x720fc6ff, 0x82b20316, 0x0d527b02, 0x63049a15, 0x7ad5b9ad, 0xd2a4641d,
0x41144f86, 0x7b04917a, 0x15c4a2c0, 0x9da07916, 0x211df54a, 0x7fdd09af, 0xfe924f3f, 0x7e132cfe,
0x9a1d18d6, 0x7c56508b, 0x80f0f0af, 0x8095ced6, 0x8037d0d7, 0x026719d1, 0xa55fec43, 0x2b1c7cb7,
0xa5cd5ac1, 0x77639fad, 0x7fcd8b62, 0x81a18c27, 0xaee4912e, 0xeae9eebe, 0xeb3081de, 0x8532aada,
0xc822362e, 0x86a649a9, 0x8031a71d, 0x7b319dc6, 0xea8022e6, 0x814bc5a9, 0x8f62f7a1, 0xa430ea17,
0x388deafb, 0x883b5185, 0x776fe13c, 0x801c683f, 0x87c11b98, 0xb7cbc644, 0x8e9ad3e8, 0x3cf5a10c,
0x7ff6a634, 0x949ef096, 0x9f84aa7c, 0x010af13f, 0x782d1de8, 0xf18e492a, 0x6cf63b01, 0x4301cd81,
0x32d15c9e, 0x68ad8cef, 0xd09bd2d6, 0x908c5c15, 0xd1e36260, 0x2c5bfdd0, 0x88765a99, 0x93deba1e,
0xac6ae342, 0xe865b84c, 0x0f4f2847, 0x7fdf0499, 0x78b1c9b3, 0x6a73261e, 0x601a96f6, 0xd2847933,
0x489aa888, 0xe12e8093, 0x3bfa5a5f, 0xd96ba5f7, 0x7c8f4c8d, 0x80940c6f, 0xcef9dd1a, 0x7e1a055f,
0x3483558b, 0x02b59cc4, 0x0c56333e, 0x05a5b813, 0x92d66287, 0x7516b679, 0x71bfe03f, 0x8056bf68,
0xc24d0724, 0x8416bcf3, 0x234afbdb, 0x4b0d6f9c, 0xaba97333, 0x4b4f42b6, 0x7e8343ab, 0x7ffe2603,
0xe590f73c, 0x45e10c76, 0xb07a6a78, 0xb35609d3, 0x1a027dfd, 0x90cb6e20, 0x82d3fe38, 0x7b409257,
0x0e395afa, 0x1b802093, 0xcb0c6c59, 0x241e17e7, 0x1ee3ea0a, 0x41a82302, 0xab04350a, 0xf570beb7,
0xbb444b9b, 0x83021459, 0x838d65dc, 0x1c439c84, 0x6fdcc454, 0xef9ef325, 0x18626c1c, 0x020d251f,
0xc4aae786, 0x8614cb48, 0xf6f53ca6, 0x8710dbab, 0x89abec0d, 0xf29d41c1, 0x94b50336, 0xfdd49178,
0x604658d1, 0x800e85be, 0xca1bb079, 0x7fa48eeb, 0xa3b7fafe, 0xd330436b, 0x64eb604c, 0x43a658ae,
0x7caa1337, 0xddd445e6, 0x7efbf955, 0xb706ec71, 0x624a6b53, 0x9e0e231f, 0x97097248, 0xa1e1a17a,
0x68dd2e44, 0x7f9d2e14, 0xddcc7074, 0x58324197, 0xc88fc426, 0x6d3640ae, 0x7ef83600, 0x759a0270,
0x98b6d854, 0xd63c9b84, 0x372474a2, 0xe3f18cfd, 0x56ab0bdb, 0x85c9be7e, 0x47dfcfeb, 0xa5830d41,
0x0ddd6283, 0xf4f480ad, 0x74c60e38, 0xab8943c3, 0xc1508fe7, 0x480cdc39, 0x8e097362, 0xa44793be,
0x538b7e18, 0x545f5b41, 0x56529175, 0x9771a97e, 0xc2da7421, 0xea8265f2, 0x805d1163, 0x883c5d28,
0x8ba94c48, 0x4f676e65, 0xf78735b3, 0xe1853671, 0x7f454f53, 0x18147f85, 0x7d09e15d, 0xdb4f3494,
0x795c8973, 0x83310632, 0x85d8061c, 0x9a1a0ebf, 0xc125583c, 0x2a1b1a95, 0x7fd9103f, 0x71e98c72,
0x40932ed7, 0x91ed227a, 0x3c5e560e, 0xe816dee9, 0xb0891b80, 0x600038ba, 0xc7d9a80d, 0x7fff5e09,
0x7e3f4351, 0xbb6b4424, 0xb14448d4, 0x8d6bb7e1, 0xfb153626, 0xa68ad537, 0xd9782006, 0xf62f6991,
0x359ba8c1, 0x02ccff0b, 0x91bf2256, 0x7ea71c4d, 0x560ce5df, 0xeeba289b, 0xa574c4e7, 0x9e04f6ee,
0x7860a5ec, 0x0b8db4a2, 0x968ba3d7, 0x0b6c77df, 0xd6f3157d, 0x402eff1a, 0x49b820b3, 0x8152aebb,
0xd180b0b6, 0x098604d4, 0x7ff92224, 0xede9c996, 0x89c58061, 0x829624c4, 0xc6e71ea7, 0xba94d915,
0x389c3cf6, 0x5b4c5a06, 0x04b335e6, 0x516a8aab, 0x42c8d7d9, 0x92b12af6, 0x86c8549f, 0xfda98acf,
0x819673b6, 0x69545dac, 0x6feaa230, 0x726e6d3f, 0x886ebdfe, 0x34f5730a, 0x7af63ba2, 0x77307bbf,
0x7cd80630, 0x6e45efe0, 0x7f8ad7eb, 0x59d7df99, 0x86c70946, 0xda233629, 0x753f6cbf, 0x825eeb40,
};

View File

@@ -1,115 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: statname.h,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* statname.h - name mangling macros for static linking
**************************************************************************************/
#ifndef _STATNAME_H
#define _STATNAME_H
/* define STAT_PREFIX to a unique name for static linking
* all the C functions and global variables will be mangled by the preprocessor
* e.g. void DCT4(...) becomes void raac_DCT4(...)
*/
#define STAT_PREFIX raac
#define STATCC1(x,y,z) STATCC2(x,y,z)
#define STATCC2(x,y,z) x##y##z
#ifdef STAT_PREFIX
#define STATNAME(func) STATCC1(STAT_PREFIX, _, func)
#else
#define STATNAME(func) func
#endif
/* these symbols are common to all implementations */
#define AllocateBuffers STATNAME(AllocateBuffers)
#define FreeBuffers STATNAME(FreeBuffers)
#define ClearBuffer STATNAME(ClearBuffer)
#define SetRawBlockParams STATNAME(SetRawBlockParams)
#define PrepareRawBlock STATNAME(PrepareRawBlock)
#define FlushCodec STATNAME(FlushCodec)
#define UnpackADTSHeader STATNAME(UnpackADTSHeader)
#define GetADTSChannelMapping STATNAME(GetADTSChannelMapping)
#define UnpackADIFHeader STATNAME(UnpackADIFHeader)
#define DecodeNextElement STATNAME(DecodeNextElement)
#define DecodeNoiselessData STATNAME(DecodeNoiselessData)
#define Dequantize STATNAME(Dequantize)
#define StereoProcess STATNAME(StereoProcess)
#define DeinterleaveShortBlocks STATNAME(DeinterleaveShortBlocks)
#define PNS STATNAME(PNS)
#define TNSFilter STATNAME(TNSFilter)
#define IMDCT STATNAME(IMDCT)
#define InitSBR STATNAME(InitSBR)
#define DecodeSBRBitstream STATNAME(DecodeSBRBitstream)
#define DecodeSBRData STATNAME(DecodeSBRData)
#define FreeSBR STATNAME(FreeSBR)
#define FlushCodecSBR STATNAME(FlushCodecSBR)
/* global ROM tables */
#define sampRateTab STATNAME(sampRateTab)
#define predSFBMax STATNAME(predSFBMax)
#define channelMapTab STATNAME(channelMapTab)
#define elementNumChans STATNAME(elementNumChans)
#define sfBandTotalShort STATNAME(sfBandTotalShort)
#define sfBandTotalLong STATNAME(sfBandTotalLong)
#define sfBandTabShortOffset STATNAME(sfBandTabShortOffset)
#define sfBandTabShort STATNAME(sfBandTabShort)
#define sfBandTabLongOffset STATNAME(sfBandTabLongOffset)
#define sfBandTabLong STATNAME(sfBandTabLong)
#define tnsMaxBandsShortOffset STATNAME(tnsMaxBandsShortOffset)
#define tnsMaxBandsShort STATNAME(tnsMaxBandsShort)
#define tnsMaxOrderShort STATNAME(tnsMaxOrderShort)
#define tnsMaxBandsLongOffset STATNAME(tnsMaxBandsLongOffset)
#define tnsMaxBandsLong STATNAME(tnsMaxBandsLong)
#define tnsMaxOrderLong STATNAME(tnsMaxOrderLong)
/* in your implementation's top-level include file (e.g. real\coder.h) you should
* add new #define sym STATNAME(sym) lines for all the
* additional global functions or variables which your
* implementation uses
*/
#endif /* _STATNAME_H */

View File

@@ -1,246 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: stproc.c,v 1.3 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
*
* stproc.c - mid-side and intensity stereo processing
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/* pow14[0][i] = -pow(2, i/4.0)
* pow14[1][i] = +pow(2, i/4.0)
*
* i = [0,1,2,3]
* format = Q30
*/
/**************************************************************************************
* Function: StereoProcessGroup
*
* Description: apply mid-side and intensity stereo to group of transform coefficients
*
* Inputs: dequantized transform coefficients for both channels
* pointer to appropriate scalefactor band table
* mid-side mask enabled flag
* buffer with mid-side mask (one bit for each scalefactor band)
* bit offset into mid-side mask buffer
* max coded scalefactor band
* buffer of codebook indices for right channel
* buffer of scalefactors for right channel, range = [0, 256]
*
* Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF)
* updated minimum guard bit count for both channels
*
* Return: none
*
* Notes: assume no guard bits in input
* gains 0 int bits
**************************************************************************************/
static void StereoProcessGroup(int *coefL, int *coefR, const /*short*/ int *sfbTab,
int msMaskPres, unsigned char *msMaskPtr, int msMaskOffset, int maxSFB,
unsigned char *cbRight, short *sfRight, int *gbCurrent)
{
//fb
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
static const int pow14[2][4] PROGMEM = {
{ 0xc0000000, 0xb3e407d7, 0xa57d8666, 0x945d819b },
{ 0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65 }
};
#pragma GCC diagnostic pop
int sfb, width, cbIdx, sf, cl, cr, scalef, scalei;
int gbMaskL, gbMaskR;
unsigned char msMask;
msMask = (*msMaskPtr++) >> msMaskOffset;
gbMaskL = 0;
gbMaskR = 0;
for (sfb = 0; sfb < maxSFB; sfb++) {
width = sfbTab[sfb+1] - sfbTab[sfb]; /* assume >= 0 (see sfBandTabLong/sfBandTabShort) */
cbIdx = cbRight[sfb];
if (cbIdx == 14 || cbIdx == 15) {
/* intensity stereo */
if (msMaskPres == 1 && (msMask & 0x01))
cbIdx ^= 0x01; /* invert_intensity(): 14 becomes 15, or 15 becomes 14 */
sf = -sfRight[sfb]; /* negative since we use identity 0.5^(x) = 2^(-x) (see spec) */
cbIdx &= 0x01; /* choose - or + scale factor */
scalef = pow14[cbIdx][sf & 0x03];
scalei = (sf >> 2) + 2; /* +2 to compensate for scalef = Q30 */
if (scalei > 0) {
if (scalei > 30)
scalei = 30;
do {
cr = MULSHIFT32(*coefL++, scalef);
CLIP_2N(cr, 31-scalei);
cr <<= scalei;
gbMaskR |= FASTABS(cr);
*coefR++ = cr;
} while (--width);
} else {
scalei = -scalei;
if (scalei > 31)
scalei = 31;
do {
cr = MULSHIFT32(*coefL++, scalef) >> scalei;
gbMaskR |= FASTABS(cr);
*coefR++ = cr;
} while (--width);
}
} else if ( cbIdx != 13 && ((msMaskPres == 1 && (msMask & 0x01)) || msMaskPres == 2) ) {
/* mid-side stereo (assumes no GB in inputs) */
do {
cl = *coefL;
cr = *coefR;
if ( (FASTABS(cl) | FASTABS(cr)) >> 30 ) {
/* avoid overflow (rare) */
cl >>= 1;
sf = cl + (cr >> 1); CLIP_2N(sf, 30); sf <<= 1;
cl = cl - (cr >> 1); CLIP_2N(cl, 30); cl <<= 1;
} else {
/* usual case */
sf = cl + cr;
cl -= cr;
}
*coefL++ = sf;
gbMaskL |= FASTABS(sf);
*coefR++ = cl;
gbMaskR |= FASTABS(cl);
} while (--width);
} else {
/* nothing to do */
coefL += width;
coefR += width;
}
/* get next mask bit (should be branchless on ARM) */
msMask >>= 1;
if (++msMaskOffset == 8) {
msMask = *msMaskPtr++;
msMaskOffset = 0;
}
}
cl = CLZ(gbMaskL) - 1;
if (gbCurrent[0] > cl)
gbCurrent[0] = cl;
cr = CLZ(gbMaskR) - 1;
if (gbCurrent[1] > cr)
gbCurrent[1] = cr;
return;
}
/**************************************************************************************
* Function: StereoProcess
*
* Description: apply mid-side and intensity stereo, if enabled
*
* Inputs: valid AACDecInfo struct (including dequantized transform coefficients)
*
* Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF)
* updated minimum guard bit count for both channels
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
int StereoProcess(AACDecInfo *aacDecInfo)
{
PSInfoBase *psi;
ICSInfo *icsInfo;
int gp, win, nSamps, msMaskOffset;
int *coefL, *coefR;
unsigned char *msMaskPtr;
const /*short*/ int *sfbTab;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* mid-side and intensity stereo require common_window == 1 (see MPEG4 spec, Correction 2, 2004) */
if (psi->commonWin != 1 || aacDecInfo->currBlockID != AAC_ID_CPE)
return 0;
/* nothing to do */
if (!psi->msMaskPresent && !psi->intensityUsed[1])
return 0;
icsInfo = &(psi->icsInfo[0]);
if (icsInfo->winSequence == 2) {
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
nSamps = NSAMPS_SHORT;
} else {
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
nSamps = NSAMPS_LONG;
}
coefL = psi->coef[0];
coefR = psi->coef[1];
/* do fused mid-side/intensity processing for each block (one long or eight short) */
msMaskOffset = 0;
msMaskPtr = psi->msMaskBits;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
StereoProcessGroup(coefL, coefR, sfbTab, psi->msMaskPresent,
msMaskPtr, msMaskOffset, icsInfo->maxSFB, psi->sfbCodeBook[1] + gp*icsInfo->maxSFB,
psi->scaleFactors[1] + gp*icsInfo->maxSFB, psi->gbCurrent);
coefL += nSamps;
coefR += nSamps;
}
/* we use one bit per sfb, so there are maxSFB bits for each window group */
msMaskPtr += (msMaskOffset + icsInfo->maxSFB) >> 3;
msMaskOffset = (msMaskOffset + icsInfo->maxSFB) & 0x07;
}
ASSERT(coefL == psi->coef[0] + 1024);
ASSERT(coefR == psi->coef[1] + 1024);
return 0;
}

View File

@@ -1,300 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: tns.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
*
* tns.c - apply TNS to spectrum
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define FBITS_LPC_COEFS 20
//fb
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
/* inverse quantization tables for TNS filter coefficients, format = Q31
* see bottom of file for table generation
* negative (vs. spec) since we use MADD for filter kernel
*/
static const int invQuant3[16] PROGMEM = {
0x00000000, 0xc8767f65, 0x9becf22c, 0x83358feb, 0x83358feb, 0x9becf22c, 0xc8767f65, 0x00000000,
0x2bc750e9, 0x5246dd49, 0x6ed9eba1, 0x7e0e2e32, 0x7e0e2e32, 0x6ed9eba1, 0x5246dd49, 0x2bc750e9,
};
static const int invQuant4[16] PROGMEM = {
0x00000000, 0xe5632654, 0xcbf00dbe, 0xb4c373ee, 0xa0e0a15f, 0x9126145f, 0x8643c7b3, 0x80b381ac,
0x7f7437ad, 0x7b1d1a49, 0x7294b5f2, 0x66256db2, 0x563ba8aa, 0x4362210e, 0x2e3d2abb, 0x17851aad,
};
#pragma GCC diagnostic pop
/**************************************************************************************
* Function: DecodeLPCCoefs
*
* Description: decode LPC coefficients for TNS
*
* Inputs: order of TNS filter
* resolution of coefficients (3 or 4 bits)
* coefficients unpacked from bitstream
* scratch buffer (b) of size >= order
*
* Outputs: LPC coefficients in Q(FBITS_LPC_COEFS), in 'a'
*
* Return: none
*
* Notes: assumes no guard bits in input transform coefficients
* a[i] = Q(FBITS_LPC_COEFS), don't store a0 = 1.0
* (so a[0] = first delay tap, etc.)
* max abs(a[i]) < log2(order), so for max order = 20 a[i] < 4.4
* (up to 3 bits of gain) so a[i] has at least 31 - FBITS_LPC_COEFS - 3
* guard bits
* to ensure no intermediate overflow in all-pole filter, set
* FBITS_LPC_COEFS such that number of guard bits >= log2(max order)
**************************************************************************************/
static void DecodeLPCCoefs(int order, int res, signed char *filtCoef, int *a, int *b)
{
int i, m, t;
const int *invQuantTab;
if (res == 3) invQuantTab = invQuant3;
else if (res == 4) invQuantTab = invQuant4;
else return;
for (m = 0; m < order; m++) {
t = invQuantTab[filtCoef[m] & 0x0f]; /* t = Q31 */
for (i = 0; i < m; i++)
b[i] = a[i] - (MULSHIFT32(t, a[m-i-1]) << 1);
for (i = 0; i < m; i++)
a[i] = b[i];
a[m] = t >> (31 - FBITS_LPC_COEFS);
}
}
/**************************************************************************************
* Function: FilterRegion
*
* Description: apply LPC filter to one region of coefficients
*
* Inputs: number of transform coefficients in this region
* direction flag (forward = 1, backward = -1)
* order of filter
* 'size' transform coefficients
* 'order' LPC coefficients in Q(FBITS_LPC_COEFS)
* scratch buffer for history (must be >= order samples long)
*
* Outputs: filtered transform coefficients
*
* Return: guard bit mask (OR of abs value of all filtered transform coefs)
*
* Notes: assumes no guard bits in input transform coefficients
* gains 0 int bits
* history buffer does not need to be preserved between regions
**************************************************************************************/
static int FilterRegion(int size, int dir, int order, int *audioCoef, int *a, int *hist)
{
int i, j, y, hi32, inc, gbMask;
U64 sum64;
/* init history to 0 every time */
for (i = 0; i < order; i++)
hist[i] = 0;
sum64.w64 = 0; /* avoid warning */
gbMask = 0;
inc = (dir ? -1 : 1);
do {
/* sum64 = a0*y[n] = 1.0*y[n] */
y = *audioCoef;
sum64.r.hi32 = y >> (32 - FBITS_LPC_COEFS);
sum64.r.lo32 = y << FBITS_LPC_COEFS;
/* sum64 += (a1*y[n-1] + a2*y[n-2] + ... + a[order-1]*y[n-(order-1)]) */
for (j = order - 1; j > 0; j--) {
sum64.w64 = MADD64(sum64.w64, hist[j], a[j]);
hist[j] = hist[j-1];
}
sum64.w64 = MADD64(sum64.w64, hist[0], a[0]);
y = (sum64.r.hi32 << (32 - FBITS_LPC_COEFS)) | (sum64.r.lo32 >> FBITS_LPC_COEFS);
/* clip output (rare) */
hi32 = sum64.r.hi32;
if ((hi32 >> 31) != (hi32 >> (FBITS_LPC_COEFS-1)))
y = (hi32 >> 31) ^ 0x7fffffff;
hist[0] = y;
*audioCoef = y;
audioCoef += inc;
gbMask |= FASTABS(y);
} while (--size);
return gbMask;
}
/**************************************************************************************
* Function: TNSFilter
*
* Description: apply temporal noise shaping, if enabled
*
* Inputs: valid AACDecInfo struct
* index of current channel
*
* Outputs: updated transform coefficients
* updated minimum guard bit count for this channel
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
int TNSFilter(AACDecInfo *aacDecInfo, int ch)
{
int win, winLen, nWindows, nSFB, filt, bottom, top, order, maxOrder, dir;
int start, end, size, tnsMaxBand, numFilt, gbMask;
int *audioCoef;
unsigned char *filtLength, *filtOrder, *filtRes, *filtDir;
signed char *filtCoef;
const unsigned /*char*/ int *tnsMaxBandTab;
const /*short*/ int *sfbTab;
ICSInfo *icsInfo;
TNSInfo *ti;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
ti = &psi->tnsInfo[ch];
if (!ti->tnsDataPresent)
return 0;
if (icsInfo->winSequence == 2) {
nWindows = NWINDOWS_SHORT;
winLen = NSAMPS_SHORT;
nSFB = sfBandTotalShort[psi->sampRateIdx];
maxOrder = tnsMaxOrderShort[aacDecInfo->profile];
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
tnsMaxBandTab = tnsMaxBandsShort + tnsMaxBandsShortOffset[aacDecInfo->profile];
tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
} else {
nWindows = NWINDOWS_LONG;
winLen = NSAMPS_LONG;
nSFB = sfBandTotalLong[psi->sampRateIdx];
maxOrder = tnsMaxOrderLong[aacDecInfo->profile];
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
tnsMaxBandTab = tnsMaxBandsLong + tnsMaxBandsLongOffset[aacDecInfo->profile];
tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
}
if (tnsMaxBand > icsInfo->maxSFB)
tnsMaxBand = icsInfo->maxSFB;
filtRes = ti->coefRes;
filtLength = ti->length;
filtOrder = ti->order;
filtDir = ti->dir;
filtCoef = ti->coef;
gbMask = 0;
audioCoef = psi->coef[ch];
for (win = 0; win < nWindows; win++) {
bottom = nSFB;
numFilt = ti->numFilt[win];
for (filt = 0; filt < numFilt; filt++) {
top = bottom;
bottom = top - *filtLength++;
bottom = MAX(bottom, 0);
order = *filtOrder++;
order = MIN(order, maxOrder);
if (order) {
start = sfbTab[MIN(bottom, tnsMaxBand)];
end = sfbTab[MIN(top, tnsMaxBand)];
size = end - start;
if (size > 0) {
dir = *filtDir++;
if (dir)
start = end - 1;
DecodeLPCCoefs(order, filtRes[win], filtCoef, psi->tnsLPCBuf, psi->tnsWorkBuf);
gbMask |= FilterRegion(size, dir, order, audioCoef + start, psi->tnsLPCBuf, psi->tnsWorkBuf);
}
filtCoef += order;
}
}
audioCoef += winLen;
}
/* update guard bit count if necessary */
size = CLZ(gbMask) - 1;
if (psi->gbCurrent[ch] > size)
psi->gbCurrent[ch] = size;
return 0;
}
/* Code to generate invQuantXXX[] tables
* {
* int res, i, t;
* double powScale, iqfac, iqfac_m, d;
*
* powScale = pow(2.0, 31) * -1.0; / ** make coefficients negative for using MADD in kernel ** /
* for (res = 3; res <= 4; res++) {
* iqfac = ( ((1 << (res-1)) - 0.5) * (2.0 / M_PI) );
* iqfac_m = ( ((1 << (res-1)) + 0.5) * (2.0 / M_PI) );
* printf("static const int invQuant%d[16] = {\n", res);
* for (i = 0; i < 16; i++) {
* / ** extend bottom 4 bits into signed, 2's complement number ** /
* t = (i << 28) >> 28;
*
* if (t >= 0) d = sin(t / iqfac);
* else d = sin(t / iqfac_m);
*
* d *= powScale;
* printf("0x%08x, ", (int)(d > 0 ? d + 0.5 : d - 0.5));
* if ((i & 0x07) == 0x07)
* printf("\n");
* }
* printf("};\n\n");
* }
* }
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
The contents of this directory, and (except where otherwise
indicated) the directories included within this directory, are
subject to the current version of the RealNetworks Public Source
License (the "RPSL") available at RPSL.txt in this directory, unless
you have licensed the directory under the current version of the
RealNetworks Community Source License (the "RCSL") available at
RCSL.txt in this directory, in which case the RCSL will apply. You
may also obtain the license terms directly from RealNetworks. You
may not use the files in this directory except in compliance with the
RPSL or, if you have a valid RCSL with RealNetworks applicable to
this directory, the RCSL. Please see the applicable RPSL or RCSL for
the rights, obligations and limitations governing use of the contents
of the directory.
This directory 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 directory, and the directories included with this directory, are
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

View File

@@ -1,948 +0,0 @@
The RCSL is made up of a base agreement and a few Attachments.
For Research and Development use, you agree to the terms of the
RCSL R&D License (base RCSL and Attachments A, B, and C)
For Commercial Use (either distribution or internal commercial
deployment) of the Helix DNA with or without support for RealNetworks'
RealAudio and RealVideo Add-on Technology, you agree to the
terms of the same RCSL R&D license
and execute one or more additional Commercial Use License attachments
<see http://www.helixcommunity.org/content/rcsl-attachments>.
------------------------------------------------------------------------
REALNETWORKS COMMUNITY SOURCE LICENSE
Version 1.2 (Rev. Date: January 22, 2003).
RECITALS
Original Contributor has developed Specifications, Source Code
implementations and Executables of certain Technology; and
Original Contributor desires to license the Technology to a large
community to facilitate research, innovation and product development
while maintaining compatibility of such products with the Technology as
delivered by Original Contributor; and
Original Contributor desires to license certain Trademarks for the
purpose of branding products that are compatible with the relevant
Technology delivered by Original Contributor; and
You desire to license the Technology and possibly certain Trademarks
from Original Contributor on the terms and conditions specified in this
License.
In consideration for the mutual covenants contained herein, You and
Original Contributor agree as follows:
AGREEMENT
*1. Introduction.*
The RealNetworks Community Source License ("RCSL") and effective
attachments ("License") may include five distinct licenses:
i) Research Use license -- License plus Attachments A, B and C only.
ii) Commercial Use and Trademark License, which may be for Internal
Deployment Use or external distribution, or both -- License plus
Attachments A, B, C, and D.
iii) Technology Compatibility Kit (TCK) license -- Attachment C.
iv) Add-On Technology License (Executable) Commercial Use License
-Attachment F.
v) Add-On Technology Source Code Porting and Optimization
License-Attachment G.
The Research Use license is effective when You click and accept this
License. The TCK is effective when You click and accept this License,
unless otherwise specified in the TCK attachments. The Commercial Use
and Trademark, Add-On Technology License, and the Add-On Technology
Source Code Porting and Optimization licenses must each be signed by You
and Original Contributor to become effective. Once effective, these
licenses and the associated requirements and responsibilities are
cumulative. Capitalized terms used in this License are defined in the
Glossary.
*2. License Grants.*
2.1 Original Contributor Grant.
Subject to Your compliance with Sections 3, 8.10 and Attachment A of
this License, Original Contributor grants to You a worldwide,
royalty-free, non-exclusive license, to the extent of Original
Contributor's Intellectual Property Rights covering the Original Code,
Upgraded Code and Specifications, to do the following:
(a) Research Use License:
(i) use, reproduce and modify the Original Code, Upgraded Code and
Specifications to create Modifications and Reformatted Specifications
for Research Use by You;
(ii) publish and display Original Code, Upgraded Code and Specifications
with, or as part of Modifications, as permitted under Section 3.1(b) below;
(iii) reproduce and distribute copies of Original Code and Upgraded Code
to Licensees and students for Research Use by You;
(iv) compile, reproduce and distribute Original Code and Upgraded Code
in Executable form, and Reformatted Specifications to anyone for
Research Use by You.
(b) Other than the licenses expressly granted in this License, Original
Contributor retains all right, title, and interest in Original Code and
Upgraded Code and Specifications.
2.2 Your Grants.
(a) To Other Licensees. You hereby grant to each Licensee a license to
Your Error Corrections and Shared Modifications, of the same scope and
extent as Original Contributor's licenses under Section 2.1 a) above
relative to Research Use and Attachment D relative to Commercial Use.
(b) To Original Contributor. You hereby grant to Original Contributor a
worldwide, royalty-free, non-exclusive, perpetual and irrevocable
license, to the extent of Your Intellectual Property Rights covering
Your Error Corrections, Shared Modifications and Reformatted
Specifications, to use, reproduce, modify, display and distribute Your
Error Corrections, Shared Modifications and Reformatted Specifications,
in any form, including the right to sublicense such rights through
multiple tiers of distribution.
(c) Other than the licenses expressly granted in Sections 2.2(a) and (b)
above, and the restrictions set forth in Section 3.1(d)(iv) below, You
retain all right, title, and interest in Your Error Corrections, Shared
Modifications and Reformatted Specifications.
2.3 Contributor Modifications.
You may use, reproduce, modify, display and distribute Contributor Error
Corrections, Shared Modifications and Reformatted Specifications,
obtained by You under this License, to the same scope and extent as with
Original Code, Upgraded Code and Specifications.
2.4 Subcontracting.
You may deliver the Source Code of Covered Code to other Licensees
having at least a Research Use license, for the sole purpose of
furnishing development services to You in connection with Your rights
granted in this License. All such Licensees must execute appropriate
documents with respect to such work consistent with the terms of this
License, and acknowledging their work-made-for-hire status or assigning
exclusive right to the work product and associated Intellectual Property
Rights to You.
*3. Requirements and Responsibilities*.
3.1 Research Use License.
As a condition of exercising the rights granted under Section 2.1(a)
above, You agree to comply with the following:
(a) Your Contribution to the Community. All Error Corrections and Shared
Modifications which You create or contribute to are automatically
subject to the licenses granted under Section 2.2 above. You are
encouraged to license all of Your other Modifications under Section 2.2
as Shared Modifications, but are not required to do so. You agree to
notify Original Contributor of any errors in the Specification.
(b) Source Code Availability. You agree to provide all Your Error
Corrections to Original Contributor as soon as reasonably practicable
and, in any event, prior to Internal Deployment Use or Commercial Use,
if applicable. Original Contributor may, at its discretion, post Source
Code for Your Error Corrections and Shared Modifications on the
Community Webserver. You may also post Error Corrections and Shared
Modifications on a web-server of Your choice; provided, that You must
take reasonable precautions to ensure that only Licensees have access to
such Error Corrections and Shared Modifications. Such precautions shall
include, without limitation, a password protection scheme limited to
Licensees and a click-on, download certification of Licensee status
required of those attempting to download from the server. An example of
an acceptable certification is attached as Attachment A-2.
(c) Notices. All Error Corrections and Shared Modifications You create
or contribute to must include a file documenting the additions and
changes You made and the date of such additions and changes. You must
also include the notice set forth in Attachment A-1 in the file header.
If it is not possible to put the notice in a particular Source Code file
due to its structure, then You must include the notice in a location
(such as a relevant directory file), where a recipient would be most
likely to look for such a notice.
(d) Redistribution.
(i) Source. Covered Code may be distributed in Source Code form only to
another Licensee (except for students as provided below). You may not
offer or impose any terms on any Covered Code that alter the rights,
requirements, or responsibilities of such Licensee. You may distribute
Covered Code to students for use in connection with their course work
and research projects undertaken at accredited educational institutions.
Such students need not be Licensees, but must be given a copy of the
notice set forth in Attachment A-3 and such notice must also be included
in a file header or prominent location in the Source Code made available
to such students.
(ii) Executable. You may distribute Executable version(s) of Covered
Code to Licensees and other third parties only for the purpose of
evaluation and comment in connection with Research Use by You and under
a license of Your choice, but which limits use of such Executable
version(s) of Covered Code only to that purpose.
(iii) Modified Class, Interface and Package Naming. In connection with
Research Use by You only, You may use Original Contributor's class,
Interface and package names only to accurately reference or invoke the
Source Code files You modify. Original Contributor grants to You a
limited license to the extent necessary for such purposes.
(iv) You expressly agree that any distribution, in whole or in part, of
Modifications developed by You shall only be done pursuant to the terms
and conditions of this License.
(e) Extensions.
(i) Covered Code. You may not include any Source Code of Community Code
in any Extensions. You may include the compiled Header Files of
Community Code in an Extension provided that Your use of the Covered
Code, including Heading Files, complies with the Commercial Use License,
the TCK and all other terms of this License.
(ii) Publication. No later than the date on which You first distribute
such Extension for Commercial Use, You must publish to the industry, on
a non-confidential basis and free of all copyright restrictions with
respect to reproduction and use, an accurate and current specification
for any Extension. In addition, You must make available an appropriate
test suite, pursuant to the same rights as the specification,
sufficiently detailed to allow any third party reasonably skilled in the
technology to produce implementations of the Extension compatible with
the specification. Such test suites must be made available as soon as
reasonably practicable but, in no event, later than ninety (90) days
after Your first Commercial Use of the Extension. You must use
reasonable efforts to promptly clarify and correct the specification and
the test suite upon written request by Original Contributor.
(iii) Open. You agree to refrain from enforcing any Intellectual
Property Rights You may have covering any interface(s) of Your
Extension, which would prevent the implementation of such interface(s)
by Original Contributor or any Licensee. This obligation does not
prevent You from enforcing any Intellectual Property Right You have that
would otherwise be infringed by an implementation of Your Extension.
(iv) Interface Modifications and Naming. You may not modify or add to
the GUID space * * "xxxxxxxx-0901-11d1-8B06-00A024406D59" or any other
GUID space designated by Original Contributor. You may not modify any
Interface prefix provided with the Covered Code or any other prefix
designated by Original Contributor.* *
* *
(f) You agree that any Specifications provided to You by Original
Contributor are confidential and proprietary information of Original
Contributor. You must maintain the confidentiality of the Specifications
and may not disclose them to any third party without Original
Contributor's prior written consent. You may only use the Specifications
under the terms of this License and only for the purpose of implementing
the terms of this License with respect to Covered Code. You agree not
use, copy or distribute any such Specifications except as provided in
writing by Original Contributor.
3.2 Commercial Use License.
You may not make Commercial Use of any Covered Code unless You and
Original Contributor have executed a copy of the Commercial Use and
Trademark License attached as Attachment D.
*4. Versions of the License.*
4.1 License Versions.
Original Contributor may publish revised versions of the License from
time to time. Each version will be given a distinguishing version number.
4.2 Effect.
Once a particular version of Covered Code has been provided under a
version of the License, You may always continue to use such Covered Code
under the terms of that version of the License. You may also choose to
use such Covered Code under the terms of any subsequent version of the
License. No one other than Original Contributor has the right to
promulgate License versions.
4.3 Multiple-Licensed Code.
Original Contributor may designate portions of the Covered Code as
"Multiple-Licensed." "Multiple-Licensed" means that the Original
Contributor permits You to utilize those designated portions of the
Covered Code under Your choice of this License or the alternative
license(s), if any, specified by the Original Contributor in an
Attachment to this License.
*5. Disclaimer of Warranty.*
5.1 COVERED CODE PROVIDED AS IS.
COVERED CODE IS PROVIDED UNDER THIS LICENSE "AS IS," WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT
FOR A PARTICULAR PURPOSE OR NON-INFRINGING. YOU AGREE TO BEAR THE ENTIRE
RISK IN CONNECTION WITH YOUR USE AND DISTRIBUTION OF COVERED CODE UNDER
THIS LICENSE. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART
OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER
EXCEPT SUBJECT TO THIS DISCLAIMER.
5.2 Not Designed for High Risk Activities.
You acknowledge that Original Code, Upgraded Code and Specifications are
not designed or intended for use in high risk activities including, but
not limited to: (i) on-line control of aircraft, air traffic, aircraft
navigation or aircraft communications; or (ii) in the design,
construction, operation or maintenance of any nuclear facility. Original
Contributor disclaims any express or implied warranty of fitness for
such uses.
*6. Termination.*
6.1 By You.
You may terminate this Research Use license at anytime by providing
written notice to Original Contributor.
6.2 By Original Contributor.
This License and the rights granted hereunder will terminate:
(i) automatically if You fail to comply with the terms of this License
and fail to cure such breach within 30 days of receipt of written notice
of the breach;
(ii) immediately in the event of circumstances specified in Sections 7.1
and 8.4; or
(iii) at Original Contributor's discretion upon any action initiated by
You (including by cross-claim or counter claim) alleging that use or
distribution by Original Contributor or any Licensee, of Original Code,
Upgraded Code, Error Corrections, Shared Modifications or Specifications
infringe a patent owned or controlled by You.
6.3 Effective of Termination.
Upon termination, You agree to discontinue use of and destroy all copies
of Covered Code in Your possession. All sublicenses to the Covered Code
which You have properly granted shall survive any termination of this
License. Provisions that, by their nature, should remain in effect
beyond the termination of this License shall survive including, without
limitation, Sections 2.2, 3, 5, 7 and 8.
6.4 No Compensation.
Each party waives and releases the other from any claim to compensation
or indemnity for permitted or lawful termination of the business
relationship established by this License.
*7. Liability.*
7.1 Infringement. Should any of the Original Code, Upgraded Code, TCK or
Specifications ("Materials") become the subject of a claim of
infringement, Original Contributor may, at its sole option, (i) attempt
to procure the rights necessary for You to continue using the Materials,
(ii) modify the Materials so that they are no longer infringing, or
(iii) terminate Your right to use the Materials, immediately upon
written notice, and refund to You the amount, if any, having then
actually been paid by You to Original Contributor for the Original Code,
Upgraded Code and TCK, depreciated on a straight line, five year basis.
7.2 LIMITATION OF LIABILITY. TO THE FULL EXTENT ALLOWED BY APPLICABLE
LAW, ORIGINAL CONTRIBUTOR'S LIABILITY TO YOU FOR CLAIMS RELATING TO THIS
LICENSE, WHETHER FOR BREACH OR IN TORT, SHALL BE LIMITED TO ONE HUNDRED
PERCENT (100%) OF THE AMOUNT HAVING THEN ACTUALLY BEEN PAID BY YOU TO
ORIGINAL CONTRIBUTOR FOR ALL COPIES LICENSED HEREUNDER OF THE PARTICULAR
ITEMS GIVING RISE TO SUCH CLAIM, IF ANY, DURING THE TWELVE MONTHS
PRECEDING THE CLAIMED BREACH. IN NO EVENT WILL YOU (RELATIVE TO YOUR
SHARED MODIFICATIONS OR ERROR CORRECTIONS) OR ORIGINAL CONTRIBUTOR BE
LIABLE FOR ANY INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES IN CONNECTION WITH OR RISING OUT OF THIS LICENSE (INCLUDING,
WITHOUT LIMITATION, LOSS OF PROFITS, USE, DATA, OR OTHER ECONOMIC
ADVANTAGE), HOWEVER IT ARISES AND ON ANY THEORY OF LIABILITY, WHETHER IN
AN ACTION FOR CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE)
OR OTHERWISE, WHETHER OR NOT YOU OR ORIGINAL CONTRIBUTOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE AND NOTWITHSTANDING THE
FAILURE OF ESSENTIAL PURPOSE OF ANY REMEDY.
*8. Miscellaneous.*
8.1 Trademark.
You shall not use any Trademark unless You and Original Contributor
execute a copy of the Commercial Use and Trademark License Agreement
attached hereto as Attachment D. Except as expressly provided in the
License, You are granted no right, title or license to, or interest in,
any Trademarks. Whether or not You and Original Contributor enter into
the Trademark License, You agree not to (i) challenge Original
Contributor's ownership or use of Trademarks; (ii) attempt to register
any Trademarks, or any mark or logo substantially similar thereto; or
(iii) incorporate any Trademarks into Your own trademarks, product
names, service marks, company names, or domain names.
8.2 Integration.
This License represents the complete agreement concerning the subject
matter hereof.
8.3 Assignment.
Original Contributor may assign this License, and its rights and
obligations hereunder, in its sole discretion. You may assign the
Research Use portions of this License and the TCK license to a third
party upon prior written notice to Original Contributor (which may be
provided electronically via the Community Web-Server). You may not
assign the Commercial Use and Trademark license, the Add-On Technology
License, or the Add-On Technology Source Code Porting License, including
by way of merger (regardless of whether You are the surviving entity) or
acquisition, without Original Contributor's prior written consent.
8.4 Severability.
If any provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to make it
enforceable. Notwithstanding the foregoing, if You are prohibited by law
from fully and specifically complying with Sections 2.2 or 3, this
License will immediately terminate and You must immediately discontinue
any use of Covered Code.
8.5 Governing Law.
This License shall be governed by the laws of the United States and the
State of Washington, as applied to contracts entered into and to be
performed in Washington between Washington residents. The application of
the United Nations Convention on Contracts for the International Sale of
Goods is expressly excluded. You agree that the state and federal courts
located in Seattle, Washington have exclusive jurisdiction over any
claim relating to the License, including contract and tort claims.
8.6 Dispute Resolution.
a) Arbitration. Any dispute arising out of or relating to this License
shall be finally settled by arbitration as set out herein, except that
either party may bring any action, in a court of competent jurisdiction
(which jurisdiction shall be exclusive), with respect to any dispute
relating to such party's Intellectual Property Rights or with respect to
Your compliance with the TCK license. Arbitration shall be administered:
(i) by the American Arbitration Association (AAA), (ii) in accordance
with the rules of the United Nations Commission on International Trade
Law (UNCITRAL) (the "Rules") in effect at the time of arbitration as
modified herein; and (iii) the arbitrator will apply the substantive
laws of Washington and the United States. Judgment upon the award
rendered by the arbitrator may be entered in any court having
jurisdiction to enforce such award.
b) Arbitration language, venue and damages. All arbitration proceedings
shall be conducted in English by a single arbitrator selected in
accordance with the Rules, who must be fluent in English and be either a
retired judge or practicing attorney having at least ten (10) years
litigation experience and be reasonably familiar with the technology
matters relative to the dispute. Unless otherwise agreed, arbitration
venue shall be in Seattle, Washington. The arbitrator may award monetary
damages only and nothing shall preclude either party from seeking
provisional or emergency relief from a court of competent jurisdiction.
The arbitrator shall have no authority to award damages in excess of
those permitted in this License and any such award in excess is void.
All awards will be payable in U.S. dollars and may include, for the
prevailing party (i) pre-judgment award interest, (ii) reasonable
attorneys' fees incurred in connection with the arbitration, and (iii)
reasonable costs and expenses incurred in enforcing the award. The
arbitrator will order each party to produce identified documents and
respond to no more than twenty-five single question interrogatories.
8.7 Construction.
Any law or regulation, which provides that the language of a contract
shall be construed against the drafter, shall not apply to this License.
8.8 U.S. Government End Users.
The Covered Code is a "commercial item," as that term is defined in 48
C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software"
and "commercial computer software documentation," as such terms are used
in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and
48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government
End Users acquire Covered Code with only those rights set forth herein.
You agree to pass this notice to our licensees.
8.9 Marketing Activities.
Licensee hereby grants Original Contributor a non-exclusive,
non-transferable, limited license to use the Licensee's company name and
logo ("Licensee Marks") in any presentations, press releases, or
marketing materials solely for the purpose of identifying Licensee as a
member of the Helix Community. Licensee shall provide samples of
Licensee Marks to Original Contributor upon request by Original
Contributor. Original Contributor acknowledges that the Licensee Marks
are the trademarks of Licensee. Original Contributor shall not use the
Licensee Marks in a way that may imply that Original Contributor is an
agency or branch of Licensee. Original Contributor understands and
agrees that the use of any Licensee Marks in connection with this
Agreement shall not create any right, title or interest, in, or to the
Licensee Marks or any Licensee trademarks and that all such use and
goodwill associated with any such trademarks will inure to the benefit
of Licensee. Further the Original Contributor will stop usage of the
Licensee Marks upon Licensee's request.
8.10 Press Announcements.
You may make press announcements or other public statements regarding
this License without the prior written consent of the Original
Contributor, if Your statement is limited to announcing the licensing of
the Covered Code or the availability of Your Product and its
compatibility with the Covered Code. All other public announcements
regarding this license require the prior written consent of the Original
Contributor. Consent requests are welcome at press@helixcommunity.org.
8.11 International Use.
a) Export/Import laws. Covered Code is subject to U.S. export control
laws and may be subject to export or import regulations in other
countries. Each party agrees to comply strictly with all such laws and
regulations and acknowledges their responsibility to obtain such
licenses to export, re-export, or import as may be required. You agree
to pass these obligations to Your licensees.
b) Intellectual Property Protection. Due to limited intellectual
property protection and enforcement in certain countries, You agree not
to redistribute the Original Code, Upgraded Code, TCK and Specifications
to any country on the list of restricted countries on the Community Web
Server.
8.12 Language.
This License is in the English language only, which language shall be
controlling in all respects, and all versions of this License in any
other language shall be for accommodation only and shall not be binding
on the parties to this License. All communications and notices made or
given pursuant to this License, and all documentation and support to be
provided, unless otherwise noted, shall be in the English language.
PLEASE READ THE TERMS OF THIS LICENSE CAREFULLY. BY CLICKING ON THE
"ACCEPT" BUTTON BELOW YOU ARE ACCEPTING AND AGREEING TO THE TERMS AND
CONDITIONS OF THIS LICENSE WITH REALNETWORKS, INC. IF YOU ARE AGREEING
TO THIS LICENSE ON BEHALF OF A COMPANY, YOU REPRESENT THAT YOU ARE
AUTHORIZED TO BIND THE COMPANY TO SUCH A LICENSE. WHETHER YOU ARE ACTING
ON YOUR OWN BEHALF, OR REPRESENTING A COMPANY, YOU MUST BE OF MAJORITY
AGE AND BE OTHERWISE COMPETENT TO ENTER INTO CONTRACTS. IF YOU DO NOT
MEET THIS CRITERIA OR YOU DO NOT AGREE TO ANY OF THE TERMS AND
CONDITIONS OF THIS LICENSE, CLICK ON THE REJECT BUTTON TO EXIT.
GLOSSARY
1. *"Added Value"* means code which:
(i) has a principal purpose which is substantially different from that
of the stand-alone Technology;
(ii) represents a significant functional and value enhancement to the
Technology;
(iii) operates in conjunction with the Technology; and
(iv) is not marketed as a technology which replaces or substitutes for
the Technology
2. "*Applicable Patent Rights*" mean: (a) in the case where Original
Contributor is the grantor of rights, claims of patents that (i) are now
or hereafter acquired, owned by or assigned to Original Contributor and
(ii) are necessarily infringed by using or making the Original Code or
Upgraded Code, including Modifications provided by Original Contributor,
alone and not in combination with other software or hardware; and (b) in
the case where Licensee is the grantor of rights, claims of patents that
(i) are now or hereafter acquired, owned by or assigned to Licensee and
(ii) are infringed (directly or indirectly) by using or making
Licensee's Modifications or Error Corrections, taken alone or in
combination with Covered Code.
3. "*Application Programming Interfaces (APIs)"* means the interfaces,
associated header files, service provider interfaces, and protocols that
enable a device, application, Operating System, or other program to
obtain services from or make requests of (or provide services in
response to requests from) other programs, and to use, benefit from, or
rely on the resources, facilities, and capabilities of the relevant
programs using the APIs. APIs includes the technical documentation
describing the APIs, the Source Code constituting the API, and any
Header Files used with the APIs.
4. "*Commercial Use*" means any use (internal or external), copying,
sublicensing or distribution (internal or external), directly or
indirectly of Covered Code by You other than Your Research Use of
Covered Code within Your business or organization or in conjunction with
other Licensees with equivalent Research Use rights. Commercial Use
includes any use of the Covered Code for direct or indirect commercial
or strategic gain, advantage or other business purpose. Any Commercial
Use requires execution of Attachment D by You and Original Contributor.
5. "*Community Code*" means the Original Code, Upgraded Code, Error
Corrections, Shared Modifications, or any combination thereof.
6. "*Community Webserver(s)"* means the webservers designated by
Original Contributor for access to the Original Code, Upgraded Code, TCK
and Specifications and for posting Error Corrections and Shared
Modifications.
7. "*Compliant Covered Code*" means Covered Code that complies with the
requirements of the TCK.
8. "*Contributor*" means each Licensee that creates or contributes to
the creation of any Error Correction or Shared Modification.
9. "*Covered Code*" means the Original Code, Upgraded Code,
Modifications, or any combination thereof.
10. "*Error Correction*" means any change made to Community Code which
conforms to the Specification and corrects the adverse effect of a
failure of Community Code to perform any function set forth in or
required by the Specifications.
11. "*Executable*" means Covered Code that has been converted from
Source Code to the preferred form for execution by a computer or digital
processor (e.g. binary form).
12. "*Extension(s)"* means any additional Interfaces developed by or for
You which: (i) are designed for use with the Technology; (ii) constitute
an API for a library of computing functions or services; and (iii) are
disclosed or otherwise made available to third party software developers
for the purpose of developing software which invokes such additional
Interfaces. The foregoing shall not apply to software developed by Your
subcontractors to be exclusively used by You.
13. "*Header File(s)"* means that portion of the Source Code that
provides the names and types of member functions, data members, class
definitions, and interface definitions necessary to implement the APIs
for the Covered Code. Header Files include, files specifically
designated by Original Contributor as Header Files. Header Files do not
include the code necessary to implement the functionality underlying the
Interface.
14. *"Helix DNA Server Technology"* means the program(s) that implement
the Helix Universal Server streaming engine for the Technology as
defined in the Specification.
15. *"Helix DNA Client Technology"* means the Covered Code that
implements the RealOne Player engine as defined in the Specification.
16. *"Helix DNA Producer Technology"* means the Covered Code that
implements the Helix Producer engine as defined in the Specification.
17. *"Helix DNA Technology"* means the Helix DNA Server Technology, the
Helix DNA Client Technology, the Helix DNA Producer Technology and other
Helix technologies designated by Original Contributor.
18. "*Intellectual Property Rights*" means worldwide statutory and
common law rights associated solely with (i) Applicable Patent Rights;
(ii) works of authorship including copyrights, copyright applications,
copyright registrations and "moral rights"; (iii) the protection of
trade and industrial secrets and confidential information; and (iv)
divisions, continuations, renewals, and re-issuances of the foregoing
now existing or acquired in the future.
19. *"Interface*" means interfaces, functions, properties, class
definitions, APIs, Header Files, GUIDs, V-Tables, and/or protocols
allowing one piece of software, firmware or hardware to communicate or
interoperate with another piece of software, firmware or hardware.
20. "*Internal Deployment Use*" means use of Compliant Covered Code
(excluding Research Use) within Your business or organization only by
Your employees and/or agents on behalf of Your business or organization,
but not to provide services, including content distribution, to third
parties, subject to execution of Attachment D by You and Original
Contributor, if required.
21. "*Licensee*" means any party that has entered into and has in effect
a version of this License with Original Contributor.
22. "*MIME type*" means a description of what type of media or other
content is in a file, including by way of example but not limited to
'audio/x-pn-realaudio-plugin.'
23. "*Modification(s)"* means (i) any addition to, deletion from and/or
change to the substance and/or structure of the Covered Code, including
Interfaces; (ii) the combination of any Covered Code and any previous
Modifications; (iii) any new file or other representation of computer
program statements that contains any portion of Covered Code; and/or
(iv) any new Source Code implementing any portion of the Specifications.
24. "*MP3 Patents*" means any patents necessary to make, use or sell
technology implementing any portion of the specification developed by
the Moving Picture Experts Group known as MPEG-1 Audio Layer-3 or MP3,
including but not limited to all past and future versions, profiles,
extensions, parts and amendments relating to the MP3 specification.
25. "*MPEG-4 Patents*" means any patents necessary to make, use or sell
technology implementing any portion of the specification developed by
the Moving Pictures Experts Group known as MPEG-4, including but not
limited to all past and future versions, profiles, extensions, parts and
amendments relating to the MPEG-4 specification.
26. "*Original Code*" means the initial Source Code for the Technology
as described on the Community Web Server.
27. "*Original Contributor*" means RealNetworks, Inc., its affiliates
and its successors and assigns.
28. "*Original Contributor MIME Type*" means the MIME registry, browser
preferences, or local file/protocol associations invoking any Helix DNA
Client-based application, including the RealOne Player, for playback of
RealAudio, RealVideo, other RealMedia MIME types or datatypes (e.g.,
.ram, .rnx, .rpm, .ra, .rm, .rp, .rt, .rf, .prx, .mpe, .rmp, .rmj, .rav,
.rjs, .rmx, .rjt, .rms), and any other Original Contributor-specific or
proprietary MIME types that Original Contributor may introduce in the
future.
29. "*Personal Use*" means use of Covered Code by an individual solely
for his or her personal, private and non-commercial purposes. An
individual's use of Covered Code in his or her capacity as an officer,
employee, member, independent contractor or agent of a corporation,
business or organization (commercial or non-commercial) does not qualify
as Personal Use.
30. "*RealMedia File Format*" means the file format designed and
developed by RealNetworks for storing multimedia data and used to store
RealAudio and RealVideo encoded streams. Valid RealMedia File Format
extensions include: .rm, .rmj, .rmc, .rmvb, .rms.
31. "*RCSL Webpage*" means the RealNetworks Community Source License
webpage located at https://www.helixcommunity.org/content/rcsl or such
other URL that Original Contributor may designate from time to time.
32. "*Reformatted Specifications*" means any revision to the
Specifications which translates or reformats the Specifications (as for
example in connection with Your documentation) but which does not alter,
subset or superset * *the functional or operational aspects of the
Specifications.
33. "*Research Use*" means use and distribution of Covered Code only for
Your Personal Use, research or development use and expressly excludes
Internal Deployment Use and Commercial Use. Research Use also includes
use of Covered Code to teach individuals how to use Covered Code.
34. "*Shared Modifications*" means Modifications that You distribute or
use for a Commercial Use, in addition to any Modifications provided by
You, at Your option, pursuant to Section 2.2, or received by You from a
Contributor pursuant to Section 2.3.
35. "*Source Code*" means the preferred form of the Covered Code for
making modifications to it, including all modules it contains, plus any
associated interface definition files, scripts used to control
compilation and installation of an Executable, or source code
differential comparisons against either the Original Code or another
well known, available Covered Code of the Contributor's choice. The
Source Code can be in a compressed or archival form, provided the
appropriate decompression or de-archiving software is widely available
for no charge.
36. "*Specifications*" means the specifications for the Technology and
other documentation, as designated on the Community Web Server, as may
be revised by Original Contributor from time to time.
37. "*Trademarks*" means Original Contributor's trademarks and logos,
including, but not limited to, RealNetworks, RealAudio, RealVideo,
RealOne, RealSystem, SureStream, Helix, Helix DNA and other trademarks
whether now used or adopted in the future.
38. "*Technology*" means the technology described in Attachment B, and
Upgrades.
39. "*Technology Compatibility Kit"* or *"TCK*" means the test programs,
procedures, acceptance criteria and/or other requirements, designated by
Original Contributor for use in verifying compliance of Covered Code
with the Specifications, in conjunction with the Original Code and
Upgraded Code. Original Contributor may, in its sole discretion and from
time to time, revise a TCK to correct errors and/or omissions and in
connection with Upgrades.
40. "*Upgrade(s)"* means new versions of Technology designated
exclusively by Original Contributor as an "Upgrade" and released by
Original Contributor from time to time under the terms of the License.
41. "*Upgraded Code*" means the Source Code and/or Executables for
Upgrades, possibly including Modifications made by Contributors.
42. *"User's Guide"* means the users guide for the TCK which Original
Contributor makes available to You to provide direction in how to run
the TCK and properly interpret the results, as may be revised by
Original Contributor from time to time.
43. "*You(r)*" means an individual, or a legal entity acting by and
through an individual or individuals, exercising rights either under
this License or under a future version of this License issued pursuant
to Section 4.1. For legal entities, "You(r)" includes any entity that by
majority voting interest controls, is controlled by, or is under common
control with You.
44. "*Your Products*" means any (i) hardware products You distribute
integrating the Covered Code; (ii) any software products You distribute
with the Covered Code that utilize the APIs of the Covered Code; or
(iii) any services You provide using the Covered Code.
ATTACHMENT A
REQUIRED NOTICES
ATTACHMENT A-1
REQUIRED IN ALL CASES
Notice to be included in header file of all Error Corrections and Shared
Modifications:
Portions Copyright 1994-2003 <20> RealNetworks, Inc. All rights reserved.
The contents of this file, and the files included with this file, are
subject to the current version of RealNetworks Community Source License
Version 1.1 (the "License"). You may not use this file except in
compliance with the License executed by both You and RealNetworks. You
may obtain a copy of the License at *
https://www.helixcommunity.org/content/rcsl.* You may also obtain a copy
of the License by contacting RealNetworks directly. Please see the
License for the rights, obligations and limitations governing use of the
contents of the file.
This file is part of the Helix DNA technology. RealNetworks, Inc., 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, are distributed 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.
Contributor(s):
_______________________________________________
Technology Compatibility Kit Test Suite(s) Location:
________________________________
ATTACHMENT A-2
SAMPLE LICENSEE CERTIFICATION
"By clicking the `Agree' button below, You certify that You are a
Licensee in good standing under the RealNetworks Community Source
License, ("License") and that Your access, use and distribution of code
and information You may obtain at this site is subject to the License.
If You are not a Licensee under the RealNetworks Community Source
License You agree not to download, copy or use the Helix DNA technology.
ATTACHMENT A-3
REQUIRED STUDENT NOTIFICATION
"This software and related documentation has been obtained by Your
educational institution subject to the RealNetworks Community Source
License. You have been provided access to the software and related
documentation for use only in connection with your course work and
research activities as a matriculated student of Your educational
institution. Any other use is expressly prohibited.
THIS SOFTWARE AND RELATED DOCUMENTATION CONTAINS PROPRIETARY MATERIAL OF
REALNETWORKS, INC, WHICH ARE PROTECTED BY VARIOUS INTELLECTUAL PROPERTY
RIGHTS.
You may not use this file except in compliance with the License. You may
obtain a copy of the License on the web at
https://www.helixcommunity.org/content/rcsl.
*
*
ATTACHMENT B
Description of Technology
Helix DNA, which consists of Helix DNA Client, Helix DNA Server and
Helix DNA Producer.
Description of "Technology"
Helix DNA Technology v1.0 as described on the Community Web Server.
ATTACHMENT C
TECHNOLOGY COMPATIBILITY KIT LICENSE
The following license is effective for the *Helix DNA* Technology
Compatibility Kit - as described on the Community Web Server. The
Technology Compatibility Kit(s) for the Technology specified in
Attachment B may be accessed at the Community Web Server.
1. TCK License.
1.1 Grants to use TCK
Subject to the terms and restrictions set forth below and the
RealNetworks Community Source License, and the Research Use license,
Original Contributor grants to You a worldwide, non-exclusive,
non-transferable license, to the extent of Original Contributor's
Intellectual Property Rights in the TCK (without the right to
sublicense), to use the TCK to develop and test Covered Code.
1.2 TCK Use Restrictions.
You are not authorized to create derivative works of the TCK or use the
TCK to test any implementation of the Specification that is not Covered
Code. You may not publish Your test results or make claims of
comparative compatibility with respect to other implementations of the
Specification. In consideration for the license grant in Section 1.1
above You agree not to develop Your own tests that are intended to
validate conformation with the Specification.
2. Test Results.
You agree to provide to Original Contributor or the third party test
facility if applicable, Your test results that demonstrate that Covered
Code is Compliant Covered Code and that Original Contributor may publish
or otherwise distribute such test results.
PLEASE READ THE TERMS OF THIS LICENSE CAREFULLY. BY CLICKING ON THE
"ACCEPT" BUTTON BELOW YOU ARE ACCEPTING AND AGREEING TO THE TERMS AND
CONDITIONS OF THIS LICENSE WITH THE ORIGINAL CONTRIBUTOR, REALNETWORKS,
INC. IF YOU ARE AGREEING TO THIS LICENSE ON BEHALF OF A COMPANY, YOU
REPRESENT THAT YOU ARE AUTHORIZED TO BIND THE COMPANY TO SUCH A LICENSE.
WHETHER YOU ARE ACTING ON YOUR OWN BEHALF, OR REPRESENTING A COMPANY,
YOU MUST BE OF MAJORITY AGE AND BE OTHERWISE COMPETENT TO ENTER INTO
CONTRACTS. IF YOU DO NOT MEET THIS CRITERIA OR YOU DO NOT AGREE TO ANY
OF THE TERMS AND CONDITIONS OF THIS LICENSE, CLICK ON THE REJECT BUTTON
TO EXIT.
*ACCEPT / REJECT
*
*
*
*To agree to the R&D/academic terms of this license, please register
<https://www.helixcommunity.org/2002/intro/why-register> on the site --
you will then be given a chance to agree to the clickwrap RCSL
<https://reguseronly.helixcommunity.org/2002/clickwrap/rcsl-clickwrap>
R&D License
<https://reguseronly.helixcommunity.org/2002/clickwrap/rcsl-clickwrap>
and gain access to the RCSL-licensed source code. To build or deploy
commercial applications based on the RCSL, you will need to agree to the
Commercial Use license attachments
<https://www.helixcommunity.org/content/rcsl-attachments>*

View File

@@ -1,518 +0,0 @@
RealNetworks Public Source License Version 1.0
(Rev. Date October 28, 2002)
1. General Definitions. This License applies to any program or other work which
RealNetworks, Inc., or any other entity that elects to use this license,
("Licensor") makes publicly available and which contains a notice placed by
Licensor identifying such program or work as "Original Code" and stating that it
is subject to the terms of this RealNetworks Public Source License version 1.0
(or subsequent version thereof) ("License"). You are not required to accept this
License. However, nothing else grants You permission to use, copy, modify or
distribute the software or its derivative works. These actions are prohibited by
law if You do not accept this License. Therefore, by modifying, copying or
distributing the software (or any work based on the software), You indicate your
acceptance of this License to do so, and all its terms and conditions. In
addition, you agree to the terms of this License by clicking the Accept button
or downloading the software. As used in this License:
1.1 "Applicable Patent Rights" mean: (a) in the case where Licensor is the
grantor of rights, claims of patents that (i) are now or hereafter acquired,
owned by or assigned to Licensor and (ii) are necessarily infringed by using or
making the Original Code alone and not in combination with other software or
hardware; and (b) in the case where You are the grantor of rights, claims of
patents that (i) are now or hereafter acquired, owned by or assigned to You and
(ii) are infringed (directly or indirectly) by using or making Your
Modifications, taken alone or in combination with Original Code.
1.2 "Compatible Source License" means any one of the licenses listed on Exhibit
B or at https://www.helixcommunity.org/content/complicense or other licenses
specifically identified by Licensor in writing. Notwithstanding any term to the
contrary in any Compatible Source License, any code covered by any Compatible
Source License that is used with Covered Code must be made readily available in
Source Code format for royalty-free use under the terms of the Compatible Source
License or this License.
1.3 "Contributor" means any person or entity that creates or contributes to the
creation of Modifications.
1.4 "Covered Code" means the Original Code, Modifications, the combination of
Original Code and any Modifications, and/or any respective portions thereof.
1.5 "Deploy" means to use, sublicense or distribute Covered Code other than for
Your internal research and development (R&D) and/or Personal Use, and includes
without limitation, any and all internal use or distribution of Covered Code
within Your business or organization except for R&D use and/or Personal Use, as
well as direct or indirect sublicensing or distribution of Covered Code by You
to any third party in any form or manner.
1.6 "Derivative Work" means either the Covered Code or any derivative work under
United States copyright law, and including any work containing or including any
portion of the Covered Code or Modifications, either verbatim or with
modifications and/or translated into another language. Derivative Work also
includes any work which combines any portion of Covered Code or Modifications
with code not otherwise governed by the terms of this License.
1.7 "Externally Deploy" means to Deploy the Covered Code in any way that may be
accessed or used by anyone other than You, used to provide any services to
anyone other than You, or used in any way to deliver any content to anyone other
than You, whether the Covered Code is distributed to those parties, made
available as an application intended for use over a computer network, or used to
provide services or otherwise deliver content to anyone other than You.
1.8. "Interface" means interfaces, functions, properties, class definitions,
APIs, header files, GUIDs, V-Tables, and/or protocols allowing one piece of
software, firmware or hardware to communicate or interoperate with another piece
of software, firmware or hardware.
1.9 "Modifications" mean any addition to, deletion from, and/or change to, the
substance and/or structure of the Original Code, any previous Modifications, the
combination of Original Code and any previous Modifications, and/or any
respective portions thereof. When code is released as a series of files, a
Modification is: (a) any addition to or deletion from the contents of a file
containing Covered Code; and/or (b) any new file or other representation of
computer program statements that contains any part of Covered Code.
1.10 "Original Code" means (a) the Source Code of a program or other work as
originally made available by Licensor under this License, including the Source
Code of any updates or upgrades to such programs or works made available by
Licensor under this License, and that has been expressly identified by Licensor
as such in the header file(s) of such work; and (b) the object code compiled
from such Source Code and originally made available by Licensor under this
License.
1.11 "Personal Use" means use of Covered Code by an individual solely for his or
her personal, private and non-commercial purposes. An individual's use of
Covered Code in his or her capacity as an officer, employee, member, independent
contractor or agent of a corporation, business or organization (commercial or
non-commercial) does not qualify as Personal Use.
1.12 "Source Code" means the human readable form of a program or other work that
is suitable for making modifications to it, including all modules it contains,
plus any associated interface definition files, scripts used to control
compilation and installation of an executable (object code).
1.13 "You" or "Your" means an individual or a legal entity exercising rights
under this License. For legal entities, "You" or "Your" includes any entity
which controls, is controlled by, or is under common control with, You, where
"control" means (a) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (b) ownership of
fifty percent (50%) or more of the outstanding shares or beneficial ownership of
such entity.
2. Permitted Uses; Conditions & Restrictions. Subject to the terms and
conditions of this License, Licensor hereby grants You, effective on the date
You accept this License (via downloading or using Covered Code or otherwise
indicating your acceptance of this License), a worldwide, royalty-free,
non-exclusive copyright license, to the extent of Licensor's copyrights cover
the Original Code, to do the following:
2.1 You may reproduce, display, perform, modify and Deploy Covered Code,
provided that in each instance:
(a) You must retain and reproduce in all copies of Original Code the copyright
and other proprietary notices and disclaimers of Licensor as they appear in the
Original Code, and keep intact all notices in the Original Code that refer to
this License;
(b) You must include a copy of this License with every copy of Source Code of
Covered Code and documentation You distribute, and You may not offer or impose
any terms on such Source Code that alter or restrict this License or the
recipients' rights hereunder, except as permitted under Section 6;
(c) You must duplicate, to the extent it does not already exist, the notice in
Exhibit A in each file of the Source Code of all Your Modifications, and cause
the modified files to carry prominent notices stating that You changed the files
and the date of any change;
(d) You must make Source Code of all Your Externally Deployed Modifications
publicly available under the terms of this License, including the license grants
set forth in Section 3 below, for as long as you Deploy the Covered Code or
twelve (12) months from the date of initial Deployment, whichever is longer. You
should preferably distribute the Source Code of Your Deployed Modifications
electronically (e.g. download from a web site); and
(e) if You Deploy Covered Code in object code, executable form only, You must
include a prominent notice, in the code itself as well as in related
documentation, stating that Source Code of the Covered Code is available under
the terms of this License with information on how and where to obtain such
Source Code. You must also include the Object Code Notice set forth in Exhibit A
in the "about" box or other appropriate place where other copyright notices are
placed, including any packaging materials.
2.2 You expressly acknowledge and agree that although Licensor and each
Contributor grants the licenses to their respective portions of the Covered Code
set forth herein, no assurances are provided by Licensor or any Contributor that
the Covered Code does not infringe the patent or other intellectual property
rights of any other entity. Licensor and each Contributor disclaim any liability
to You for claims brought by any other entity based on infringement of
intellectual property rights or otherwise. As a condition to exercising the
rights and licenses granted hereunder, You hereby assume sole responsibility to
secure any other intellectual property rights needed, if any. For example, if a
third party patent license is required to allow You to make, use, sell, import
or offer for sale the Covered Code, it is Your responsibility to acquire such
license(s).
2.3 Subject to the terms and conditions of this License, Licensor hereby grants
You, effective on the date You accept this License (via downloading or using
Covered Code or otherwise indicating your acceptance of this License), a
worldwide, royalty-free, perpetual, non-exclusive patent license under
Licensor's Applicable Patent Rights to make, use, sell, offer for sale and
import the Covered Code, provided that in each instance you comply with the
terms of this License.
3. Your Grants. In consideration of, and as a condition to, the licenses granted
to You under this License:
(a) You grant to Licensor and all third parties a non-exclusive, perpetual,
irrevocable, royalty free license under Your Applicable Patent Rights and other
intellectual property rights owned or controlled by You, to make, sell, offer
for sale, use, import, reproduce, display, perform, modify, distribute and
Deploy Your Modifications of the same scope and extent as Licensor's licenses
under Sections 2.1 and 2.2; and
(b) You grant to Licensor and its subsidiaries a non-exclusive, worldwide,
royalty-free, perpetual and irrevocable license, under Your Applicable Patent
Rights and other intellectual property rights owned or controlled by You, to
make, use, sell, offer for sale, import, reproduce, display, perform,
distribute, modify or have modified (for Licensor and/or its subsidiaries),
sublicense and distribute Your Modifications, in any form and for any purpose,
through multiple tiers of distribution.
(c) You agree not use any information derived from Your use and review of the
Covered Code, including but not limited to any algorithms or inventions that may
be contained in the Covered Code, for the purpose of asserting any of Your
patent rights, or assisting a third party to assert any of its patent rights,
against Licensor or any Contributor.
4. Derivative Works. You may create a Derivative Work by combining Covered Code
with other code not otherwise governed by the terms of this License and
distribute the Derivative Work as an integrated product. In each such instance,
You must make sure the requirements of this License are fulfilled for the
Covered Code or any portion thereof, including all Modifications.
4.1 You must cause any Derivative Work that you distribute, publish or
Externally Deploy, that in whole or in part contains or is derived from the
Covered Code or any part thereof, to be licensed as a whole at no charge to all
third parties under the terms of this License and no other license except as
provided in Section 4.2. You also must make Source Code available for the
Derivative Work under the same terms as Modifications, described in Sections 2
and 3, above.
4.2 Compatible Source Licenses. Software modules that have been independently
developed without any use of Covered Code and which contain no portion of the
Covered Code, Modifications or other Derivative Works, but are used or combined
in any way wtih the Covered Code or any Derivative Work to form a larger
Derivative Work, are exempt from the conditions described in Section 4.1 but
only to the extent that: the software module, including any software that is
linked to, integrated with, or part of the same applications as, the software
module by any method must be wholly subject to one of the Compatible Source
Licenses. Notwithstanding the foregoing, all Covered Code must be subject to the
terms of this License. Thus, the entire Derivative Work must be licensed under a
combination of the RPSL (for Covered Code) and a Compatible Source License for
any independently developed software modules within the Derivative Work. The
foregoing requirement applies even if the Compatible Source License would
ordinarily allow the software module to link with, or form larger works with,
other software that is not subject to the Compatible Source License. For
example, although the Mozilla Public License v1.1 allows Mozilla code to be
combined with proprietary software that is not subject to the MPL, if
MPL-licensed code is used with Covered Code the MPL-licensed code could not be
combined or linked with any code not governed by the MPL. The general intent of
this section 4.2 is to enable use of Covered Code with applications that are
wholly subject to an acceptable open source license. You are responsible for
determining whether your use of software with Covered Code is allowed under Your
license to such software.
4.3 Mere aggregation of another work not based on the Covered Code with the
Covered Code (or with a work based on the Covered Code) on a volume of a storage
or distribution medium does not bring the other work under the scope of this
License. If You deliver the Covered Code for combination and/or integration with
an application previously provided by You (for example, via automatic updating
technology), such combination and/or integration constitutes a Derivative Work
subject to the terms of this License.
5. Exclusions From License Grant. Nothing in this License shall be deemed to
grant any rights to trademarks, copyrights, patents, trade secrets or any other
intellectual property of Licensor or any Contributor except as expressly stated
herein. No right is granted to the trademarks of Licensor or any Contributor
even if such marks are included in the Covered Code. Nothing in this License
shall be interpreted to prohibit Licensor from licensing under different terms
from this License any code that Licensor otherwise would have a right to
license. Modifications, Derivative Works and/or any use or combination of
Covered Code with other technology provided by Licensor or third parties may
require additional patent licenses from Licensor which Licensor may grant in its
sole discretion. No patent license is granted separate from the Original Code or
combinations of the Original Code with other software or hardware.
5.1. Trademarks. This License does not grant any rights to use the trademarks or
trade names owned by Licensor ("Licensor Marks" defined in Exhibit C) or to any
trademark or trade name belonging to any Contributor. No Licensor Marks may be
used to endorse or promote products derived from the Original Code other than as
permitted by the Licensor Trademark Policy defined in Exhibit C.
6. Additional Terms. You may choose to offer, and to charge a fee for, warranty,
support, indemnity or liability obligations and/or other rights consistent with
the scope of the license granted herein ("Additional Terms") to one or more
recipients of Covered Code. However, You may do so only on Your own behalf and
as Your sole responsibility, and not on behalf of Licensor or any Contributor.
You must obtain the recipient's agreement that any such Additional Terms are
offered by You alone, and You hereby agree to indemnify, defend and hold
Licensor and every Contributor harmless for any liability incurred by or claims
asserted against Licensor or such Contributor by reason of any such Additional
Terms.
7. Versions of the License. Licensor may publish revised and/or new versions of
this License from time to time. Each version will be given a distinguishing
version number. Once Original Code has been published under a particular version
of this License, You may continue to use it under the terms of that version. You
may also choose to use such Original Code under the terms of any subsequent
version of this License published by Licensor. No one other than Licensor has
the right to modify the terms applicable to Covered Code created under this
License.
8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in part
pre-release, untested, or not fully tested works. The Covered Code may contain
errors that could cause failures or loss of data, and may be incomplete or
contain inaccuracies. You expressly acknowledge and agree that use of the
Covered Code, or any portion thereof, is at Your sole and entire risk. THE
COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF
ANY KIND AND LICENSOR AND LICENSOR'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS
"LICENSOR" FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY
DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF
SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET
ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. LICENSOR AND EACH
CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE
COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR
REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR
WRITTEN DOCUMENTATION, INFORMATION OR ADVICE GIVEN BY LICENSOR, A LICENSOR
AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You
acknowledge that the Covered Code is not intended for use in high risk
activities, including, but not limited to, the design, construction, operation
or maintenance of nuclear facilities, aircraft navigation, aircraft
communication systems, or air traffic control machines in which case the failure
of the Covered Code could lead to death, personal injury, or severe physical or
environmental damage. Licensor disclaims any express or implied warranty of
fitness for such uses.
9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT
SHALL LICENSOR OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR
YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER
UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE OR STRICT
LIABILITY), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF LICENSOR OR SUCH
CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND
NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY REMEDY. SOME
JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF INCIDENTAL OR
CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. In no event
shall Licensor's total liability to You for all damages (other than as may be
required by applicable law) under this License exceed the amount of ten dollars
($10.00).
10. Ownership. Subject to the licenses granted under this License, each
Contributor retains all rights, title and interest in and to any Modifications
made by such Contributor. Licensor retains all rights, title and interest in and
to the Original Code and any Modifications made by or on behalf of Licensor
("Licensor Modifications"), and such Licensor Modifications will not be
automatically subject to this License. Licensor may, at its sole discretion,
choose to license such Licensor Modifications under this License, or on
different terms from those contained in this License or may choose not to
license them at all.
11. Termination.
11.1 Term and Termination. The term of this License is perpetual unless
terminated as provided below. This License and the rights granted hereunder will
terminate:
(a) automatically without notice from Licensor if You fail to comply with any
term(s) of this License and fail to cure such breach within 30 days of becoming
aware of such breach;
(b) immediately in the event of the circumstances described in Section 12.5(b);
or
(c) automatically without notice from Licensor if You, at any time during the
term of this License, commence an action for patent infringement against
Licensor (including by cross-claim or counter claim in a lawsuit);
(d) upon written notice from Licensor if You, at any time during the term of
this License, commence an action for patent infringement against any third party
alleging that the Covered Code itself (excluding combinations with other
software or hardware) infringes any patent (including by cross-claim or counter
claim in a lawsuit).
11.2 Effect of Termination. Upon termination, You agree to immediately stop any
further use, reproduction, modification, sublicensing and distribution of the
Covered Code and to destroy all copies of the Covered Code that are in your
possession or control. All sublicenses to the Covered Code which have been
properly granted prior to termination shall survive any termination of this
License. Provisions which, by their nature, should remain in effect beyond the
termination of this License shall survive, including but not limited to Sections
3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other for
compensation, indemnity or damages of any sort solely as a result of terminating
this License in accordance with its terms, and termination of this License will
be without prejudice to any other right or remedy of any party.
12. Miscellaneous.
12.1 Government End Users. The Covered Code is a "commercial item" as defined in
FAR 2.101. Government software and technical data rights in the Covered Code
include only those rights customarily provided to the public as defined in this
License. This customary commercial license in technical data and software is
provided in accordance with FAR 12.211 (Technical Data) and 12.212 (Computer
Software) and, for Department of Defense purchases, DFAR 252.227-7015 (Technical
Data -- Commercial Items) and 227.7202-3 (Rights in Commercial Computer Software
or Computer Software Documentation). Accordingly, all U.S. Government End Users
acquire Covered Code with only those rights set forth herein.
12.2 Relationship of Parties. This License will not be construed as creating an
agency, partnership, joint venture or any other form of legal association
between or among You, Licensor or any Contributor, and You will not represent to
the contrary, whether expressly, by implication, appearance or otherwise.
12.3 Independent Development. Nothing in this License will impair Licensor's
right to acquire, license, develop, have others develop for it, market and/or
distribute technology or products that perform the same or similar functions as,
or otherwise compete with, Modifications, Derivative Works, technology or
products that You may develop, produce, market or distribute.
12.4 Waiver; Construction. Failure by Licensor or any Contributor to enforce any
provision of this License will not be deemed a waiver of future enforcement of
that or any other provision. Any law or regulation which provides that the
language of a contract shall be construed against the drafter will not apply to
this License.
12.5 Severability. (a) If for any reason a court of competent jurisdiction finds
any provision of this License, or portion thereof, to be unenforceable, that
provision of the License will be enforced to the maximum extent permissible so
as to effect the economic benefits and intent of the parties, and the remainder
of this License will continue in full force and effect. (b) Notwithstanding the
foregoing, if applicable law prohibits or restricts You from fully and/or
specifically complying with Sections 2 and/or 3 or prevents the enforceability
of either of those Sections, this License will immediately terminate and You
must immediately discontinue any use of the Covered Code and destroy all copies
of it that are in your possession or control.
12.6 Dispute Resolution. Any litigation or other dispute resolution between You
and Licensor relating to this License shall take place in the Seattle,
Washington, and You and Licensor hereby consent to the personal jurisdiction of,
and venue in, the state and federal courts within that District with respect to
this License. The application of the United Nations Convention on Contracts for
the International Sale of Goods is expressly excluded.
12.7 Export/Import Laws. This software is subject to all export and import laws
and restrictions and regulations of the country in which you receive the Covered
Code and You are solely responsible for ensuring that You do not export,
re-export or import the Covered Code or any direct product thereof in violation
of any such restrictions, laws or regulations, or without all necessary
authorizations.
12.8 Entire Agreement; Governing Law. This License constitutes the entire
agreement between the parties with respect to the subject matter hereof. This
License shall be governed by the laws of the United States and the State of
Washington.
Where You are located in the province of Quebec, Canada, the following clause
applies: The parties hereby confirm that they have requested that this License
and all related documents be drafted in English. Les parties ont exig&eacute;
que le pr&eacute;sent contrat et tous les documents connexes soient
r&eacute;dig&eacute;s en anglais.
EXHIBIT A.
"Copyright &copy; 1995-2002
RealNetworks, Inc. and/or its licensors. 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 Version 1.0 (the
"RPSL") available at https://www.helixcommunity.org/content/rpsl unless you have
licensed the file under the RealNetworks Community Source License Version 1.0
(the "RCSL") available at https://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.
Contributor(s): ____________________________________
Technology Compatibility Kit Test
Suite(s) Location (if licensed under the RCSL): ______________________________
Object Code Notice: Helix DNA Client technology included. Copyright (c)
RealNetworks, Inc., 1995-2002. All rights reserved.
EXHIBIT B
Compatible Source Licenses for the RealNetworks Public Source License. The
following list applies to the most recent version of the license as of October
25, 2002, unless otherwise indicated.
* Academic Free License
* Apache Software License
* Apple Public Source License
* Artistic license
* Attribution Assurance Licenses
* BSD license
* Common Public License (1)
* Eiffel Forum License
* GNU General Public License (GPL) (1)
* GNU Library or "Lesser" General Public License (LGPL) (1)
* IBM Public License
* Intel Open Source License
* Jabber Open Source License
* MIT license
* MITRE Collaborative Virtual Workspace License (CVW License)
* Motosoto License
* Mozilla Public License 1.0 (MPL)
* Mozilla Public License 1.1 (MPL)
* Nokia Open Source License
* Open Group Test Suite License
* Python Software Foundation License
* Ricoh Source Code Public License
* Sun Industry Standards Source License (SISSL)
* Sun Public License
* University of Illinois/NCSA Open Source License
* Vovida Software License v. 1.0
* W3C License
* X.Net License
* Zope Public License
* zlib/libpng license
(1) Note: because this license contains certain reciprocal licensing terms that
purport to extend to independently developed code, You may be prohibited under
the terms of this otherwise compatible license from using code licensed under
its terms with Covered Code because Covered Code may only be licensed under the
RealNetworks Public Source License. Any attempt to apply non RPSL license terms,
including without limitation the GPL, to Covered Code is expressly forbidden.
You are responsible for ensuring that Your use of Compatible Source Licensed
code does not violate either the RPSL or the Compatible Source License.
The latest version of this list can be found at:
https://www.helixcommunity.org/content/complicense
EXHIBIT C
RealNetworks' Trademark policy.
RealNetworks defines the following trademarks collectively as "Licensor
Trademarks": "RealNetworks", "RealPlayer", "RealJukebox", "RealSystem",
"RealAudio", "RealVideo", "RealOne Player", "RealMedia", "Helix" or any other
trademarks or trade names belonging to RealNetworks.
RealNetworks "Licensor Trademark Policy" forbids any use of Licensor Trademarks
except as permitted by and in strict compliance at all times with RealNetworks'
third party trademark usage guidelines which are posted at
http://www.realnetworks.com/info/helixlogo.html.

View File

@@ -1,458 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* assembly.h - assembly language functions and prototypes for supported platforms
*
* - inline rountines with access to 64-bit multiply results
* - x86 (_WIN32) and ARM (ARM_ADS, _WIN32_WCE) versions included
* - some inline functions are mix of asm and C for speed
* - some functions are in native asm files, so only the prototype is given here
*
* MULSHIFT32(x, y) signed multiply of two 32-bit integers (x and y), returns top 32 bits of 64-bit result
* FASTABS(x) branchless absolute value of signed integer x
* CLZ(x) count leading zeros in x
* MADD64(sum, x, y) (Windows only) sum [64-bit] += x [32-bit] * y [32-bit]
* SHL64(sum, x, y) (Windows only) 64-bit left shift using __int64
* SAR64(sum, x, y) (Windows only) 64-bit right shift using __int64
*/
#ifndef _ASSEMBLY_H
#define _ASSEMBLY_H
#if (defined _WIN32 && !defined _WIN32_WCE) || (defined __WINS__ && defined _SYMBIAN) || defined(_OPENWAVE_SIMULATOR) || defined(WINCE_EMULATOR) /* Symbian emulator for Ix86 */
#pragma warning( disable : 4035 ) /* complains about inline asm not returning a value */
static __inline int MULSHIFT32(int x, int y)
{
__asm {
mov eax, x
imul y
mov eax, edx
}
}
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
/* MADD64, SHL64, SAR64:
* write in assembly to avoid dependency on run-time lib for 64-bit shifts, muls
* (sometimes compiler thunks to function calls instead of code generating)
* required for Symbian emulator
*/
#ifdef __CW32__
typedef long long Word64;
#else
typedef __int64 Word64;
#endif
static __inline Word64 MADD64(Word64 sum, int x, int y)
{
unsigned int sumLo = ((unsigned int *)&sum)[0];
int sumHi = ((int *)&sum)[1];
__asm {
mov eax, x
imul y
add eax, sumLo
adc edx, sumHi
}
/* equivalent to return (sum + ((__int64)x * y)); */
}
static __inline Word64 SHL64(Word64 x, int n)
{
unsigned int xLo = ((unsigned int *)&x)[0];
int xHi = ((int *)&x)[1];
unsigned char nb = (unsigned char)n;
if (n < 32) {
__asm {
mov edx, xHi
mov eax, xLo
mov cl, nb
shld edx, eax, cl
shl eax, cl
}
} else if (n < 64) {
/* shl masks cl to 0x1f */
__asm {
mov edx, xLo
mov cl, nb
xor eax, eax
shl edx, cl
}
} else {
__asm {
xor edx, edx
xor eax, eax
}
}
}
static __inline Word64 SAR64(Word64 x, int n)
{
unsigned int xLo = ((unsigned int *)&x)[0];
int xHi = ((int *)&x)[1];
unsigned char nb = (unsigned char)n;
if (n < 32) {
__asm {
mov edx, xHi
mov eax, xLo
mov cl, nb
shrd eax, edx, cl
sar edx, cl
}
} else if (n < 64) {
/* sar masks cl to 0x1f */
__asm {
mov edx, xHi
mov eax, xHi
mov cl, nb
sar edx, 31
sar eax, cl
}
} else {
__asm {
sar xHi, 31
mov eax, xHi
mov edx, xHi
}
}
}
#elif (defined _WIN32) && (defined _WIN32_WCE)
/* use asm function for now (EVC++ 3.0 does horrible job compiling __int64 version) */
#define MULSHIFT32 xmp3_MULSHIFT32
int MULSHIFT32(int x, int y);
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
#elif defined XXXARM_ADS
static __inline int MULSHIFT32(int x, int y)
{
/* important rules for smull RdLo, RdHi, Rm, Rs:
* RdHi and Rm can't be the same register
* RdLo and Rm can't be the same register
* RdHi and RdLo can't be the same register
* Note: Rs determines early termination (leading sign bits) so if you want to specify
* which operand is Rs, put it in the SECOND argument (y)
* For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter
* which one is returned. (If this were a function call, returning y (R1) would
* require an extra "mov r0, r1")
*/
int zlow;
__asm {
smull zlow,y,x,y
}
return y;
}
static __inline int FASTABS(int x)
{
int t=0; /*Really is not necessary to initialiaze only to avoid warning*/
__asm {
eor t, x, x, asr #31
sub t, t, x, asr #31
}
return t;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
#elif defined(__GNUC__) && defined(XXXX__thumb__)
static __inline int MULSHIFT32(int x, int y)
{
// important rules for smull RdLo, RdHi, Rm, Rs:
// RdHi and Rm can't be the same register
// RdLo and Rm can't be the same register
// RdHi and RdLo can't be the same register
// Note: Rs determines early termination (leading sign bits) so if you want to specify
// which operand is Rs, put it in the SECOND argument (y)
// For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter
// which one is returned. (If this were a function call, returning y (R1) would
// require an extra "mov r0, r1")
int zlow;
__asm__ volatile ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y)) ;
return y;
}
//fb
#include <stdlib.h>
static __inline int FASTABS(int x)
{
return abs(x);
}
static __inline int CLZ(int x)
{
return __builtin_clz(x);
}
//fb
//mw
//TODO: Check Compiler output on these.. (fb)
static __inline Word64 xMADD64(Word64 sum, int x, int y)
{
return (sum + ((int64_t)x * y));
}
static __inline Word64 xHL64(Word64 x, int n)
{
return x << n;
}
static __inline Word64 xSAR64(Word64 x, int n)
{
return x >> n;
}
//mw
#elif defined(__arm__)
#if defined(ARM7DI)
typedef long long Word64;
static __inline int MULSHIFT32(int x, int y) {
return x * y;
}
#else
static __inline Word64 SAR64(Word64 x, int n) {
return x >>= n;
}
typedef union _U64 {
Word64 w64;
struct {
/* x86 = little endian */
unsigned int lo32;
signed int hi32;
} r;
} U64;
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
static __inline int MULSHIFT32(int x, int y)
{
/* important rules for smull RdLo, RdHi, Rm, Rs:
* RdHi and Rm can't be the same register
* RdLo and Rm can't be the same register
* RdHi and RdLo can't be the same register
* Note: Rs determines early termination (leading sign bits) so if you want to specify
* which operand is Rs, put it in the SECOND argument (y)
* For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter
* which one is returned. (If this were a function call, returning y (R1) would
* require an extra "mov r0, r1")
*/
int zlow;
__asm__ volatile ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y)) ;
return y;
}
#endif
static __inline int FASTABS(int x)
{
int t=0; /*Really is not necessary to initialiaze only to avoid warning*/
__asm__ volatile (
"eor %0,%2,%2, asr #31;"
"sub %0,%1,%2, asr #31;"
: "=&r" (t)
: "0" (t), "r" (x)
);
return t;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
#elif defined(__APPLE__) || defined(ESP_PLATFORM) || defined(__amd64__)
static __inline int FASTABS(int x)
{
int sign;
sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;
return x;
}
static __inline int CLZ(int x)
{
int numZeros;
if (!x)
return (sizeof(int) * 8);
numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}
return numZeros;
}
/* returns 64-bit value in [edx:eax] */
static __inline Word64 MADD64(Word64 sum64, int x, int y)
{
sum64 += (Word64)x * (Word64)y;
return sum64;
}
static __inline__ int MULSHIFT32(int x, int y)
{
int z;
z = (Word64)x * (Word64)y >> 32;
return z;
}
static __inline Word64 SAR64(Word64 x, int n)
{
return x >> n;
}
#else
#error Unsupported platform in assembly.h
#endif /* platforms */
#endif /* _ASSEMBLY_H */

View File

@@ -1,389 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* bitstream.c - bitstream unpacking, frame header parsing, side info parsing
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: SetBitstreamPointer
*
* Description: initialize bitstream reader
*
* Inputs: pointer to BitStreamInfo struct
* number of bytes in bitstream
* pointer to byte-aligned buffer of data to read from
*
* Outputs: filled bitstream info struct
*
* Return: none
**************************************************************************************/
void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf)
{
/* init bitstream */
bsi->bytePtr = buf;
bsi->iCache = 0; /* 4-byte unsigned int */
bsi->cachedBits = 0; /* i.e. zero bits in cache */
bsi->nBytes = nBytes;
}
/**************************************************************************************
* Function: RefillBitstreamCache
*
* Description: read new data from bitstream buffer into bsi cache
*
* Inputs: pointer to initialized BitStreamInfo struct
*
* Outputs: updated bitstream info struct
*
* Return: none
*
* Notes: only call when iCache is completely drained (resets bitOffset to 0)
* always loads 4 new bytes except when bsi->nBytes < 4 (end of buffer)
* stores data as big-endian in cache, regardless of machine endian-ness
*
* TODO: optimize for ARM
* possibly add little/big-endian modes for doing 32-bit loads
**************************************************************************************/
static __inline void RefillBitstreamCache(BitStreamInfo *bsi)
{
int nBytes = bsi->nBytes;
/* optimize for common case, independent of machine endian-ness */
if (nBytes >= 4) {
bsi->iCache = (*bsi->bytePtr++) << 24;
bsi->iCache |= (*bsi->bytePtr++) << 16;
bsi->iCache |= (*bsi->bytePtr++) << 8;
bsi->iCache |= (*bsi->bytePtr++);
bsi->cachedBits = 32;
bsi->nBytes -= 4;
} else {
bsi->iCache = 0;
while (nBytes--) {
bsi->iCache |= (*bsi->bytePtr++);
bsi->iCache <<= 8;
}
bsi->iCache <<= ((3 - bsi->nBytes)*8);
bsi->cachedBits = 8*bsi->nBytes;
bsi->nBytes = 0;
}
}
/**************************************************************************************
* Function: GetBits
*
* Description: get bits from bitstream, advance bitstream pointer
*
* Inputs: pointer to initialized BitStreamInfo struct
* number of bits to get from bitstream
*
* Outputs: updated bitstream info struct
*
* Return: the next nBits bits of data from bitstream buffer
*
* Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f
* for speed, does not indicate error if you overrun bit buffer
* if nBits = 0, returns 0 (useful for scalefactor unpacking)
*
* TODO: optimize for ARM
**************************************************************************************/
unsigned int GetBits(BitStreamInfo *bsi, int nBits)
{
unsigned int data, lowBits;
nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */
data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */
data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */
bsi->iCache <<= nBits; /* left-justify cache */
bsi->cachedBits -= nBits; /* how many bits have we drawn from the cache so far */
/* if we cross an int boundary, refill the cache */
if (bsi->cachedBits < 0) {
lowBits = -bsi->cachedBits;
RefillBitstreamCache(bsi);
data |= bsi->iCache >> (32 - lowBits); /* get the low-order bits */
bsi->cachedBits -= lowBits; /* how many bits have we drawn from the cache so far */
bsi->iCache <<= lowBits; /* left-justify cache */
}
return data;
}
/**************************************************************************************
* Function: CalcBitsUsed
*
* Description: calculate how many bits have been read from bitstream
*
* Inputs: pointer to initialized BitStreamInfo struct
* pointer to start of bitstream buffer
* bit offset into first byte of startBuf (0-7)
*
* Outputs: none
*
* Return: number of bits read from bitstream, as offset from startBuf:startOffset
**************************************************************************************/
int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset)
{
int bitsUsed;
bitsUsed = (bsi->bytePtr - startBuf) * 8;
bitsUsed -= bsi->cachedBits;
bitsUsed -= startOffset;
return bitsUsed;
}
/**************************************************************************************
* Function: CheckPadBit
*
* Description: check whether padding byte is present in an MP3 frame
*
* Inputs: MP3DecInfo struct with valid FrameHeader struct
* (filled by UnpackFrameHeader())
*
* Outputs: none
*
* Return: 1 if pad bit is set, 0 if not, -1 if null input pointer
**************************************************************************************/
int CheckPadBit(MP3DecInfo *mp3DecInfo)
{
FrameHeader *fh;
/* validate pointers */
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS)
return -1;
fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS));
return (fh->paddingBit ? 1 : 0);
}
/**************************************************************************************
* Function: UnpackFrameHeader
*
* Description: parse the fields of the MP3 frame header
*
* Inputs: buffer pointing to a complete MP3 frame header (4 bytes, plus 2 if CRC)
*
* Outputs: filled frame header info in the MP3DecInfo structure
* updated platform-specific FrameHeader struct
*
* Return: length (in bytes) of frame header (for caller to calculate offset to
* first byte following frame header)
* -1 if null frameHeader or invalid header
*
* TODO: check for valid modes, depending on capabilities of decoder
* test CRC on actual stream (verify no endian problems)
**************************************************************************************/
int UnpackFrameHeader(MP3DecInfo *mp3DecInfo, unsigned char *buf)
{
int verIdx;
FrameHeader *fh;
/* validate pointers and sync word */
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || (buf[0] & SYNCWORDH) != SYNCWORDH || (buf[1] & SYNCWORDL) != SYNCWORDL)
return -1;
fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS));
/* read header fields - use bitmasks instead of GetBits() for speed, since format never varies */
verIdx = (buf[1] >> 3) & 0x03;
fh->ver = (MPEGVersion)( verIdx == 0 ? MPEG25 : ((verIdx & 0x01) ? MPEG1 : MPEG2) );
fh->layer = 4 - ((buf[1] >> 1) & 0x03); /* easy mapping of index to layer number, 4 = error */
fh->crc = 1 - ((buf[1] >> 0) & 0x01);
fh->brIdx = (buf[2] >> 4) & 0x0f;
fh->srIdx = (buf[2] >> 2) & 0x03;
fh->paddingBit = (buf[2] >> 1) & 0x01;
fh->privateBit = (buf[2] >> 0) & 0x01;
fh->sMode = (StereoMode)((buf[3] >> 6) & 0x03); /* maps to correct enum (see definition) */
fh->modeExt = (buf[3] >> 4) & 0x03;
fh->copyFlag = (buf[3] >> 3) & 0x01;
fh->origFlag = (buf[3] >> 2) & 0x01;
fh->emphasis = (buf[3] >> 0) & 0x03;
/* check parameters to avoid indexing tables with bad values */
if (fh->srIdx == 3 || fh->layer == 4 || fh->brIdx == 15)
return -1;
fh->sfBand = &sfBandTable[fh->ver][fh->srIdx]; /* for readability (we reference sfBandTable many times in decoder) */
if (fh->sMode != Joint) /* just to be safe (dequant, stproc check fh->modeExt) */
fh->modeExt = 0;
/* init user-accessible data */
mp3DecInfo->nChans = (fh->sMode == Mono ? 1 : 2);
mp3DecInfo->samprate = samplerateTab[fh->ver][fh->srIdx];
mp3DecInfo->nGrans = (fh->ver == MPEG1 ? NGRANS_MPEG1 : NGRANS_MPEG2);
mp3DecInfo->nGranSamps = ((int)samplesPerFrameTab[fh->ver][fh->layer - 1]) / mp3DecInfo->nGrans;
mp3DecInfo->layer = fh->layer;
mp3DecInfo->version = fh->ver;
/* get bitrate and nSlots from table, unless brIdx == 0 (free mode) in which case caller must figure it out himself
* question - do we want to overwrite mp3DecInfo->bitrate with 0 each time if it's free mode, and
* copy the pre-calculated actual free bitrate into it in mp3dec.c (according to the spec,
* this shouldn't be necessary, since it should be either all frames free or none free)
*/
if (fh->brIdx) {
mp3DecInfo->bitrate = ((int)bitrateTab[fh->ver][fh->layer - 1][fh->brIdx]) * 1000;
/* nSlots = total frame bytes (from table) - sideInfo bytes - header - CRC (if present) + pad (if present) */
mp3DecInfo->nSlots = (int)slotTab[fh->ver][fh->srIdx][fh->brIdx] -
(int)sideBytesTab[fh->ver][(fh->sMode == Mono ? 0 : 1)] -
4 - (fh->crc ? 2 : 0) + (fh->paddingBit ? 1 : 0);
}
/* load crc word, if enabled, and return length of frame header (in bytes) */
if (fh->crc) {
fh->CRCWord = ((int)buf[4] << 8 | (int)buf[5] << 0);
return 6;
} else {
fh->CRCWord = 0;
return 4;
}
}
/**************************************************************************************
* Function: UnpackSideInfo
*
* Description: parse the fields of the MP3 side info header
*
* Inputs: MP3DecInfo structure filled by UnpackFrameHeader()
* buffer pointing to the MP3 side info data
*
* Outputs: updated mainDataBegin in MP3DecInfo struct
* updated private (platform-specific) SideInfo struct
*
* Return: length (in bytes) of side info data
* -1 if null input pointers
**************************************************************************************/
int UnpackSideInfo(MP3DecInfo *mp3DecInfo, unsigned char *buf)
{
int gr, ch, bd, nBytes;
BitStreamInfo bitStreamInfo, *bsi;
FrameHeader *fh;
SideInfo *si;
SideInfoSub *sis;
/* validate pointers and sync word */
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS)
return -1;
fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS));
si = ((SideInfo *)(mp3DecInfo->SideInfoPS));
bsi = &bitStreamInfo;
if (fh->ver == MPEG1) {
/* MPEG 1 */
nBytes = (fh->sMode == Mono ? SIBYTES_MPEG1_MONO : SIBYTES_MPEG1_STEREO);
SetBitstreamPointer(bsi, nBytes, buf);
si->mainDataBegin = GetBits(bsi, 9);
si->privateBits = GetBits(bsi, (fh->sMode == Mono ? 5 : 3));
for (ch = 0; ch < mp3DecInfo->nChans; ch++)
for (bd = 0; bd < MAX_SCFBD; bd++)
si->scfsi[ch][bd] = GetBits(bsi, 1);
} else {
/* MPEG 2, MPEG 2.5 */
nBytes = (fh->sMode == Mono ? SIBYTES_MPEG2_MONO : SIBYTES_MPEG2_STEREO);
SetBitstreamPointer(bsi, nBytes, buf);
si->mainDataBegin = GetBits(bsi, 8);
si->privateBits = GetBits(bsi, (fh->sMode == Mono ? 1 : 2));
}
for(gr =0; gr < mp3DecInfo->nGrans; gr++) {
for (ch = 0; ch < mp3DecInfo->nChans; ch++) {
sis = &si->sis[gr][ch]; /* side info subblock for this granule, channel */
sis->part23Length = GetBits(bsi, 12);
sis->nBigvals = GetBits(bsi, 9);
sis->globalGain = GetBits(bsi, 8);
sis->sfCompress = GetBits(bsi, (fh->ver == MPEG1 ? 4 : 9));
sis->winSwitchFlag = GetBits(bsi, 1);
if(sis->winSwitchFlag) {
/* this is a start, stop, short, or mixed block */
sis->blockType = GetBits(bsi, 2); /* 0 = normal, 1 = start, 2 = short, 3 = stop */
sis->mixedBlock = GetBits(bsi, 1); /* 0 = not mixed, 1 = mixed */
sis->tableSelect[0] = GetBits(bsi, 5);
sis->tableSelect[1] = GetBits(bsi, 5);
sis->tableSelect[2] = 0; /* unused */
sis->subBlockGain[0] = GetBits(bsi, 3);
sis->subBlockGain[1] = GetBits(bsi, 3);
sis->subBlockGain[2] = GetBits(bsi, 3);
/* TODO - check logic */
if (sis->blockType == 0) {
/* this should not be allowed, according to spec */
sis->nBigvals = 0;
sis->part23Length = 0;
sis->sfCompress = 0;
} else if (sis->blockType == 2 && sis->mixedBlock == 0) {
/* short block, not mixed */
sis->region0Count = 8;
} else {
/* start, stop, or short-mixed */
sis->region0Count = 7;
}
sis->region1Count = 20 - sis->region0Count;
} else {
/* this is a normal block */
sis->blockType = 0;
sis->mixedBlock = 0;
sis->tableSelect[0] = GetBits(bsi, 5);
sis->tableSelect[1] = GetBits(bsi, 5);
sis->tableSelect[2] = GetBits(bsi, 5);
sis->region0Count = GetBits(bsi, 4);
sis->region1Count = GetBits(bsi, 3);
}
sis->preFlag = (fh->ver == MPEG1 ? GetBits(bsi, 1) : 0);
sis->sfactScale = GetBits(bsi, 1);
sis->count1TableSelect = GetBits(bsi, 1);
}
}
mp3DecInfo->mainDataBegin = si->mainDataBegin; /* needed by main decode loop */
ASSERT(nBytes == CalcBitsUsed(bsi, buf, 0) >> 3);
return nBytes;
}

View File

@@ -1,177 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* buffers.c - allocation and freeing of internal MP3 decoder buffers
*
* All memory allocation for the codec is done in this file, so if you don't want
* to use other the default system malloc() and free() for heap management this is
* the only file you'll need to change.
**************************************************************************************/
//#include "hlxclib/stdlib.h" /* for malloc, free */
#include <stdlib.h>
#include <string.h>
#include "coder.h"
/**************************************************************************************
* Function: ClearBuffer
*
* Description: fill buffer with 0's
*
* Inputs: pointer to buffer
* number of bytes to fill with 0
*
* Outputs: cleared buffer
*
* Return: none
*
* Notes: slow, platform-independent equivalent to memset(buf, 0, nBytes)
**************************************************************************************/
#define ClearBuffer(buf, nBytes) memset(buf, 0, nBytes) //fb
/*
static void ClearBuffer(void *buf, int nBytes)
{
int i;
unsigned char *cbuf = (unsigned char *)buf;
for (i = 0; i < nBytes; i++)
cbuf[i] = 0;
//fb
memset(buf, 0, nBytes)
return;
}
*/
/**************************************************************************************
* Function: AllocateBuffers
*
* Description: allocate all the memory needed for the MP3 decoder
*
* Inputs: none
*
* Outputs: none
*
* Return: pointer to MP3DecInfo structure (initialized with pointers to all
* the internal buffers needed for decoding, all other members of
* MP3DecInfo structure set to 0)
*
* Notes: if one or more mallocs fail, function frees any buffers already
* allocated before returning
**************************************************************************************/
MP3DecInfo *AllocateBuffers(void)
{
MP3DecInfo *mp3DecInfo;
FrameHeader *fh;
SideInfo *si;
ScaleFactorInfo *sfi;
HuffmanInfo *hi;
DequantInfo *di;
IMDCTInfo *mi;
SubbandInfo *sbi;
mp3DecInfo = (MP3DecInfo *)malloc(sizeof(MP3DecInfo));
if (!mp3DecInfo)
return 0;
ClearBuffer(mp3DecInfo, sizeof(MP3DecInfo));
fh = (FrameHeader *) malloc(sizeof(FrameHeader));
si = (SideInfo *) malloc(sizeof(SideInfo));
sfi = (ScaleFactorInfo *) malloc(sizeof(ScaleFactorInfo));
hi = (HuffmanInfo *) malloc(sizeof(HuffmanInfo));
di = (DequantInfo *) malloc(sizeof(DequantInfo));
mi = (IMDCTInfo *) malloc(sizeof(IMDCTInfo));
sbi = (SubbandInfo *) malloc(sizeof(SubbandInfo));
mp3DecInfo->FrameHeaderPS = (void *)fh;
mp3DecInfo->SideInfoPS = (void *)si;
mp3DecInfo->ScaleFactorInfoPS = (void *)sfi;
mp3DecInfo->HuffmanInfoPS = (void *)hi;
mp3DecInfo->DequantInfoPS = (void *)di;
mp3DecInfo->IMDCTInfoPS = (void *)mi;
mp3DecInfo->SubbandInfoPS = (void *)sbi;
if (!fh || !si || !sfi || !hi || !di || !mi || !sbi) {
FreeBuffers(mp3DecInfo); /* safe to call - only frees memory that was successfully allocated */
return 0;
}
/* important to do this - DSP primitives assume a bunch of state variables are 0 on first use */
ClearBuffer(fh, sizeof(FrameHeader));
ClearBuffer(si, sizeof(SideInfo));
ClearBuffer(sfi, sizeof(ScaleFactorInfo));
ClearBuffer(hi, sizeof(HuffmanInfo));
ClearBuffer(di, sizeof(DequantInfo));
ClearBuffer(mi, sizeof(IMDCTInfo));
ClearBuffer(sbi, sizeof(SubbandInfo));
return mp3DecInfo;
}
#define SAFE_FREE(x) {if (x) free(x); (x) = 0;} /* helper macro */
/**************************************************************************************
* Function: FreeBuffers
*
* Description: frees all the memory used by the MP3 decoder
*
* Inputs: pointer to initialized MP3DecInfo structure
*
* Outputs: none
*
* Return: none
*
* Notes: safe to call even if some buffers were not allocated (uses SAFE_FREE)
**************************************************************************************/
void FreeBuffers(MP3DecInfo *mp3DecInfo)
{
if (!mp3DecInfo)
return;
SAFE_FREE(mp3DecInfo->FrameHeaderPS);
SAFE_FREE(mp3DecInfo->SideInfoPS);
SAFE_FREE(mp3DecInfo->ScaleFactorInfoPS);
SAFE_FREE(mp3DecInfo->HuffmanInfoPS);
SAFE_FREE(mp3DecInfo->DequantInfoPS);
SAFE_FREE(mp3DecInfo->IMDCTInfoPS);
SAFE_FREE(mp3DecInfo->SubbandInfoPS);
SAFE_FREE(mp3DecInfo);
}

View File

@@ -1,309 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* coder.h - private, implementation-specific header file
**************************************************************************************/
#ifndef _CODER_H
#define _CODER_H
#pragma GCC optimize ("O3")
#include "mp3common.h"
#if defined(ASSERT)
#undef ASSERT
#endif
#if defined(_WIN32) && defined(_M_IX86) && (defined (_DEBUG) || defined (REL_ENABLE_ASSERTS))
#define ASSERT(x) if (!(x)) __asm int 3;
#else
#define ASSERT(x) /* do nothing */
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/* clip to range [-2^n, 2^n - 1] */
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (n)) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
#define SIBYTES_MPEG1_MONO 17
#define SIBYTES_MPEG1_STEREO 32
#define SIBYTES_MPEG2_MONO 9
#define SIBYTES_MPEG2_STEREO 17
/* number of fraction bits for pow43Tab (see comments there) */
#define POW43_FRACBITS_LOW 22
#define POW43_FRACBITS_HIGH 12
#define DQ_FRACBITS_OUT 25 /* number of fraction bits in output of dequant */
#define IMDCT_SCALE 2 /* additional scaling (by sqrt(2)) for fast IMDCT36 */
#define HUFF_PAIRTABS 32
#define BLOCK_SIZE 18
#define NBANDS 32
#define MAX_REORDER_SAMPS ((192-126)*3) /* largest critical band for short blocks (see sfBandTable) */
#define VBUF_LENGTH (17 * 2 * NBANDS) /* for double-sized vbuf FIFO */
/* additional external symbols to name-mangle for static linking */
#define SetBitstreamPointer STATNAME(SetBitstreamPointer)
#define GetBits STATNAME(GetBits)
#define CalcBitsUsed STATNAME(CalcBitsUsed)
#define DequantChannel STATNAME(DequantChannel)
#define MidSideProc STATNAME(MidSideProc)
#define IntensityProcMPEG1 STATNAME(IntensityProcMPEG1)
#define IntensityProcMPEG2 STATNAME(IntensityProcMPEG2)
#define PolyphaseMono STATNAME(PolyphaseMono)
#define PolyphaseStereo STATNAME(PolyphaseStereo)
#define FDCT32 STATNAME(FDCT32)
#define ISFMpeg1 STATNAME(ISFMpeg1)
#define ISFMpeg2 STATNAME(ISFMpeg2)
#define ISFIIP STATNAME(ISFIIP)
#define uniqueIDTab STATNAME(uniqueIDTab)
#define coef32 STATNAME(coef32)
#define polyCoef STATNAME(polyCoef)
#define csa STATNAME(csa)
#define imdctWin STATNAME(imdctWin)
#define huffTable STATNAME(huffTable)
#define huffTabOffset STATNAME(huffTabOffset)
#define huffTabLookup STATNAME(huffTabLookup)
#define quadTable STATNAME(quadTable)
#define quadTabOffset STATNAME(quadTabOffset)
#define quadTabMaxBits STATNAME(quadTabMaxBits)
/* map these to the corresponding 2-bit values in the frame header */
typedef enum {
Stereo = 0x00, /* two independent channels, but L and R frames might have different # of bits */
Joint = 0x01, /* coupled channels - layer III: mix of M-S and intensity, Layers I/II: intensity and direct coding only */
Dual = 0x02, /* two independent channels, L and R always have exactly 1/2 the total bitrate */
Mono = 0x03 /* one channel */
} StereoMode;
typedef struct _BitStreamInfo {
unsigned char *bytePtr;
unsigned int iCache;
int cachedBits;
int nBytes;
} BitStreamInfo;
typedef struct _FrameHeader {
MPEGVersion ver; /* version ID */
int layer; /* layer index (1, 2, or 3) */
int crc; /* CRC flag: 0 = disabled, 1 = enabled */
int brIdx; /* bitrate index (0 - 15) */
int srIdx; /* sample rate index (0 - 2) */
int paddingBit; /* padding flag: 0 = no padding, 1 = single pad byte */
int privateBit; /* unused */
StereoMode sMode; /* mono/stereo mode */
int modeExt; /* used to decipher joint stereo mode */
int copyFlag; /* copyright flag: 0 = no, 1 = yes */
int origFlag; /* original flag: 0 = copy, 1 = original */
int emphasis; /* deemphasis mode */
int CRCWord; /* CRC word (16 bits, 0 if crc not enabled) */
const SFBandTable *sfBand;
} FrameHeader;
typedef struct _SideInfoSub {
int part23Length; /* number of bits in main data */
int nBigvals; /* 2x this = first set of Huffman cw's (maximum amplitude can be > 1) */
int globalGain; /* overall gain for dequantizer */
int sfCompress; /* unpacked to figure out number of bits in scale factors */
int winSwitchFlag; /* window switching flag */
int blockType; /* block type */
int mixedBlock; /* 0 = regular block (all short or long), 1 = mixed block */
int tableSelect[3]; /* index of Huffman tables for the big values regions */
int subBlockGain[3]; /* subblock gain offset, relative to global gain */
int region0Count; /* 1+region0Count = num scale factor bands in first region of bigvals */
int region1Count; /* 1+region1Count = num scale factor bands in second region of bigvals */
int preFlag; /* for optional high frequency boost */
int sfactScale; /* scaling of the scalefactors */
int count1TableSelect; /* index of Huffman table for quad codewords */
} SideInfoSub;
typedef struct _SideInfo {
int mainDataBegin;
int privateBits;
int scfsi[MAX_NCHAN][MAX_SCFBD]; /* 4 scalefactor bands per channel */
SideInfoSub sis[MAX_NGRAN][MAX_NCHAN];
} SideInfo;
typedef struct {
int cbType; /* pure long = 0, pure short = 1, mixed = 2 */
int cbEndS[3]; /* number nonzero short cb's, per subbblock */
int cbEndSMax; /* max of cbEndS[] */
int cbEndL; /* number nonzero long cb's */
} CriticalBandInfo;
typedef struct _DequantInfo {
int workBuf[MAX_REORDER_SAMPS]; /* workbuf for reordering short blocks */
CriticalBandInfo cbi[MAX_NCHAN]; /* filled in dequantizer, used in joint stereo reconstruction */
} DequantInfo;
typedef struct _HuffmanInfo {
int huffDecBuf[MAX_NCHAN][MAX_NSAMP]; /* used both for decoded Huffman values and dequantized coefficients */
int nonZeroBound[MAX_NCHAN]; /* number of coeffs in huffDecBuf[ch] which can be > 0 */
int gb[MAX_NCHAN]; /* minimum number of guard bits in huffDecBuf[ch] */
} HuffmanInfo;
typedef enum _HuffTabType {
noBits,
oneShot,
loopNoLinbits,
loopLinbits,
quadA,
quadB,
invalidTab
} HuffTabType;
typedef struct _HuffTabLookup {
int linBits;
int /*HuffTabType*/ tabType;
} HuffTabLookup;
typedef struct _IMDCTInfo {
int outBuf[MAX_NCHAN][BLOCK_SIZE][NBANDS]; /* output of IMDCT */
int overBuf[MAX_NCHAN][MAX_NSAMP / 2]; /* overlap-add buffer (by symmetry, only need 1/2 size) */
int numPrevIMDCT[MAX_NCHAN]; /* how many IMDCT's calculated in this channel on prev. granule */
int prevType[MAX_NCHAN];
int prevWinSwitch[MAX_NCHAN];
int gb[MAX_NCHAN];
} IMDCTInfo;
typedef struct _BlockCount {
int nBlocksLong;
int nBlocksTotal;
int nBlocksPrev;
int prevType;
int prevWinSwitch;
int currWinSwitch;
int gbIn;
int gbOut;
} BlockCount;
/* max bits in scalefactors = 5, so use char's to save space */
typedef struct _ScaleFactorInfoSub {
char l[23]; /* [band] */
char s[13][3]; /* [band][window] */
} ScaleFactorInfoSub;
/* used in MPEG 2, 2.5 intensity (joint) stereo only */
typedef struct _ScaleFactorJS {
int intensityScale;
int slen[4];
int nr[4];
} ScaleFactorJS;
typedef struct _ScaleFactorInfo {
ScaleFactorInfoSub sfis[MAX_NGRAN][MAX_NCHAN];
ScaleFactorJS sfjs;
} ScaleFactorInfo;
/* NOTE - could get by with smaller vbuf if memory is more important than speed
* (in Subband, instead of replicating each block in FDCT32 you would do a memmove on the
* last 15 blocks to shift them down one, a hardware style FIFO)
*/
typedef struct _SubbandInfo {
int vbuf[MAX_NCHAN * VBUF_LENGTH]; /* vbuf for fast DCT-based synthesis PQMF - double size for speed (no modulo indexing) */
int vindex; /* internal index for tracking position in vbuf */
} SubbandInfo;
/* bitstream.c */
void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf);
unsigned int GetBits(BitStreamInfo *bsi, int nBits);
int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset);
/* dequant.c, dqchan.c, stproc.c */
int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, FrameHeader *fh, SideInfoSub *sis,
ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi);
void MidSideProc(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, int mOut[2]);
void IntensityProcMPEG1(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis,
CriticalBandInfo *cbi, int midSideFlag, int mixFlag, int mOut[2]);
void IntensityProcMPEG2(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis,
CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int midSideFlag, int mixFlag, int mOut[2]);
/* dct32.c */
// about 1 ms faster in RAM, but very large
void FDCT32(int *x, int *d, int offset, int oddBlock, int gb);// __attribute__ ((section (".data")));
/* hufftabs.c */
extern const HuffTabLookup huffTabLookup[HUFF_PAIRTABS];
extern const int huffTabOffset[HUFF_PAIRTABS];
extern const unsigned short huffTable[];
extern const unsigned char quadTable[64+16];
extern const int quadTabOffset[2];
extern const int quadTabMaxBits[2];
/* polyphase.c (or asmpoly.s)
* some platforms require a C++ compile of all source files,
* so if we're compiling C as C++ and using native assembly
* for these functions we need to prevent C++ name mangling.
*/
#ifdef __cplusplus
extern "C" {
#endif
void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase);
void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase);
#ifdef __cplusplus
}
#endif
/* trigtabs.c */
extern const int imdctWin[4][36];
extern const int ISFMpeg1[2][7];
extern const int ISFMpeg2[2][2][16];
extern const int ISFIIP[2][2];
extern const int csa[8][2];
extern const int coef32[31];
extern const int polyCoef[264];
#endif /* _CODER_H */

View File

@@ -1,280 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* dct32.c - optimized implementations of 32-point DCT for matrixing stage of
* polyphase filter
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define COS0_0 0x4013c251 /* Q31 */
#define COS0_1 0x40b345bd /* Q31 */
#define COS0_2 0x41fa2d6d /* Q31 */
#define COS0_3 0x43f93421 /* Q31 */
#define COS0_4 0x46cc1bc4 /* Q31 */
#define COS0_5 0x4a9d9cf0 /* Q31 */
#define COS0_6 0x4fae3711 /* Q31 */
#define COS0_7 0x56601ea7 /* Q31 */
#define COS0_8 0x5f4cf6eb /* Q31 */
#define COS0_9 0x6b6fcf26 /* Q31 */
#define COS0_10 0x7c7d1db3 /* Q31 */
#define COS0_11 0x4ad81a97 /* Q30 */
#define COS0_12 0x5efc8d96 /* Q30 */
#define COS0_13 0x41d95790 /* Q29 */
#define COS0_14 0x6d0b20cf /* Q29 */
#define COS0_15 0x518522fb /* Q27 */
#define COS1_0 0x404f4672 /* Q31 */
#define COS1_1 0x42e13c10 /* Q31 */
#define COS1_2 0x48919f44 /* Q31 */
#define COS1_3 0x52cb0e63 /* Q31 */
#define COS1_4 0x64e2402e /* Q31 */
#define COS1_5 0x43e224a9 /* Q30 */
#define COS1_6 0x6e3c92c1 /* Q30 */
#define COS1_7 0x519e4e04 /* Q28 */
#define COS2_0 0x4140fb46 /* Q31 */
#define COS2_1 0x4cf8de88 /* Q31 */
#define COS2_2 0x73326bbf /* Q31 */
#define COS2_3 0x52036742 /* Q29 */
#define COS3_0 0x4545e9ef /* Q31 */
#define COS3_1 0x539eba45 /* Q30 */
#define COS4_0 0x5a82799a /* Q31 */
// faster in ROM
static const int dcttab[48] PROGMEM = {
/* first pass */
COS0_0, COS0_15, COS1_0, /* 31, 27, 31 */
COS0_1, COS0_14, COS1_1, /* 31, 29, 31 */
COS0_2, COS0_13, COS1_2, /* 31, 29, 31 */
COS0_3, COS0_12, COS1_3, /* 31, 30, 31 */
COS0_4, COS0_11, COS1_4, /* 31, 30, 31 */
COS0_5, COS0_10, COS1_5, /* 31, 31, 30 */
COS0_6, COS0_9, COS1_6, /* 31, 31, 30 */
COS0_7, COS0_8, COS1_7, /* 31, 31, 28 */
/* second pass */
COS2_0, COS2_3, COS3_0, /* 31, 29, 31 */
COS2_1, COS2_2, COS3_1, /* 31, 31, 30 */
-COS2_0, -COS2_3, COS3_0, /* 31, 29, 31 */
-COS2_1, -COS2_2, COS3_1, /* 31, 31, 30 */
COS2_0, COS2_3, COS3_0, /* 31, 29, 31 */
COS2_1, COS2_2, COS3_1, /* 31, 31, 30 */
-COS2_0, -COS2_3, COS3_0, /* 31, 29, 31 */
-COS2_1, -COS2_2, COS3_1, /* 31, 31, 30 */
};
#define D32FP(i, s0, s1, s2) { \
a0 = buf[i]; a3 = buf[31-i]; \
a1 = buf[15-i]; a2 = buf[16+i]; \
b0 = a0 + a3; b3 = MULSHIFT32(*cptr++, a0 - a3) << (s0); \
b1 = a1 + a2; b2 = MULSHIFT32(*cptr++, a1 - a2) << (s1); \
buf[i] = b0 + b1; buf[15-i] = MULSHIFT32(*cptr, b0 - b1) << (s2); \
buf[16+i] = b2 + b3; buf[31-i] = MULSHIFT32(*cptr++, b3 - b2) << (s2); \
}
/**************************************************************************************
* Function: FDCT32
*
* Description: Ken's highly-optimized 32-point DCT (radix-4 + radix-8)
*
* Inputs: input buffer, length = 32 samples
* require at least 6 guard bits in input vector x to avoid possibility
* of overflow in internal calculations (see bbtest_imdct test app)
* buffer offset and oddblock flag for polyphase filter input buffer
* number of guard bits in input
*
* Outputs: output buffer, data copied and interleaved for polyphase filter
* no guarantees about number of guard bits in output
*
* Return: none
*
* Notes: number of muls = 4*8 + 12*4 = 80
* final stage of DCT is hardcoded to shuffle data into the proper order
* for the polyphase filterbank
* fully unrolled stage 1, for max precision (scale the 1/cos() factors
* differently, depending on magnitude)
* guard bit analysis verified by exhaustive testing of all 2^32
* combinations of max pos/max neg values in x[]
*
* TODO: code organization and optimization for ARM
* possibly interleave stereo (cut # of coef loads in half - may not have
* enough registers)
**************************************************************************************/
// about 1ms faster in RAM
/* attribute__ ((section (".data"))) */ void FDCT32(int *buf, int *dest, int offset, int oddBlock, int gb)
{
int i, s, tmp, es;
const int *cptr = dcttab;
int a0, a1, a2, a3, a4, a5, a6, a7;
int b0, b1, b2, b3, b4, b5, b6, b7;
int *d;
/* scaling - ensure at least 6 guard bits for DCT
* (in practice this is already true 99% of time, so this code is
* almost never triggered)
*/
es = 0;
if (gb < 6) {
es = 6 - gb;
for (i = 0; i < 32; i++)
buf[i] >>= es;
}
/* first pass */
D32FP(0, 1, 5, 1);
D32FP(1, 1, 3, 1);
D32FP(2, 1, 3, 1);
D32FP(3, 1, 2, 1);
D32FP(4, 1, 2, 1);
D32FP(5, 1, 1, 2);
D32FP(6, 1, 1, 2);
D32FP(7, 1, 1, 4);
/* second pass */
for (i = 4; i > 0; i--) {
a0 = buf[0]; a7 = buf[7]; a3 = buf[3]; a4 = buf[4];
b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1;
b3 = a3 + a4; b4 = MULSHIFT32(*cptr++, a3 - a4) << 3;
a0 = b0 + b3; a3 = MULSHIFT32(*cptr, b0 - b3) << 1;
a4 = b4 + b7; a7 = MULSHIFT32(*cptr++, b7 - b4) << 1;
a1 = buf[1]; a6 = buf[6]; a2 = buf[2]; a5 = buf[5];
b1 = a1 + a6; b6 = MULSHIFT32(*cptr++, a1 - a6) << 1;
b2 = a2 + a5; b5 = MULSHIFT32(*cptr++, a2 - a5) << 1;
a1 = b1 + b2; a2 = MULSHIFT32(*cptr, b1 - b2) << 2;
a5 = b5 + b6; a6 = MULSHIFT32(*cptr++, b6 - b5) << 2;
b0 = a0 + a1; b1 = MULSHIFT32(COS4_0, a0 - a1) << 1;
b2 = a2 + a3; b3 = MULSHIFT32(COS4_0, a3 - a2) << 1;
buf[0] = b0; buf[1] = b1;
buf[2] = b2 + b3; buf[3] = b3;
b4 = a4 + a5; b5 = MULSHIFT32(COS4_0, a4 - a5) << 1;
b6 = a6 + a7; b7 = MULSHIFT32(COS4_0, a7 - a6) << 1;
b6 += b7;
buf[4] = b4 + b6; buf[5] = b5 + b7;
buf[6] = b5 + b6; buf[7] = b7;
buf += 8;
}
buf -= 32; /* reset */
/* sample 0 - always delayed one block */
d = dest + 64*16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH);
s = buf[ 0]; d[0] = d[8] = s;
/* samples 16 to 31 */
d = dest + offset + (oddBlock ? VBUF_LENGTH : 0);
s = buf[ 1]; d[0] = d[8] = s; d += 64;
tmp = buf[25] + buf[29];
s = buf[17] + tmp; d[0] = d[8] = s; d += 64;
s = buf[ 9] + buf[13]; d[0] = d[8] = s; d += 64;
s = buf[21] + tmp; d[0] = d[8] = s; d += 64;
tmp = buf[29] + buf[27];
s = buf[ 5]; d[0] = d[8] = s; d += 64;
s = buf[21] + tmp; d[0] = d[8] = s; d += 64;
s = buf[13] + buf[11]; d[0] = d[8] = s; d += 64;
s = buf[19] + tmp; d[0] = d[8] = s; d += 64;
tmp = buf[27] + buf[31];
s = buf[ 3]; d[0] = d[8] = s; d += 64;
s = buf[19] + tmp; d[0] = d[8] = s; d += 64;
s = buf[11] + buf[15]; d[0] = d[8] = s; d += 64;
s = buf[23] + tmp; d[0] = d[8] = s; d += 64;
tmp = buf[31];
s = buf[ 7]; d[0] = d[8] = s; d += 64;
s = buf[23] + tmp; d[0] = d[8] = s; d += 64;
s = buf[15]; d[0] = d[8] = s; d += 64;
s = tmp; d[0] = d[8] = s;
/* samples 16 to 1 (sample 16 used again) */
d = dest + 16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH);
s = buf[ 1]; d[0] = d[8] = s; d += 64;
tmp = buf[30] + buf[25];
s = buf[17] + tmp; d[0] = d[8] = s; d += 64;
s = buf[14] + buf[ 9]; d[0] = d[8] = s; d += 64;
s = buf[22] + tmp; d[0] = d[8] = s; d += 64;
s = buf[ 6]; d[0] = d[8] = s; d += 64;
tmp = buf[26] + buf[30];
s = buf[22] + tmp; d[0] = d[8] = s; d += 64;
s = buf[10] + buf[14]; d[0] = d[8] = s; d += 64;
s = buf[18] + tmp; d[0] = d[8] = s; d += 64;
s = buf[ 2]; d[0] = d[8] = s; d += 64;
tmp = buf[28] + buf[26];
s = buf[18] + tmp; d[0] = d[8] = s; d += 64;
s = buf[12] + buf[10]; d[0] = d[8] = s; d += 64;
s = buf[20] + tmp; d[0] = d[8] = s; d += 64;
s = buf[ 4]; d[0] = d[8] = s; d += 64;
tmp = buf[24] + buf[28];
s = buf[20] + tmp; d[0] = d[8] = s; d += 64;
s = buf[ 8] + buf[12]; d[0] = d[8] = s; d += 64;
s = buf[16] + tmp; d[0] = d[8] = s;
/* this is so rarely invoked that it's not worth making two versions of the output
* shuffle code (one for no shift, one for clip + variable shift) like in IMDCT
* here we just load, clip, shift, and store on the rare instances that es != 0
*/
if (es) {
d = dest + 64*16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH);
s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es);
d = dest + offset + (oddBlock ? VBUF_LENGTH : 0);
for (i = 16; i <= 31; i++) {
s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); d += 64;
}
d = dest + 16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH);
for (i = 15; i >= 0; i--) {
s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); d += 64;
}
}
}

View File

@@ -1,158 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* dequant.c - dequantization, stereo processing (intensity, mid-side), short-block
* coefficient reordering
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: Dequantize
*
* Description: dequantize coefficients, decode stereo, reorder short blocks
* (one granule-worth)
*
* Inputs: MP3DecInfo structure filled by UnpackFrameHeader(), UnpackSideInfo(),
* UnpackScaleFactors(), and DecodeHuffman() (for this granule)
* index of current granule
*
* Outputs: dequantized and reordered coefficients in hi->huffDecBuf
* (one granule-worth, all channels), format = Q26
* operates in-place on huffDecBuf but also needs di->workBuf
* updated hi->nonZeroBound index for both channels
*
* Return: 0 on success, -1 if null input pointers
*
* Notes: In calling output Q(DQ_FRACBITS_OUT), we assume an implicit bias
* of 2^15. Some (floating-point) reference implementations factor this
* into the 2^(0.25 * gain) scaling explicitly. But to avoid precision
* loss, we don't do that. Instead take it into account in the final
* round to PCM (>> by 15 less than we otherwise would have).
* Equivalently, we can think of the dequantized coefficients as
* Q(DQ_FRACBITS_OUT - 15) with no implicit bias.
**************************************************************************************/
int Dequantize(MP3DecInfo *mp3DecInfo, int gr)
{
int i, ch, nSamps, mOut[2];
FrameHeader *fh;
SideInfo *si;
ScaleFactorInfo *sfi;
HuffmanInfo *hi;
DequantInfo *di;
CriticalBandInfo *cbi;
/* validate pointers */
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS ||
!mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->DequantInfoPS)
return -1;
fh = (FrameHeader *)(mp3DecInfo->FrameHeaderPS);
/* si is an array of up to 4 structs, stored as gr0ch0, gr0ch1, gr1ch0, gr1ch1 */
si = (SideInfo *)(mp3DecInfo->SideInfoPS);
sfi = (ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS);
hi = (HuffmanInfo *)mp3DecInfo->HuffmanInfoPS;
di = (DequantInfo *)mp3DecInfo->DequantInfoPS;
cbi = di->cbi;
mOut[0] = mOut[1] = 0;
/* dequantize all the samples in each channel */
for (ch = 0; ch < mp3DecInfo->nChans; ch++) {
hi->gb[ch] = DequantChannel(hi->huffDecBuf[ch], di->workBuf, &hi->nonZeroBound[ch], fh,
&si->sis[gr][ch], &sfi->sfis[gr][ch], &cbi[ch]);
}
/* joint stereo processing assumes one guard bit in input samples
* it's extremely rare not to have at least one gb, so if this is the case
* just make a pass over the data and clip to [-2^30+1, 2^30-1]
* in practice this may never happen
*/
if (fh->modeExt && (hi->gb[0] < 1 || hi->gb[1] < 1)) {
for (i = 0; i < hi->nonZeroBound[0]; i++) {
if (hi->huffDecBuf[0][i] < -0x3fffffff) hi->huffDecBuf[0][i] = -0x3fffffff;
if (hi->huffDecBuf[0][i] > 0x3fffffff) hi->huffDecBuf[0][i] = 0x3fffffff;
}
for (i = 0; i < hi->nonZeroBound[1]; i++) {
if (hi->huffDecBuf[1][i] < -0x3fffffff) hi->huffDecBuf[1][i] = -0x3fffffff;
if (hi->huffDecBuf[1][i] > 0x3fffffff) hi->huffDecBuf[1][i] = 0x3fffffff;
}
}
/* do mid-side stereo processing, if enabled */
if (fh->modeExt >> 1) {
if (fh->modeExt & 0x01) {
/* intensity stereo enabled - run mid-side up to start of right zero region */
if (cbi[1].cbType == 0)
nSamps = fh->sfBand->l[cbi[1].cbEndL + 1];
else
nSamps = 3 * fh->sfBand->s[cbi[1].cbEndSMax + 1];
} else {
/* intensity stereo disabled - run mid-side on whole spectrum */
nSamps = MAX(hi->nonZeroBound[0], hi->nonZeroBound[1]);
}
MidSideProc(hi->huffDecBuf, nSamps, mOut);
}
/* do intensity stereo processing, if enabled */
if (fh->modeExt & 0x01) {
nSamps = hi->nonZeroBound[0];
if (fh->ver == MPEG1) {
IntensityProcMPEG1(hi->huffDecBuf, nSamps, fh, &sfi->sfis[gr][1], di->cbi,
fh->modeExt >> 1, si->sis[gr][1].mixedBlock, mOut);
} else {
IntensityProcMPEG2(hi->huffDecBuf, nSamps, fh, &sfi->sfis[gr][1], di->cbi, &sfi->sfjs,
fh->modeExt >> 1, si->sis[gr][1].mixedBlock, mOut);
}
}
/* adjust guard bit count and nonZeroBound if we did any stereo processing */
if (fh->modeExt) {
hi->gb[0] = CLZ(mOut[0]) - 1;
hi->gb[1] = CLZ(mOut[1]) - 1;
nSamps = MAX(hi->nonZeroBound[0], hi->nonZeroBound[1]);
hi->nonZeroBound[0] = nSamps;
hi->nonZeroBound[1] = nSamps;
}
/* output format Q(DQ_FRACBITS_OUT) */
return 0;
}

View File

@@ -1,376 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* August 2003
*
* dqchan.c - dequantization of transform coefficients
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
typedef int ARRAY3[3]; /* for short-block reordering */
/* optional pre-emphasis for high-frequency scale factor bands */
static const char preTab[22] = { 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0 };
/* pow(2,-i/4) for i=0..3, Q31 format */
const int pow14[4] PROGMEM = {
0x7fffffff, 0x6ba27e65, 0x5a82799a, 0x4c1bf829
};
/* pow(2,-i/4) * pow(j,4/3) for i=0..3 j=0..15, Q25 format */
const int pow43_14[4][16] PROGMEM = {
{ 0x00000000, 0x10000000, 0x285145f3, 0x453a5cdb, /* Q28 */
0x0cb2ff53, 0x111989d6, 0x15ce31c8, 0x1ac7f203,
0x20000000, 0x257106b9, 0x2b16b4a3, 0x30ed74b4,
0x36f23fa5, 0x3d227bd3, 0x437be656, 0x49fc823c, },
{ 0x00000000, 0x0d744fcd, 0x21e71f26, 0x3a36abd9,
0x0aadc084, 0x0e610e6e, 0x12560c1d, 0x168523cf,
0x1ae89f99, 0x1f7c03a4, 0x243bae49, 0x29249c67,
0x2e34420f, 0x33686f85, 0x38bf3dff, 0x3e370182, },
{ 0x00000000, 0x0b504f33, 0x1c823e07, 0x30f39a55,
0x08facd62, 0x0c176319, 0x0f6b3522, 0x12efe2ad,
0x16a09e66, 0x1a79a317, 0x1e77e301, 0x2298d5b4,
0x26da56fc, 0x2b3a902a, 0x2fb7e7e7, 0x3450f650, },
{ 0x00000000, 0x09837f05, 0x17f910d7, 0x2929c7a9,
0x078d0dfa, 0x0a2ae661, 0x0cf73154, 0x0fec91cb,
0x1306fe0a, 0x16434a6c, 0x199ee595, 0x1d17ae3d,
0x20abd76a, 0x2459d551, 0x28204fbb, 0x2bfe1808, },
};
/* pow(j,4/3) for j=16..63, Q23 format */
const int pow43[] PROGMEM = {
0x1428a2fa, 0x15db1bd6, 0x1796302c, 0x19598d85,
0x1b24e8bb, 0x1cf7fcfa, 0x1ed28af2, 0x20b4582a,
0x229d2e6e, 0x248cdb55, 0x26832fda, 0x28800000,
0x2a832287, 0x2c8c70a8, 0x2e9bc5d8, 0x30b0ff99,
0x32cbfd4a, 0x34eca001, 0x3712ca62, 0x393e6088,
0x3b6f47e0, 0x3da56717, 0x3fe0a5fc, 0x4220ed72,
0x44662758, 0x46b03e7c, 0x48ff1e87, 0x4b52b3f3,
0x4daaebfd, 0x5007b497, 0x5268fc62, 0x54ceb29c,
0x5738c721, 0x59a72a59, 0x5c19cd35, 0x5e90a129,
0x610b9821, 0x638aa47f, 0x660db90f, 0x6894c90b,
0x6b1fc80c, 0x6daeaa0d, 0x70416360, 0x72d7e8b0,
0x75722ef9, 0x78102b85, 0x7ab1d3ec, 0x7d571e09,
};
/* sqrt(0.5) in Q31 format */
#define SQRTHALF 0x5a82799a
/*
* Minimax polynomial approximation to pow(x, 4/3), over the range
* poly43lo: x = [0.5, 0.7071]
* poly43hi: x = [0.7071, 1.0]
*
* Relative error < 1E-7
* Coefs are scaled by 4, 2, 1, 0.5, 0.25
*/
static const unsigned int poly43lo[5] PROGMEM = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 };
static const unsigned int poly43hi[5] PROGMEM = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 };
/* pow(2, i*4/3) as exp and frac */
const int pow2exp[8] PROGMEM = { 14, 13, 11, 10, 9, 7, 6, 5 };
const int pow2frac[8] PROGMEM = {
0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94,
0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6
};
/**************************************************************************************
* Function: DequantBlock
*
* Description: Ken's highly-optimized, low memory dequantizer performing the operation
* y = pow(x, 4.0/3.0) * pow(2, 25 - scale/4.0)
*
* Inputs: input buffer of decode Huffman codewords (signed-magnitude)
* output buffer of same length (in-place (outbuf = inbuf) is allowed)
* number of samples
*
* Outputs: dequantized samples in Q25 format
*
* Return: bitwise-OR of the unsigned outputs (for guard bit calculations)
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static int DequantBlock(int *inbuf, int *outbuf, int num, int scale)
{
int tab4[4];
int scalef, scalei, shift;
int sx, x, y;
int mask = 0;
const int *tab16;
const unsigned int *coef;
tab16 = pow43_14[scale & 0x3];
scalef = pow14[scale & 0x3];
scalei = MIN(scale >> 2, 31); /* smallest input scale = -47, so smallest scalei = -12 */
/* cache first 4 values */
shift = MIN(scalei + 3, 31);
shift = MAX(shift, 0);
tab4[0] = 0;
tab4[1] = tab16[1] >> shift;
tab4[2] = tab16[2] >> shift;
tab4[3] = tab16[3] >> shift;
do {
sx = *inbuf++;
x = sx & 0x7fffffff; /* sx = sign|mag */
if (x < 4) {
y = tab4[x];
} else if (x < 16) {
y = tab16[x];
y = (scalei < 0) ? y << -scalei : y >> scalei;
} else {
if (x < 64) {
y = pow43[x-16];
/* fractional scale */
y = MULSHIFT32(y, scalef);
shift = scalei - 3;
} else {
/* normalize to [0x40000000, 0x7fffffff] */
x <<= 17;
shift = 0;
if (x < 0x08000000)
x <<= 4, shift += 4;
if (x < 0x20000000)
x <<= 2, shift += 2;
if (x < 0x40000000)
x <<= 1, shift += 1;
coef = (x < SQRTHALF) ? poly43lo : poly43hi;
/* polynomial */
y = coef[0];
y = MULSHIFT32(y, x) + coef[1];
y = MULSHIFT32(y, x) + coef[2];
y = MULSHIFT32(y, x) + coef[3];
y = MULSHIFT32(y, x) + coef[4];
y = MULSHIFT32(y, pow2frac[shift]) << 3;
/* fractional scale */
y = MULSHIFT32(y, scalef);
shift = scalei - pow2exp[shift];
}
/* integer scale */
if (shift < 0) {
shift = -shift;
if (y > (0x7fffffff >> shift))
y = 0x7fffffff; /* clip */
else
y <<= shift;
} else {
y >>= shift;
}
}
/* sign and store */
mask |= y;
*outbuf++ = (sx < 0) ? -y : y;
} while (--num);
return mask;
}
/**************************************************************************************
* Function: DequantChannel
*
* Description: dequantize one granule, one channel worth of decoded Huffman codewords
*
* Inputs: sample buffer (decoded Huffman codewords), length = MAX_NSAMP samples
* work buffer for reordering short-block, length = MAX_REORDER_SAMPS
* samples (3 * width of largest short-block critical band)
* non-zero bound for this channel/granule
* valid FrameHeader, SideInfoSub, ScaleFactorInfoSub, and CriticalBandInfo
* structures for this channel/granule
*
* Outputs: MAX_NSAMP dequantized samples in sampleBuf
* updated non-zero bound (indicating which samples are != 0 after DQ)
* filled-in cbi structure indicating start and end critical bands
*
* Return: minimum number of guard bits in dequantized sampleBuf
*
* Notes: dequantized samples in Q(DQ_FRACBITS_OUT) format
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, FrameHeader *fh, SideInfoSub *sis,
ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi)
{
int i, j, w, cb;
int /* cbStartL, */ cbEndL, cbStartS, cbEndS;
int nSamps, nonZero, sfactMultiplier, gbMask;
int globalGain, gainI;
int cbMax[3];
ARRAY3 *buf; /* short block reorder */
/* set default start/end points for short/long blocks - will update with non-zero cb info */
if (sis->blockType == 2) {
// cbStartL = 0;
if (sis->mixedBlock) {
cbEndL = (fh->ver == MPEG1 ? 8 : 6);
cbStartS = 3;
} else {
cbEndL = 0;
cbStartS = 0;
}
cbEndS = 13;
} else {
/* long block */
//cbStartL = 0;
cbEndL = 22;
cbStartS = 13;
cbEndS = 13;
}
cbMax[2] = cbMax[1] = cbMax[0] = 0;
gbMask = 0;
i = 0;
/* sfactScale = 0 --> quantizer step size = 2
* sfactScale = 1 --> quantizer step size = sqrt(2)
* so sfactMultiplier = 2 or 4 (jump through globalGain by powers of 2 or sqrt(2))
*/
sfactMultiplier = 2 * (sis->sfactScale + 1);
/* offset globalGain by -2 if midSide enabled, for 1/sqrt(2) used in MidSideProc()
* (DequantBlock() does 0.25 * gainI so knocking it down by two is the same as
* dividing every sample by sqrt(2) = multiplying by 2^-.5)
*/
globalGain = sis->globalGain;
if (fh->modeExt >> 1)
globalGain -= 2;
globalGain += IMDCT_SCALE; /* scale everything by sqrt(2), for fast IMDCT36 */
/* long blocks */
for (cb = 0; cb < cbEndL; cb++) {
nonZero = 0;
nSamps = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb];
gainI = 210 - globalGain + sfactMultiplier * (sfis->l[cb] + (sis->preFlag ? (int)preTab[cb] : 0));
nonZero |= DequantBlock(sampleBuf + i, sampleBuf + i, nSamps, gainI);
i += nSamps;
/* update highest non-zero critical band */
if (nonZero)
cbMax[0] = cb;
gbMask |= nonZero;
if (i >= *nonZeroBound)
break;
}
/* set cbi (Type, EndS[], EndSMax will be overwritten if we proceed to do short blocks) */
cbi->cbType = 0; /* long only */
cbi->cbEndL = cbMax[0];
cbi->cbEndS[0] = cbi->cbEndS[1] = cbi->cbEndS[2] = 0;
cbi->cbEndSMax = 0;
/* early exit if no short blocks */
if (cbStartS >= 12)
return CLZ(gbMask) - 1;
/* short blocks */
cbMax[2] = cbMax[1] = cbMax[0] = cbStartS;
for (cb = cbStartS; cb < cbEndS; cb++) {
nSamps = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb];
for (w = 0; w < 3; w++) {
nonZero = 0;
gainI = 210 - globalGain + 8*sis->subBlockGain[w] + sfactMultiplier*(sfis->s[cb][w]);
nonZero |= DequantBlock(sampleBuf + i + nSamps*w, workBuf + nSamps*w, nSamps, gainI);
/* update highest non-zero critical band */
if (nonZero)
cbMax[w] = cb;
gbMask |= nonZero;
}
/* reorder blocks */
buf = (ARRAY3 *)(sampleBuf + i);
i += 3*nSamps;
for (j = 0; j < nSamps; j++) {
buf[j][0] = workBuf[0*nSamps + j];
buf[j][1] = workBuf[1*nSamps + j];
buf[j][2] = workBuf[2*nSamps + j];
}
ASSERT(3*nSamps <= MAX_REORDER_SAMPS);
if (i >= *nonZeroBound)
break;
}
/* i = last non-zero INPUT sample processed, which corresponds to highest possible non-zero
* OUTPUT sample (after reorder)
* however, the original nzb is no longer necessarily true
* for each cb, buf[][] is updated with 3*nSamps samples (i increases 3*nSamps each time)
* (buf[j + 1][0] = 3 (input) samples ahead of buf[j][0])
* so update nonZeroBound to i
*/
*nonZeroBound = i;
ASSERT(*nonZeroBound <= MAX_NSAMP);
cbi->cbType = (sis->mixedBlock ? 2 : 1); /* 2 = mixed short/long, 1 = short only */
cbi->cbEndS[0] = cbMax[0];
cbi->cbEndS[1] = cbMax[1];
cbi->cbEndS[2] = cbMax[2];
cbi->cbEndSMax = cbMax[0];
cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[1]);
cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[2]);
return CLZ(gbMask) - 1;
}

View File

@@ -1,462 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* July 2003
*
* huffman.c - Huffman decoding of transform coefficients
**************************************************************************************/
#include "coder.h"
#define PGM_READ_UNALIGNED 0 // Only support aligned reads, faster
/* helper macros - see comments in hufftabs.c about the format of the huffman tables */
#define GetMaxbits(x) ((int)( (((unsigned short)(x)) >> 0) & 0x000f))
#define GetHLen(x) ((int)( (((unsigned short)(x)) >> 12) & 0x000f))
#define GetCWY(x) ((int)( (((unsigned short)(x)) >> 8) & 0x000f))
#define GetCWX(x) ((int)( (((unsigned short)(x)) >> 4) & 0x000f))
#define GetSignBits(x) ((int)( (((unsigned short)(x)) >> 0) & 0x000f))
#define GetHLenQ(x) ((int)( (((unsigned char)(x)) >> 4) & 0x0f))
#define GetCWVQ(x) ((int)( (((unsigned char)(x)) >> 3) & 0x01))
#define GetCWWQ(x) ((int)( (((unsigned char)(x)) >> 2) & 0x01))
#define GetCWXQ(x) ((int)( (((unsigned char)(x)) >> 1) & 0x01))
#define GetCWYQ(x) ((int)( (((unsigned char)(x)) >> 0) & 0x01))
/* apply sign of s to the positive number x (save in MSB, will do two's complement in dequant) */
#define ApplySign(x, s) { (x) |= ((s) & 0x80000000); }
/**************************************************************************************
* Function: DecodeHuffmanPairs
*
* Description: decode 2-way vector Huffman codes in the "bigValues" region of spectrum
*
* Inputs: valid BitStreamInfo struct, pointing to start of pair-wise codes
* pointer to xy buffer to received decoded values
* number of codewords to decode
* index of Huffman table to use
* number of bits remaining in bitstream
*
* Outputs: pairs of decoded coefficients in vwxy
* updated BitStreamInfo struct
*
* Return: number of bits used, or -1 if out of bits
*
* Notes: assumes that nVals is an even number
* si_huff.bit tests every Huffman codeword in every table (though not
* necessarily all linBits outputs for x,y > 15)
**************************************************************************************/
// no improvement with section=data
static int DecodeHuffmanPairs(int *xy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset)
{
int i, x, y;
int cachedBits, padBits, len, startBits, linBits, maxBits, minBits;
HuffTabType tabType;
unsigned short cw, *tBase, *tCurr;
unsigned int cache;
if(nVals <= 0)
return 0;
if (bitsLeft < 0)
return -1;
startBits = bitsLeft;
tBase = (unsigned short *)(huffTable + huffTabOffset[tabIdx]);
linBits = huffTabLookup[tabIdx].linBits;
tabType = huffTabLookup[tabIdx].tabType;
ASSERT(!(nVals & 0x01));
ASSERT(tabIdx < HUFF_PAIRTABS);
ASSERT(tabIdx >= 0);
ASSERT(tabType != invalidTab);
/* initially fill cache with any partial byte */
cache = 0;
cachedBits = (8 - bitOffset) & 0x07;
if (cachedBits)
cache = (unsigned int)(*buf++) << (32 - cachedBits);
bitsLeft -= cachedBits;
if (tabType == noBits) {
/* table 0, no data, x = y = 0 */
for (i = 0; i < nVals; i+=2) {
xy[i+0] = 0;
xy[i+1] = 0;
}
return 0;
} else if (tabType == oneShot) {
/* single lookup, no escapes */
maxBits = GetMaxbits(pgm_read_word(&tBase[0]));
tBase++;
padBits = 0;
while (nVals > 0) {
/* refill cache - assumes cachedBits <= 16 */
if (bitsLeft >= 16) {
/* load 2 new bytes into left-justified cache */
cache |= (unsigned int)(*buf++) << (24 - cachedBits);
cache |= (unsigned int)(*buf++) << (16 - cachedBits);
cachedBits += 16;
bitsLeft -= 16;
} else {
/* last time through, pad cache with zeros and drain cache */
if (cachedBits + bitsLeft <= 0) return -1;
if (bitsLeft > 0) cache |= (unsigned int)(*buf++) << (24 - cachedBits);
if (bitsLeft > 8) cache |= (unsigned int)(*buf++) << (16 - cachedBits);
cachedBits += bitsLeft;
bitsLeft = 0;
cache &= (signed int)0x80000000 >> (cachedBits - 1);
padBits = 11;
cachedBits += padBits; /* okay if this is > 32 (0's automatically shifted in from right) */
}
/* largest maxBits = 9, plus 2 for sign bits, so make sure cache has at least 11 bits */
while (nVals > 0 && cachedBits >= 11 ) {
cw = pgm_read_word(&tBase[cache >> (32 - maxBits)]);
len = GetHLen(cw);
cachedBits -= len;
cache <<= len;
x = GetCWX(cw); if (x) {ApplySign(x, cache); cache <<= 1; cachedBits--;}
y = GetCWY(cw); if (y) {ApplySign(y, cache); cache <<= 1; cachedBits--;}
/* ran out of bits - should never have consumed padBits */
if (cachedBits < padBits)
return -1;
*xy++ = x;
*xy++ = y;
nVals -= 2;
}
}
bitsLeft += (cachedBits - padBits);
return (startBits - bitsLeft);
} else if (tabType == loopLinbits || tabType == loopNoLinbits) {
tCurr = tBase;
padBits = 0;
while (nVals > 0) {
/* refill cache - assumes cachedBits <= 16 */
if (bitsLeft >= 16) {
/* load 2 new bytes into left-justified cache */
cache |= (unsigned int)(*buf++) << (24 - cachedBits);
cache |= (unsigned int)(*buf++) << (16 - cachedBits);
cachedBits += 16;
bitsLeft -= 16;
} else {
/* last time through, pad cache with zeros and drain cache */
if (cachedBits + bitsLeft <= 0) return -1;
if (bitsLeft > 0) cache |= (unsigned int)(*buf++) << (24 - cachedBits);
if (bitsLeft > 8) cache |= (unsigned int)(*buf++) << (16 - cachedBits);
cachedBits += bitsLeft;
bitsLeft = 0;
cache &= (signed int)0x80000000 >> (cachedBits - 1);
padBits = 11;
cachedBits += padBits; /* okay if this is > 32 (0's automatically shifted in from right) */
}
/* largest maxBits = 9, plus 2 for sign bits, so make sure cache has at least 11 bits */
while (nVals > 0 && cachedBits >= 11 ) {
maxBits = GetMaxbits(pgm_read_word(&tCurr[0]));
cw = pgm_read_word(&tCurr[(cache >> (32 - maxBits)) + 1]);
len = GetHLen(cw);
if (!len) {
cachedBits -= maxBits;
cache <<= maxBits;
tCurr += cw;
continue;
}
cachedBits -= len;
cache <<= len;
x = GetCWX(cw);
y = GetCWY(cw);
if (x == 15 && tabType == loopLinbits) {
minBits = linBits + 1 + (y ? 1 : 0);
if (cachedBits + bitsLeft < minBits)
return -1;
while (cachedBits < minBits) {
cache |= (unsigned int)(*buf++) << (24 - cachedBits);
cachedBits += 8;
bitsLeft -= 8;
}
if (bitsLeft < 0) {
cachedBits += bitsLeft;
bitsLeft = 0;
cache &= (signed int)0x80000000 >> (cachedBits - 1);
}
x += (int)(cache >> (32 - linBits));
cachedBits -= linBits;
cache <<= linBits;
}
if (x) {ApplySign(x, cache); cache <<= 1; cachedBits--;}
if (y == 15 && tabType == loopLinbits) {
minBits = linBits + 1;
if (cachedBits + bitsLeft < minBits)
return -1;
while (cachedBits < minBits) {
cache |= (unsigned int)(*buf++) << (24 - cachedBits);
cachedBits += 8;
bitsLeft -= 8;
}
if (bitsLeft < 0) {
cachedBits += bitsLeft;
bitsLeft = 0;
cache &= (signed int)0x80000000 >> (cachedBits - 1);
}
y += (int)(cache >> (32 - linBits));
cachedBits -= linBits;
cache <<= linBits;
}
if (y) {ApplySign(y, cache); cache <<= 1; cachedBits--;}
/* ran out of bits - should never have consumed padBits */
if (cachedBits < padBits)
return -1;
*xy++ = x;
*xy++ = y;
nVals -= 2;
tCurr = tBase;
}
}
bitsLeft += (cachedBits - padBits);
return (startBits - bitsLeft);
}
/* error in bitstream - trying to access unused Huffman table */
return -1;
}
/**************************************************************************************
* Function: DecodeHuffmanQuads
*
* Description: decode 4-way vector Huffman codes in the "count1" region of spectrum
*
* Inputs: valid BitStreamInfo struct, pointing to start of quadword codes
* pointer to vwxy buffer to received decoded values
* maximum number of codewords to decode
* index of quadword table (0 = table A, 1 = table B)
* number of bits remaining in bitstream
*
* Outputs: quadruples of decoded coefficients in vwxy
* updated BitStreamInfo struct
*
* Return: index of the first "zero_part" value (index of the first sample
* of the quad word after which all samples are 0)
*
* Notes: si_huff.bit tests every vwxy output in both quad tables
**************************************************************************************/
// no improvement with section=data
static int DecodeHuffmanQuads(int *vwxy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset)
{
int i, v, w, x, y;
int len, maxBits, cachedBits, padBits;
unsigned int cache;
unsigned char cw, *tBase;
if (bitsLeft <= 0)
return 0;
tBase = (unsigned char *)quadTable + quadTabOffset[tabIdx];
maxBits = quadTabMaxBits[tabIdx];
/* initially fill cache with any partial byte */
cache = 0;
cachedBits = (8 - bitOffset) & 0x07;
if (cachedBits)
cache = (unsigned int)(*buf++) << (32 - cachedBits);
bitsLeft -= cachedBits;
i = padBits = 0;
while (i < (nVals - 3)) {
/* refill cache - assumes cachedBits <= 16 */
if (bitsLeft >= 16) {
/* load 2 new bytes into left-justified cache */
cache |= (unsigned int)(*buf++) << (24 - cachedBits);
cache |= (unsigned int)(*buf++) << (16 - cachedBits);
cachedBits += 16;
bitsLeft -= 16;
} else {
/* last time through, pad cache with zeros and drain cache */
if (cachedBits + bitsLeft <= 0) return i;
if (bitsLeft > 0) cache |= (unsigned int)(*buf++) << (24 - cachedBits);
if (bitsLeft > 8) cache |= (unsigned int)(*buf++) << (16 - cachedBits);
cachedBits += bitsLeft;
bitsLeft = 0;
cache &= (signed int)0x80000000 >> (cachedBits - 1);
padBits = 10;
cachedBits += padBits; /* okay if this is > 32 (0's automatically shifted in from right) */
}
/* largest maxBits = 6, plus 4 for sign bits, so make sure cache has at least 10 bits */
while (i < (nVals - 3) && cachedBits >= 10 ) {
cw = pgm_read_byte(&tBase[cache >> (32 - maxBits)]);
len = GetHLenQ(cw);
cachedBits -= len;
cache <<= len;
v = GetCWVQ(cw); if(v) {ApplySign(v, cache); cache <<= 1; cachedBits--;}
w = GetCWWQ(cw); if(w) {ApplySign(w, cache); cache <<= 1; cachedBits--;}
x = GetCWXQ(cw); if(x) {ApplySign(x, cache); cache <<= 1; cachedBits--;}
y = GetCWYQ(cw); if(y) {ApplySign(y, cache); cache <<= 1; cachedBits--;}
/* ran out of bits - okay (means we're done) */
if (cachedBits < padBits)
return i;
*vwxy++ = v;
*vwxy++ = w;
*vwxy++ = x;
*vwxy++ = y;
i += 4;
}
}
/* decoded max number of quad values */
return i;
}
/**************************************************************************************
* Function: DecodeHuffman
*
* Description: decode one granule, one channel worth of Huffman codes
*
* Inputs: MP3DecInfo structure filled by UnpackFrameHeader(), UnpackSideInfo(),
* and UnpackScaleFactors() (for this granule)
* buffer pointing to start of Huffman data in MP3 frame
* pointer to bit offset (0-7) indicating starting bit in buf[0]
* number of bits in the Huffman data section of the frame
* (could include padding bits)
* index of current granule and channel
*
* Outputs: decoded coefficients in hi->huffDecBuf[ch] (hi pointer in mp3DecInfo)
* updated bitOffset
*
* Return: length (in bytes) of Huffman codes
* bitOffset also returned in parameter (0 = MSB, 7 = LSB of
* byte located at buf + offset)
* -1 if null input pointers, huffBlockBits < 0, or decoder runs
* out of bits prematurely (invalid bitstream)
**************************************************************************************/
// .data about 1ms faster per frame
/* __attribute__ ((section (".data"))) */ int DecodeHuffman(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch)
{
int r1Start, r2Start, rEnd[4]; /* region boundaries */
int i, w, bitsUsed, bitsLeft;
unsigned char *startBuf = buf;
FrameHeader *fh;
SideInfo *si;
SideInfoSub *sis;
//ScaleFactorInfo *sfi;
HuffmanInfo *hi;
/* validate pointers */
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS || !mp3DecInfo->HuffmanInfoPS)
return -1;
fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS));
si = ((SideInfo *)(mp3DecInfo->SideInfoPS));
sis = &si->sis[gr][ch];
//sfi = ((ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS));
hi = (HuffmanInfo*)(mp3DecInfo->HuffmanInfoPS);
if (huffBlockBits < 0)
return -1;
/* figure out region boundaries (the first 2*bigVals coefficients divided into 3 regions) */
if (sis->winSwitchFlag && sis->blockType == 2) {
if (sis->mixedBlock == 0) {
r1Start = fh->sfBand->s[(sis->region0Count + 1)/3] * 3;
} else {
if (fh->ver == MPEG1) {
r1Start = fh->sfBand->l[sis->region0Count + 1];
} else {
/* see MPEG2 spec for explanation */
w = fh->sfBand->s[4] - fh->sfBand->s[3];
r1Start = fh->sfBand->l[6] + 2*w;
}
}
r2Start = MAX_NSAMP; /* short blocks don't have region 2 */
} else {
r1Start = fh->sfBand->l[sis->region0Count + 1];
r2Start = fh->sfBand->l[sis->region0Count + 1 + sis->region1Count + 1];
}
/* offset rEnd index by 1 so first region = rEnd[1] - rEnd[0], etc. */
rEnd[3] = MIN(MAX_NSAMP, 2 * sis->nBigvals);
rEnd[2] = MIN(r2Start, rEnd[3]);
rEnd[1] = MIN(r1Start, rEnd[3]);
rEnd[0] = 0;
/* rounds up to first all-zero pair (we don't check last pair for (x,y) == (non-zero, zero)) */
hi->nonZeroBound[ch] = rEnd[3];
/* decode Huffman pairs (rEnd[i] are always even numbers) */
bitsLeft = huffBlockBits;
for (i = 0; i < 3; i++) {
bitsUsed = DecodeHuffmanPairs(hi->huffDecBuf[ch] + rEnd[i], rEnd[i+1] - rEnd[i], sis->tableSelect[i], bitsLeft, buf, *bitOffset);
if (bitsUsed < 0 || bitsUsed > bitsLeft) /* error - overran end of bitstream */
return -1;
/* update bitstream position */
buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
bitsLeft -= bitsUsed;
}
/* decode Huffman quads (if any) */
hi->nonZeroBound[ch] += DecodeHuffmanQuads(hi->huffDecBuf[ch] + rEnd[3], MAX_NSAMP - rEnd[3], sis->count1TableSelect, bitsLeft, buf, *bitOffset);
ASSERT(hi->nonZeroBound[ch] <= MAX_NSAMP);
for (i = hi->nonZeroBound[ch]; i < MAX_NSAMP; i++)
hi->huffDecBuf[ch][i] = 0;
/* If bits used for 576 samples < huffBlockBits, then the extras are considered
* to be stuffing bits (throw away, but need to return correct bitstream position)
*/
buf += (bitsLeft + *bitOffset) >> 3;
*bitOffset = (bitsLeft + *bitOffset) & 0x07;
return (buf - startBuf);
}

View File

@@ -1,755 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* hufftabs.c - compressed Huffman code tables
**************************************************************************************/
#include "coder.h"
/* NOTE - regenerated tables to use shorts instead of ints
* (all needed data can fit in 16 bits - see below)
*
* format 0xABCD
* A = length of codeword
* B = y value
* C = x value
* D = number of sign bits (0, 1, or 2)
*
* to read a CW, the code reads maxbits from the stream (dep. on
* table index), but doesn't remove them from the bitstream reader
* then it gets the correct CW by direct lookup into the table
* of length (2^maxbits) (more complicated for non-oneShot...)
* for CW's with hlen < maxbits, there are multiple entries in the
* table (extra bits are don't cares)
* the bitstream reader then "purges" (or removes) only the correct
* number of bits for the chosen CW
*
* entries starting with F are special: D (signbits) is maxbits,
* so the decoder always checks huffTableXX[0] first, gets the
* signbits, and reads that many bits from the bitstream
* (sometimes it takes > 1 read to get the value, so maxbits is
* can get updated by jumping to another value starting with 0xF)
* entries starting with 0 are also special: A = hlen = 0, rest of
* value is an offset to jump higher in the table (for tables of
* type loopNoLinbits or loopLinbits)
*/
/* store Huffman codes as one big table plus table of offsets, since some platforms
* don't properly support table-of-tables (table of pointers to other const tables)
*/
const unsigned short huffTable[] PROGMEM = {
/* huffTable01[9] */
0xf003, 0x3112, 0x3101, 0x2011, 0x2011, 0x1000, 0x1000, 0x1000,
0x1000,
/* huffTable02[65] */
0xf006, 0x6222, 0x6201, 0x5212, 0x5212, 0x5122, 0x5122, 0x5021,
0x5021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000,
/* huffTable03[65] */
0xf006, 0x6222, 0x6201, 0x5212, 0x5212, 0x5122, 0x5122, 0x5021,
0x5021, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101,
0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101,
0x2101, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000,
/* huffTable05[257] */
0xf008, 0x8332, 0x8322, 0x7232, 0x7232, 0x6132, 0x6132, 0x6132,
0x6132, 0x7312, 0x7312, 0x7301, 0x7301, 0x7031, 0x7031, 0x7222,
0x7222, 0x6212, 0x6212, 0x6212, 0x6212, 0x6122, 0x6122, 0x6122,
0x6122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021,
0x6021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000,
/* huffTable06[129] */
0xf007, 0x7332, 0x7301, 0x6322, 0x6322, 0x6232, 0x6232, 0x6031,
0x6031, 0x5312, 0x5312, 0x5312, 0x5312, 0x5132, 0x5132, 0x5132,
0x5132, 0x5222, 0x5222, 0x5222, 0x5222, 0x5201, 0x5201, 0x5201,
0x5201, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212,
0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122,
0x4122, 0x4021, 0x4021, 0x4021, 0x4021, 0x4021, 0x4021, 0x4021,
0x4021, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000,
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000,
0x3000,
/* huffTable07[110] */
0xf006, 0x0041, 0x0052, 0x005b, 0x0060, 0x0063, 0x0068, 0x006b,
0x6212, 0x5122, 0x5122, 0x6201, 0x6021, 0x4112, 0x4112, 0x4112,
0x4112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0xf004, 0x4552, 0x4542, 0x4452, 0x4352, 0x3532, 0x3532,
0x3442, 0x3442, 0x3522, 0x3522, 0x3252, 0x3252, 0x2512, 0x2512,
0x2512, 0x2512, 0xf003, 0x2152, 0x2152, 0x3501, 0x3432, 0x2051,
0x2051, 0x3342, 0x3332, 0xf002, 0x2422, 0x2242, 0x1412, 0x1412,
0xf001, 0x1142, 0x1041, 0xf002, 0x2401, 0x2322, 0x2232, 0x2301,
0xf001, 0x1312, 0x1132, 0xf001, 0x1031, 0x1222,
/* huffTable08[280] */
0xf008, 0x0101, 0x010a, 0x010f, 0x8512, 0x8152, 0x0112, 0x0115,
0x8422, 0x8242, 0x8412, 0x7142, 0x7142, 0x8401, 0x8041, 0x8322,
0x8232, 0x8312, 0x8132, 0x8301, 0x8031, 0x6222, 0x6222, 0x6222,
0x6222, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021,
0x6021, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212,
0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212,
0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122,
0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122,
0x4122, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112,
0x2112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0xf003, 0x3552, 0x3452, 0x2542, 0x2542, 0x1352, 0x1352,
0x1352, 0x1352, 0xf002, 0x2532, 0x2442, 0x1522, 0x1522, 0xf001,
0x1252, 0x1501, 0xf001, 0x1432, 0x1342, 0xf001, 0x1051, 0x1332,
/* huffTable09[93] */
0xf006, 0x0041, 0x004a, 0x004f, 0x0052, 0x0057, 0x005a, 0x6412,
0x6142, 0x6322, 0x6232, 0x5312, 0x5312, 0x5132, 0x5132, 0x6301,
0x6031, 0x5222, 0x5222, 0x5201, 0x5201, 0x4212, 0x4212, 0x4212,
0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4021, 0x4021, 0x4021,
0x4021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000,
0x3000, 0xf003, 0x3552, 0x3542, 0x2532, 0x2532, 0x2352, 0x2352,
0x3452, 0x3501, 0xf002, 0x2442, 0x2522, 0x2252, 0x2512, 0xf001,
0x1152, 0x1432, 0xf002, 0x1342, 0x1342, 0x2051, 0x2401, 0xf001,
0x1422, 0x1242, 0xf001, 0x1332, 0x1041,
/* huffTable10[320] */
0xf008, 0x0101, 0x010a, 0x010f, 0x0118, 0x011b, 0x0120, 0x0125,
0x8712, 0x8172, 0x012a, 0x012d, 0x0132, 0x8612, 0x8162, 0x8061,
0x0137, 0x013a, 0x013d, 0x8412, 0x8142, 0x8041, 0x8322, 0x8232,
0x8301, 0x7312, 0x7312, 0x7132, 0x7132, 0x7031, 0x7031, 0x7222,
0x7222, 0x6212, 0x6212, 0x6212, 0x6212, 0x6122, 0x6122, 0x6122,
0x6122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021,
0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0xf003, 0x3772, 0x3762, 0x3672, 0x3752, 0x3572, 0x3662,
0x2742, 0x2742, 0xf002, 0x2472, 0x2652, 0x2562, 0x2732, 0xf003,
0x2372, 0x2372, 0x2642, 0x2642, 0x3552, 0x3452, 0x2362, 0x2362,
0xf001, 0x1722, 0x1272, 0xf002, 0x2462, 0x2701, 0x1071, 0x1071,
0xf002, 0x1262, 0x1262, 0x2542, 0x2532, 0xf002, 0x1601, 0x1601,
0x2352, 0x2442, 0xf001, 0x1632, 0x1622, 0xf002, 0x2522, 0x2252,
0x1512, 0x1512, 0xf002, 0x1152, 0x1152, 0x2432, 0x2342, 0xf001,
0x1501, 0x1051, 0xf001, 0x1422, 0x1242, 0xf001, 0x1332, 0x1401,
/* huffTable11[296] */
0xf008, 0x0101, 0x0106, 0x010f, 0x0114, 0x0117, 0x8722, 0x8272,
0x011c, 0x7172, 0x7172, 0x8712, 0x8071, 0x8632, 0x8362, 0x8061,
0x011f, 0x0122, 0x8512, 0x7262, 0x7262, 0x8622, 0x8601, 0x7612,
0x7612, 0x7162, 0x7162, 0x8152, 0x8432, 0x8051, 0x0125, 0x8422,
0x8242, 0x8412, 0x8142, 0x8401, 0x8041, 0x7322, 0x7322, 0x7232,
0x7232, 0x6312, 0x6312, 0x6312, 0x6312, 0x6132, 0x6132, 0x6132,
0x6132, 0x7301, 0x7301, 0x7031, 0x7031, 0x6222, 0x6222, 0x6222,
0x6222, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122,
0x5122, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212,
0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212,
0x4212, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201,
0x5201, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021,
0x5021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000,
0x2000, 0xf002, 0x2772, 0x2762, 0x2672, 0x2572, 0xf003, 0x2662,
0x2662, 0x2742, 0x2742, 0x2472, 0x2472, 0x3752, 0x3552, 0xf002,
0x2652, 0x2562, 0x1732, 0x1732, 0xf001, 0x1372, 0x1642, 0xf002,
0x2542, 0x2452, 0x2532, 0x2352, 0xf001, 0x1462, 0x1701, 0xf001,
0x1442, 0x1522, 0xf001, 0x1252, 0x1501, 0xf001, 0x1342, 0x1332,
/* huffTable12[185] */
0xf007, 0x0081, 0x008a, 0x008f, 0x0092, 0x0097, 0x009a, 0x009d,
0x00a2, 0x00a5, 0x00a8, 0x7622, 0x7262, 0x7162, 0x00ad, 0x00b0,
0x00b3, 0x7512, 0x7152, 0x7432, 0x7342, 0x00b6, 0x7422, 0x7242,
0x7412, 0x6332, 0x6332, 0x6142, 0x6142, 0x6322, 0x6322, 0x6232,
0x6232, 0x7041, 0x7301, 0x6031, 0x6031, 0x5312, 0x5312, 0x5312,
0x5312, 0x5132, 0x5132, 0x5132, 0x5132, 0x5222, 0x5222, 0x5222,
0x5222, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212,
0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122,
0x4122, 0x5201, 0x5201, 0x5201, 0x5201, 0x5021, 0x5021, 0x5021,
0x5021, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
0x4000, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101,
0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0xf003, 0x3772, 0x3762, 0x2672, 0x2672, 0x2752, 0x2752,
0x2572, 0x2572, 0xf002, 0x2662, 0x2742, 0x2472, 0x2562, 0xf001,
0x1652, 0x1732, 0xf002, 0x2372, 0x2552, 0x1722, 0x1722, 0xf001,
0x1272, 0x1642, 0xf001, 0x1462, 0x1712, 0xf002, 0x1172, 0x1172,
0x2701, 0x2071, 0xf001, 0x1632, 0x1362, 0xf001, 0x1542, 0x1452,
0xf002, 0x1442, 0x1442, 0x2601, 0x2501, 0xf001, 0x1612, 0x1061,
0xf001, 0x1532, 0x1352, 0xf001, 0x1522, 0x1252, 0xf001, 0x1051,
0x1401,
/* huffTable13[497] */
0xf006, 0x0041, 0x0082, 0x00c3, 0x00e4, 0x0105, 0x0116, 0x011f,
0x0130, 0x0139, 0x013e, 0x0143, 0x0146, 0x6212, 0x6122, 0x6201,
0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4101, 0x4101, 0x4101,
0x4101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0xf006, 0x0108, 0x0111, 0x011a, 0x0123, 0x012c, 0x0131,
0x0136, 0x013f, 0x0144, 0x0147, 0x014c, 0x0151, 0x0156, 0x015b,
0x6f12, 0x61f2, 0x60f1, 0x0160, 0x0163, 0x0166, 0x62e2, 0x0169,
0x6e12, 0x61e2, 0x016c, 0x016f, 0x0172, 0x0175, 0x0178, 0x017b,
0x66c2, 0x6d32, 0x017e, 0x6d22, 0x62d2, 0x6d12, 0x67b2, 0x0181,
0x0184, 0x63c2, 0x0187, 0x6b42, 0x51d2, 0x51d2, 0x6d01, 0x60d1,
0x6a82, 0x68a2, 0x6c42, 0x64c2, 0x6b62, 0x66b2, 0x5c32, 0x5c32,
0x5c22, 0x5c22, 0x52c2, 0x52c2, 0x5b52, 0x5b52, 0x65b2, 0x6982,
0x5c12, 0x5c12, 0xf006, 0x51c2, 0x51c2, 0x6892, 0x6c01, 0x50c1,
0x50c1, 0x64b2, 0x6a62, 0x66a2, 0x6972, 0x5b32, 0x5b32, 0x53b2,
0x53b2, 0x6882, 0x6a52, 0x5b22, 0x5b22, 0x65a2, 0x6962, 0x54a2,
0x54a2, 0x6872, 0x6782, 0x5492, 0x5492, 0x6772, 0x6672, 0x42b2,
0x42b2, 0x42b2, 0x42b2, 0x4b12, 0x4b12, 0x4b12, 0x4b12, 0x41b2,
0x41b2, 0x41b2, 0x41b2, 0x5b01, 0x5b01, 0x50b1, 0x50b1, 0x5692,
0x5692, 0x5a42, 0x5a42, 0x5a32, 0x5a32, 0x53a2, 0x53a2, 0x5952,
0x5952, 0x5592, 0x5592, 0x4a22, 0x4a22, 0x4a22, 0x4a22, 0x42a2,
0x42a2, 0x42a2, 0x42a2, 0xf005, 0x4a12, 0x4a12, 0x41a2, 0x41a2,
0x5a01, 0x5862, 0x40a1, 0x40a1, 0x5682, 0x5942, 0x4392, 0x4392,
0x5932, 0x5852, 0x5582, 0x5762, 0x4922, 0x4922, 0x4292, 0x4292,
0x5752, 0x5572, 0x4832, 0x4832, 0x4382, 0x4382, 0x5662, 0x5742,
0x5472, 0x5652, 0x5562, 0x5372, 0xf005, 0x3912, 0x3912, 0x3912,
0x3912, 0x3192, 0x3192, 0x3192, 0x3192, 0x4901, 0x4901, 0x4091,
0x4091, 0x4842, 0x4842, 0x4482, 0x4482, 0x4272, 0x4272, 0x5642,
0x5462, 0x3822, 0x3822, 0x3822, 0x3822, 0x3282, 0x3282, 0x3282,
0x3282, 0x3812, 0x3812, 0x3812, 0x3812, 0xf004, 0x4732, 0x4722,
0x3712, 0x3712, 0x3172, 0x3172, 0x4552, 0x4701, 0x4071, 0x4632,
0x4362, 0x4542, 0x4452, 0x4622, 0x4262, 0x4532, 0xf003, 0x2182,
0x2182, 0x3801, 0x3081, 0x3612, 0x3162, 0x3601, 0x3061, 0xf004,
0x4352, 0x4442, 0x3522, 0x3522, 0x3252, 0x3252, 0x3501, 0x3501,
0x2512, 0x2512, 0x2512, 0x2512, 0x2152, 0x2152, 0x2152, 0x2152,
0xf003, 0x3432, 0x3342, 0x3051, 0x3422, 0x3242, 0x3332, 0x2412,
0x2412, 0xf002, 0x1142, 0x1142, 0x2401, 0x2041, 0xf002, 0x2322,
0x2232, 0x1312, 0x1312, 0xf001, 0x1132, 0x1301, 0xf001, 0x1031,
0x1222, 0xf003, 0x0082, 0x008b, 0x008e, 0x0091, 0x0094, 0x0097,
0x3ce2, 0x3dd2, 0xf003, 0x0093, 0x3eb2, 0x3be2, 0x3f92, 0x39f2,
0x3ae2, 0x3db2, 0x3bd2, 0xf003, 0x3f82, 0x38f2, 0x3cc2, 0x008d,
0x3e82, 0x0090, 0x27f2, 0x27f2, 0xf003, 0x2ad2, 0x2ad2, 0x3da2,
0x3cb2, 0x3bc2, 0x36f2, 0x2f62, 0x2f62, 0xf002, 0x28e2, 0x2f52,
0x2d92, 0x29d2, 0xf002, 0x25f2, 0x27e2, 0x2ca2, 0x2bb2, 0xf003,
0x2f42, 0x2f42, 0x24f2, 0x24f2, 0x3ac2, 0x36e2, 0x23f2, 0x23f2,
0xf002, 0x1f32, 0x1f32, 0x2d82, 0x28d2, 0xf001, 0x1f22, 0x12f2,
0xf002, 0x2e62, 0x2c92, 0x1f01, 0x1f01, 0xf002, 0x29c2, 0x2e52,
0x1ba2, 0x1ba2, 0xf002, 0x2d72, 0x27d2, 0x1e42, 0x1e42, 0xf002,
0x28c2, 0x26d2, 0x1e32, 0x1e32, 0xf002, 0x19b2, 0x19b2, 0x2b92,
0x2aa2, 0xf001, 0x1ab2, 0x15e2, 0xf001, 0x14e2, 0x1c82, 0xf001,
0x1d62, 0x13e2, 0xf001, 0x1e22, 0x1e01, 0xf001, 0x10e1, 0x1d52,
0xf001, 0x15d2, 0x1c72, 0xf001, 0x17c2, 0x1d42, 0xf001, 0x1b82,
0x18b2, 0xf001, 0x14d2, 0x1a92, 0xf001, 0x19a2, 0x1c62, 0xf001,
0x13d2, 0x1b72, 0xf001, 0x1c52, 0x15c2, 0xf001, 0x1992, 0x1a72,
0xf001, 0x17a2, 0x1792, 0xf003, 0x0023, 0x3df2, 0x2de2, 0x2de2,
0x1ff2, 0x1ff2, 0x1ff2, 0x1ff2, 0xf001, 0x1fe2, 0x1fd2, 0xf001,
0x1ee2, 0x1fc2, 0xf001, 0x1ed2, 0x1fb2, 0xf001, 0x1bf2, 0x1ec2,
0xf002, 0x1cd2, 0x1cd2, 0x2fa2, 0x29e2, 0xf001, 0x1af2, 0x1dc2,
0xf001, 0x1ea2, 0x1e92, 0xf001, 0x1f72, 0x1e72, 0xf001, 0x1ef2,
0x1cf2,
/* huffTable15[580] */
0xf008, 0x0101, 0x0122, 0x0143, 0x0154, 0x0165, 0x0176, 0x017f,
0x0188, 0x0199, 0x01a2, 0x01ab, 0x01b4, 0x01bd, 0x01c2, 0x01cb,
0x01d4, 0x01d9, 0x01de, 0x01e3, 0x01e8, 0x01ed, 0x01f2, 0x01f7,
0x01fc, 0x0201, 0x0204, 0x0207, 0x020a, 0x020f, 0x0212, 0x0215,
0x021a, 0x021d, 0x0220, 0x8192, 0x0223, 0x0226, 0x0229, 0x022c,
0x022f, 0x8822, 0x8282, 0x8812, 0x8182, 0x0232, 0x0235, 0x0238,
0x023b, 0x8722, 0x8272, 0x8462, 0x8712, 0x8552, 0x8172, 0x023e,
0x8632, 0x8362, 0x8542, 0x8452, 0x8622, 0x8262, 0x8612, 0x0241,
0x8532, 0x7162, 0x7162, 0x8352, 0x8442, 0x7522, 0x7522, 0x7252,
0x7252, 0x7512, 0x7512, 0x7152, 0x7152, 0x8501, 0x8051, 0x7432,
0x7432, 0x7342, 0x7342, 0x7422, 0x7422, 0x7242, 0x7242, 0x7332,
0x7332, 0x6142, 0x6142, 0x6142, 0x6142, 0x7412, 0x7412, 0x7401,
0x7401, 0x6322, 0x6322, 0x6322, 0x6322, 0x6232, 0x6232, 0x6232,
0x6232, 0x7041, 0x7041, 0x7301, 0x7301, 0x6312, 0x6312, 0x6312,
0x6312, 0x6132, 0x6132, 0x6132, 0x6132, 0x6031, 0x6031, 0x6031,
0x6031, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222,
0x5222, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212,
0x5212, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122,
0x5122, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201,
0x5201, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021,
0x5021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112,
0x3112, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011,
0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011,
0x4011, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000,
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000,
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000,
0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000,
0x3000, 0xf005, 0x5ff2, 0x5fe2, 0x5ef2, 0x5fd2, 0x4ee2, 0x4ee2,
0x5df2, 0x5fc2, 0x5cf2, 0x5ed2, 0x5de2, 0x5fb2, 0x4bf2, 0x4bf2,
0x5ec2, 0x5ce2, 0x4dd2, 0x4dd2, 0x4fa2, 0x4fa2, 0x4af2, 0x4af2,
0x4eb2, 0x4eb2, 0x4be2, 0x4be2, 0x4dc2, 0x4dc2, 0x4cd2, 0x4cd2,
0x4f92, 0x4f92, 0xf005, 0x49f2, 0x49f2, 0x4ae2, 0x4ae2, 0x4db2,
0x4db2, 0x4bd2, 0x4bd2, 0x4f82, 0x4f82, 0x48f2, 0x48f2, 0x4cc2,
0x4cc2, 0x4e92, 0x4e92, 0x49e2, 0x49e2, 0x4f72, 0x4f72, 0x47f2,
0x47f2, 0x4da2, 0x4da2, 0x4ad2, 0x4ad2, 0x4cb2, 0x4cb2, 0x4f62,
0x4f62, 0x5ea2, 0x5f01, 0xf004, 0x3bc2, 0x3bc2, 0x36f2, 0x36f2,
0x4e82, 0x48e2, 0x4f52, 0x4d92, 0x35f2, 0x35f2, 0x3e72, 0x3e72,
0x37e2, 0x37e2, 0x3ca2, 0x3ca2, 0xf004, 0x3ac2, 0x3ac2, 0x3bb2,
0x3bb2, 0x49d2, 0x4d82, 0x3f42, 0x3f42, 0x34f2, 0x34f2, 0x3f32,
0x3f32, 0x33f2, 0x33f2, 0x38d2, 0x38d2, 0xf004, 0x36e2, 0x36e2,
0x3f22, 0x3f22, 0x32f2, 0x32f2, 0x4e62, 0x40f1, 0x3f12, 0x3f12,
0x31f2, 0x31f2, 0x3c92, 0x3c92, 0x39c2, 0x39c2, 0xf003, 0x3e52,
0x3ba2, 0x3ab2, 0x35e2, 0x3d72, 0x37d2, 0x3e42, 0x34e2, 0xf003,
0x3c82, 0x38c2, 0x3e32, 0x3d62, 0x36d2, 0x33e2, 0x3b92, 0x39b2,
0xf004, 0x3e22, 0x3e22, 0x3aa2, 0x3aa2, 0x32e2, 0x32e2, 0x3e12,
0x3e12, 0x31e2, 0x31e2, 0x4e01, 0x40e1, 0x3d52, 0x3d52, 0x35d2,
0x35d2, 0xf003, 0x3c72, 0x37c2, 0x3d42, 0x3b82, 0x24d2, 0x24d2,
0x38b2, 0x3a92, 0xf003, 0x39a2, 0x3c62, 0x36c2, 0x3d32, 0x23d2,
0x23d2, 0x22d2, 0x22d2, 0xf003, 0x3d22, 0x3d01, 0x2d12, 0x2d12,
0x2b72, 0x2b72, 0x27b2, 0x27b2, 0xf003, 0x21d2, 0x21d2, 0x3c52,
0x30d1, 0x25c2, 0x25c2, 0x2a82, 0x2a82, 0xf002, 0x28a2, 0x2c42,
0x24c2, 0x2b62, 0xf003, 0x26b2, 0x26b2, 0x3992, 0x3c01, 0x2c32,
0x2c32, 0x23c2, 0x23c2, 0xf003, 0x2a72, 0x2a72, 0x27a2, 0x27a2,
0x26a2, 0x26a2, 0x30c1, 0x3b01, 0xf002, 0x12c2, 0x12c2, 0x2c22,
0x2b52, 0xf002, 0x25b2, 0x2c12, 0x2982, 0x2892, 0xf002, 0x21c2,
0x2b42, 0x24b2, 0x2a62, 0xf002, 0x2b32, 0x2972, 0x13b2, 0x13b2,
0xf002, 0x2792, 0x2882, 0x2b22, 0x2a52, 0xf002, 0x12b2, 0x12b2,
0x25a2, 0x2b12, 0xf002, 0x11b2, 0x11b2, 0x20b1, 0x2962, 0xf002,
0x2692, 0x2a42, 0x24a2, 0x2872, 0xf002, 0x2782, 0x2a32, 0x13a2,
0x13a2, 0xf001, 0x1952, 0x1592, 0xf001, 0x1a22, 0x12a2, 0xf001,
0x1a12, 0x11a2, 0xf002, 0x2a01, 0x20a1, 0x1862, 0x1862, 0xf001,
0x1682, 0x1942, 0xf001, 0x1492, 0x1932, 0xf002, 0x1392, 0x1392,
0x2772, 0x2901, 0xf001, 0x1852, 0x1582, 0xf001, 0x1922, 0x1762,
0xf001, 0x1672, 0x1292, 0xf001, 0x1912, 0x1091, 0xf001, 0x1842,
0x1482, 0xf001, 0x1752, 0x1572, 0xf001, 0x1832, 0x1382, 0xf001,
0x1662, 0x1742, 0xf001, 0x1472, 0x1801, 0xf001, 0x1081, 0x1652,
0xf001, 0x1562, 0x1732, 0xf001, 0x1372, 0x1642, 0xf001, 0x1701,
0x1071, 0xf001, 0x1601, 0x1061,
/* huffTable16[651] */
0xf008, 0x0101, 0x010a, 0x0113, 0x8ff2, 0x0118, 0x011d, 0x0120,
0x82f2, 0x0131, 0x8f12, 0x81f2, 0x0134, 0x0145, 0x0156, 0x0167,
0x0178, 0x0189, 0x019a, 0x01a3, 0x01ac, 0x01b5, 0x01be, 0x01c7,
0x01d0, 0x01d9, 0x01de, 0x01e3, 0x01e6, 0x01eb, 0x01f0, 0x8152,
0x01f3, 0x01f6, 0x01f9, 0x01fc, 0x8412, 0x8142, 0x01ff, 0x8322,
0x8232, 0x7312, 0x7312, 0x7132, 0x7132, 0x8301, 0x8031, 0x7222,
0x7222, 0x6212, 0x6212, 0x6212, 0x6212, 0x6122, 0x6122, 0x6122,
0x6122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021,
0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011,
0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0xf003, 0x3fe2, 0x3ef2, 0x3fd2, 0x3df2, 0x3fc2, 0x3cf2,
0x3fb2, 0x3bf2, 0xf003, 0x2fa2, 0x2fa2, 0x3af2, 0x3f92, 0x39f2,
0x38f2, 0x2f82, 0x2f82, 0xf002, 0x2f72, 0x27f2, 0x2f62, 0x26f2,
0xf002, 0x2f52, 0x25f2, 0x1f42, 0x1f42, 0xf001, 0x14f2, 0x13f2,
0xf004, 0x10f1, 0x10f1, 0x10f1, 0x10f1, 0x10f1, 0x10f1, 0x10f1,
0x10f1, 0x2f32, 0x2f32, 0x2f32, 0x2f32, 0x00e2, 0x00f3, 0x00fc,
0x0105, 0xf001, 0x1f22, 0x1f01, 0xf004, 0x00fa, 0x00ff, 0x0104,
0x0109, 0x010c, 0x0111, 0x0116, 0x0119, 0x011e, 0x0123, 0x0128,
0x43e2, 0x012d, 0x0130, 0x0133, 0x0136, 0xf004, 0x0128, 0x012b,
0x012e, 0x4d01, 0x0131, 0x0134, 0x0137, 0x4c32, 0x013a, 0x4c12,
0x40c1, 0x013d, 0x32e2, 0x32e2, 0x4e22, 0x4e12, 0xf004, 0x43d2,
0x4d22, 0x42d2, 0x41d2, 0x4b32, 0x012f, 0x3d12, 0x3d12, 0x44c2,
0x4b62, 0x43c2, 0x47a2, 0x3c22, 0x3c22, 0x42c2, 0x45b2, 0xf004,
0x41c2, 0x4c01, 0x4b42, 0x44b2, 0x4a62, 0x46a2, 0x33b2, 0x33b2,
0x4a52, 0x45a2, 0x3b22, 0x3b22, 0x32b2, 0x32b2, 0x3b12, 0x3b12,
0xf004, 0x31b2, 0x31b2, 0x4b01, 0x40b1, 0x4962, 0x4692, 0x4a42,
0x44a2, 0x4872, 0x4782, 0x33a2, 0x33a2, 0x4a32, 0x4952, 0x3a22,
0x3a22, 0xf004, 0x4592, 0x4862, 0x31a2, 0x31a2, 0x4682, 0x4772,
0x3492, 0x3492, 0x4942, 0x4752, 0x3762, 0x3762, 0x22a2, 0x22a2,
0x22a2, 0x22a2, 0xf003, 0x2a12, 0x2a12, 0x3a01, 0x30a1, 0x3932,
0x3392, 0x3852, 0x3582, 0xf003, 0x2922, 0x2922, 0x2292, 0x2292,
0x3672, 0x3901, 0x2912, 0x2912, 0xf003, 0x2192, 0x2192, 0x3091,
0x3842, 0x3482, 0x3572, 0x3832, 0x3382, 0xf003, 0x3662, 0x3822,
0x2282, 0x2282, 0x3742, 0x3472, 0x2812, 0x2812, 0xf003, 0x2182,
0x2182, 0x2081, 0x2081, 0x3801, 0x3652, 0x2732, 0x2732, 0xf003,
0x2372, 0x2372, 0x3562, 0x3642, 0x2722, 0x2722, 0x2272, 0x2272,
0xf003, 0x3462, 0x3552, 0x2701, 0x2701, 0x1712, 0x1712, 0x1712,
0x1712, 0xf002, 0x1172, 0x1172, 0x2071, 0x2632, 0xf002, 0x2362,
0x2542, 0x2452, 0x2622, 0xf001, 0x1262, 0x1612, 0xf002, 0x1162,
0x1162, 0x2601, 0x2061, 0xf002, 0x1352, 0x1352, 0x2532, 0x2442,
0xf001, 0x1522, 0x1252, 0xf001, 0x1512, 0x1501, 0xf001, 0x1432,
0x1342, 0xf001, 0x1051, 0x1422, 0xf001, 0x1242, 0x1332, 0xf001,
0x1401, 0x1041, 0xf004, 0x4ec2, 0x0086, 0x3ed2, 0x3ed2, 0x39e2,
0x39e2, 0x4ae2, 0x49d2, 0x2ee2, 0x2ee2, 0x2ee2, 0x2ee2, 0x3de2,
0x3de2, 0x3be2, 0x3be2, 0xf003, 0x2eb2, 0x2eb2, 0x2dc2, 0x2dc2,
0x3cd2, 0x3bd2, 0x2ea2, 0x2ea2, 0xf003, 0x2cc2, 0x2cc2, 0x3da2,
0x3ad2, 0x3e72, 0x3ca2, 0x2ac2, 0x2ac2, 0xf003, 0x39c2, 0x3d72,
0x2e52, 0x2e52, 0x1db2, 0x1db2, 0x1db2, 0x1db2, 0xf002, 0x1e92,
0x1e92, 0x2cb2, 0x2bc2, 0xf002, 0x2e82, 0x28e2, 0x2d92, 0x27e2,
0xf002, 0x2bb2, 0x2d82, 0x28d2, 0x2e62, 0xf001, 0x16e2, 0x1c92,
0xf002, 0x2ba2, 0x2ab2, 0x25e2, 0x27d2, 0xf002, 0x1e42, 0x1e42,
0x24e2, 0x2c82, 0xf001, 0x18c2, 0x1e32, 0xf002, 0x1d62, 0x1d62,
0x26d2, 0x2b92, 0xf002, 0x29b2, 0x2aa2, 0x11e2, 0x11e2, 0xf002,
0x14d2, 0x14d2, 0x28b2, 0x29a2, 0xf002, 0x1b72, 0x1b72, 0x27b2,
0x20d1, 0xf001, 0x1e01, 0x10e1, 0xf001, 0x1d52, 0x15d2, 0xf001,
0x1c72, 0x17c2, 0xf001, 0x1d42, 0x1b82, 0xf001, 0x1a92, 0x1c62,
0xf001, 0x16c2, 0x1d32, 0xf001, 0x1c52, 0x15c2, 0xf001, 0x1a82,
0x18a2, 0xf001, 0x1992, 0x1c42, 0xf001, 0x16b2, 0x1a72, 0xf001,
0x1b52, 0x1982, 0xf001, 0x1892, 0x1972, 0xf001, 0x1792, 0x1882,
0xf001, 0x1ce2, 0x1dd2,
/* huffTable24[705] */
0xf009, 0x8fe2, 0x8fe2, 0x8ef2, 0x8ef2, 0x8fd2, 0x8fd2, 0x8df2,
0x8df2, 0x8fc2, 0x8fc2, 0x8cf2, 0x8cf2, 0x8fb2, 0x8fb2, 0x8bf2,
0x8bf2, 0x7af2, 0x7af2, 0x7af2, 0x7af2, 0x8fa2, 0x8fa2, 0x8f92,
0x8f92, 0x79f2, 0x79f2, 0x79f2, 0x79f2, 0x78f2, 0x78f2, 0x78f2,
0x78f2, 0x8f82, 0x8f82, 0x8f72, 0x8f72, 0x77f2, 0x77f2, 0x77f2,
0x77f2, 0x7f62, 0x7f62, 0x7f62, 0x7f62, 0x76f2, 0x76f2, 0x76f2,
0x76f2, 0x7f52, 0x7f52, 0x7f52, 0x7f52, 0x75f2, 0x75f2, 0x75f2,
0x75f2, 0x7f42, 0x7f42, 0x7f42, 0x7f42, 0x74f2, 0x74f2, 0x74f2,
0x74f2, 0x7f32, 0x7f32, 0x7f32, 0x7f32, 0x73f2, 0x73f2, 0x73f2,
0x73f2, 0x7f22, 0x7f22, 0x7f22, 0x7f22, 0x72f2, 0x72f2, 0x72f2,
0x72f2, 0x71f2, 0x71f2, 0x71f2, 0x71f2, 0x8f12, 0x8f12, 0x80f1,
0x80f1, 0x9f01, 0x0201, 0x0206, 0x020b, 0x0210, 0x0215, 0x021a,
0x021f, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2,
0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2,
0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2,
0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2,
0x4ff2, 0x0224, 0x0229, 0x0232, 0x0237, 0x023a, 0x023f, 0x0242,
0x0245, 0x024a, 0x024d, 0x0250, 0x0253, 0x0256, 0x0259, 0x025c,
0x025f, 0x0262, 0x0265, 0x0268, 0x026b, 0x026e, 0x0271, 0x0274,
0x0277, 0x027a, 0x027d, 0x0280, 0x0283, 0x0288, 0x028b, 0x028e,
0x0291, 0x0294, 0x0297, 0x029a, 0x029f, 0x94b2, 0x02a4, 0x02a7,
0x02aa, 0x93b2, 0x9882, 0x02af, 0x92b2, 0x02b2, 0x02b5, 0x9692,
0x94a2, 0x02b8, 0x9782, 0x9a32, 0x93a2, 0x9952, 0x9592, 0x9a22,
0x92a2, 0x91a2, 0x9862, 0x9682, 0x9772, 0x9942, 0x9492, 0x9932,
0x9392, 0x9852, 0x9582, 0x9922, 0x9762, 0x9672, 0x9292, 0x9912,
0x9192, 0x9842, 0x9482, 0x9752, 0x9572, 0x9832, 0x9382, 0x9662,
0x9822, 0x9282, 0x9812, 0x9742, 0x9472, 0x9182, 0x02bb, 0x9652,
0x9562, 0x9712, 0x02be, 0x8372, 0x8372, 0x9732, 0x9722, 0x8272,
0x8272, 0x8642, 0x8642, 0x8462, 0x8462, 0x8552, 0x8552, 0x8172,
0x8172, 0x8632, 0x8632, 0x8362, 0x8362, 0x8542, 0x8542, 0x8452,
0x8452, 0x8622, 0x8622, 0x8262, 0x8262, 0x8612, 0x8612, 0x8162,
0x8162, 0x9601, 0x9061, 0x8532, 0x8532, 0x8352, 0x8352, 0x8442,
0x8442, 0x8522, 0x8522, 0x8252, 0x8252, 0x8512, 0x8512, 0x9501,
0x9051, 0x7152, 0x7152, 0x7152, 0x7152, 0x8432, 0x8432, 0x8342,
0x8342, 0x7422, 0x7422, 0x7422, 0x7422, 0x7242, 0x7242, 0x7242,
0x7242, 0x7332, 0x7332, 0x7332, 0x7332, 0x7412, 0x7412, 0x7412,
0x7412, 0x7142, 0x7142, 0x7142, 0x7142, 0x8401, 0x8401, 0x8041,
0x8041, 0x7322, 0x7322, 0x7322, 0x7322, 0x7232, 0x7232, 0x7232,
0x7232, 0x6312, 0x6312, 0x6312, 0x6312, 0x6312, 0x6312, 0x6312,
0x6312, 0x6132, 0x6132, 0x6132, 0x6132, 0x6132, 0x6132, 0x6132,
0x6132, 0x7301, 0x7301, 0x7301, 0x7301, 0x7031, 0x7031, 0x7031,
0x7031, 0x6222, 0x6222, 0x6222, 0x6222, 0x6222, 0x6222, 0x6222,
0x6222, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212,
0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212,
0x5212, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122,
0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122,
0x5122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6201, 0x6201, 0x6201,
0x6201, 0x6021, 0x6021, 0x6021, 0x6021, 0x6021, 0x6021, 0x6021,
0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112,
0x4112, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101,
0x4101, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011,
0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011,
0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011,
0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011,
0x4011, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
0x4000, 0xf002, 0x2ee2, 0x2ed2, 0x2de2, 0x2ec2, 0xf002, 0x2ce2,
0x2dd2, 0x2eb2, 0x2be2, 0xf002, 0x2dc2, 0x2cd2, 0x2ea2, 0x2ae2,
0xf002, 0x2db2, 0x2bd2, 0x2cc2, 0x2e92, 0xf002, 0x29e2, 0x2da2,
0x2ad2, 0x2cb2, 0xf002, 0x2bc2, 0x2e82, 0x28e2, 0x2d92, 0xf002,
0x29d2, 0x2e72, 0x27e2, 0x2ca2, 0xf002, 0x2ac2, 0x2bb2, 0x2d82,
0x28d2, 0xf003, 0x3e01, 0x30e1, 0x2d01, 0x2d01, 0x16e2, 0x16e2,
0x16e2, 0x16e2, 0xf002, 0x2e62, 0x2c92, 0x19c2, 0x19c2, 0xf001,
0x1e52, 0x1ab2, 0xf002, 0x15e2, 0x15e2, 0x2ba2, 0x2d72, 0xf001,
0x17d2, 0x14e2, 0xf001, 0x1c82, 0x18c2, 0xf002, 0x2e42, 0x2e22,
0x1e32, 0x1e32, 0xf001, 0x1d62, 0x16d2, 0xf001, 0x13e2, 0x1b92,
0xf001, 0x19b2, 0x1aa2, 0xf001, 0x12e2, 0x1e12, 0xf001, 0x11e2,
0x1d52, 0xf001, 0x15d2, 0x1c72, 0xf001, 0x17c2, 0x1d42, 0xf001,
0x1b82, 0x18b2, 0xf001, 0x14d2, 0x1a92, 0xf001, 0x19a2, 0x1c62,
0xf001, 0x16c2, 0x1d32, 0xf001, 0x13d2, 0x1d22, 0xf001, 0x12d2,
0x1d12, 0xf001, 0x1b72, 0x17b2, 0xf001, 0x11d2, 0x1c52, 0xf001,
0x15c2, 0x1a82, 0xf001, 0x18a2, 0x1992, 0xf001, 0x1c42, 0x14c2,
0xf001, 0x1b62, 0x16b2, 0xf002, 0x20d1, 0x2c01, 0x1c32, 0x1c32,
0xf001, 0x13c2, 0x1a72, 0xf001, 0x17a2, 0x1c22, 0xf001, 0x12c2,
0x1b52, 0xf001, 0x15b2, 0x1c12, 0xf001, 0x1982, 0x1892, 0xf001,
0x11c2, 0x1b42, 0xf002, 0x20c1, 0x2b01, 0x1b32, 0x1b32, 0xf002,
0x20b1, 0x2a01, 0x1a12, 0x1a12, 0xf001, 0x1a62, 0x16a2, 0xf001,
0x1972, 0x1792, 0xf002, 0x20a1, 0x2901, 0x1091, 0x1091, 0xf001,
0x1b22, 0x1a52, 0xf001, 0x15a2, 0x1b12, 0xf001, 0x11b2, 0x1962,
0xf001, 0x1a42, 0x1872, 0xf001, 0x1801, 0x1081, 0xf001, 0x1701,
0x1071,
};
#define HUFF_OFFSET_01 0
#define HUFF_OFFSET_02 ( 9 + HUFF_OFFSET_01)
#define HUFF_OFFSET_03 ( 65 + HUFF_OFFSET_02)
#define HUFF_OFFSET_05 ( 65 + HUFF_OFFSET_03)
#define HUFF_OFFSET_06 (257 + HUFF_OFFSET_05)
#define HUFF_OFFSET_07 (129 + HUFF_OFFSET_06)
#define HUFF_OFFSET_08 (110 + HUFF_OFFSET_07)
#define HUFF_OFFSET_09 (280 + HUFF_OFFSET_08)
#define HUFF_OFFSET_10 ( 93 + HUFF_OFFSET_09)
#define HUFF_OFFSET_11 (320 + HUFF_OFFSET_10)
#define HUFF_OFFSET_12 (296 + HUFF_OFFSET_11)
#define HUFF_OFFSET_13 (185 + HUFF_OFFSET_12)
#define HUFF_OFFSET_15 (497 + HUFF_OFFSET_13)
#define HUFF_OFFSET_16 (580 + HUFF_OFFSET_15)
#define HUFF_OFFSET_24 (651 + HUFF_OFFSET_16)
const int huffTabOffset[HUFF_PAIRTABS] PROGMEM = {
0,
HUFF_OFFSET_01,
HUFF_OFFSET_02,
HUFF_OFFSET_03,
0,
HUFF_OFFSET_05,
HUFF_OFFSET_06,
HUFF_OFFSET_07,
HUFF_OFFSET_08,
HUFF_OFFSET_09,
HUFF_OFFSET_10,
HUFF_OFFSET_11,
HUFF_OFFSET_12,
HUFF_OFFSET_13,
0,
HUFF_OFFSET_15,
HUFF_OFFSET_16,
HUFF_OFFSET_16,
HUFF_OFFSET_16,
HUFF_OFFSET_16,
HUFF_OFFSET_16,
HUFF_OFFSET_16,
HUFF_OFFSET_16,
HUFF_OFFSET_16,
HUFF_OFFSET_24,
HUFF_OFFSET_24,
HUFF_OFFSET_24,
HUFF_OFFSET_24,
HUFF_OFFSET_24,
HUFF_OFFSET_24,
HUFF_OFFSET_24,
HUFF_OFFSET_24,
};
const HuffTabLookup huffTabLookup[HUFF_PAIRTABS] PROGMEM = {
{ 0, noBits },
{ 0, oneShot },
{ 0, oneShot },
{ 0, oneShot },
{ 0, invalidTab },
{ 0, oneShot },
{ 0, oneShot },
{ 0, loopNoLinbits },
{ 0, loopNoLinbits },
{ 0, loopNoLinbits },
{ 0, loopNoLinbits },
{ 0, loopNoLinbits },
{ 0, loopNoLinbits },
{ 0, loopNoLinbits },
{ 0, invalidTab },
{ 0, loopNoLinbits },
{ 1, loopLinbits },
{ 2, loopLinbits },
{ 3, loopLinbits },
{ 4, loopLinbits },
{ 6, loopLinbits },
{ 8, loopLinbits },
{ 10, loopLinbits },
{ 13, loopLinbits },
{ 4, loopLinbits },
{ 5, loopLinbits },
{ 6, loopLinbits },
{ 7, loopLinbits },
{ 8, loopLinbits },
{ 9, loopLinbits },
{ 11, loopLinbits },
{ 13, loopLinbits },
};
/* tables for quadruples
* format 0xAB
* A = length of codeword
* B = codeword
*/
const unsigned char quadTable[64+16] PROGMEM = {
/* table A */
0x6b, 0x6f, 0x6d, 0x6e, 0x67, 0x65, 0x59, 0x59,
0x56, 0x56, 0x53, 0x53, 0x5a, 0x5a, 0x5c, 0x5c,
0x42, 0x42, 0x42, 0x42, 0x41, 0x41, 0x41, 0x41,
0x44, 0x44, 0x44, 0x44, 0x48, 0x48, 0x48, 0x48,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
/* table B */
0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48,
0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
};
const int quadTabOffset[2] PROGMEM = {0, 64};
const int quadTabMaxBits[2] PROGMEM = {6, 4};

View File

@@ -1,787 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* imdct.c - antialias, inverse transform (short/long/mixed), windowing,
* overlap-add, frequency inversion
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#include <pgmspace.h>
/**************************************************************************************
* Function: AntiAlias
*
* Description: smooth transition across DCT block boundaries (every 18 coefficients)
*
* Inputs: vector of dequantized coefficients, length = (nBfly+1) * 18
* number of "butterflies" to perform (one butterfly means one
* inter-block smoothing operation)
*
* Outputs: updated coefficient vector x
*
* Return: none
*
* Notes: weighted average of opposite bands (pairwise) from the 8 samples
* before and after each block boundary
* nBlocks = (nonZeroBound + 7) / 18, since nZB is the first ZERO sample
* above which all other samples are also zero
* max gain per sample = 1.372
* MAX(i) (abs(csa[i][0]) + abs(csa[i][1]))
* bits gained = 0
* assume at least 1 guard bit in x[] to avoid overflow
* (should be guaranteed from dequant, and max gain from stproc * max
* gain from AntiAlias < 2.0)
**************************************************************************************/
// a little bit faster in RAM (< 1 ms per block)
/* __attribute__ ((section (".data"))) */ static void AntiAlias(int *x, int nBfly)
{
int k, a0, b0, c0, c1;
const int *c;
/* csa = Q31 */
for (k = nBfly; k > 0; k--) {
c = csa[0];
x += 18;
a0 = x[-1]; c0 = *c; c++; b0 = x[0]; c1 = *c; c++;
x[-1] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[0] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
a0 = x[-2]; c0 = *c; c++; b0 = x[1]; c1 = *c; c++;
x[-2] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[1] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
a0 = x[-3]; c0 = *c; c++; b0 = x[2]; c1 = *c; c++;
x[-3] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[2] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
a0 = x[-4]; c0 = *c; c++; b0 = x[3]; c1 = *c; c++;
x[-4] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[3] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
a0 = x[-5]; c0 = *c; c++; b0 = x[4]; c1 = *c; c++;
x[-5] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[4] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
a0 = x[-6]; c0 = *c; c++; b0 = x[5]; c1 = *c; c++;
x[-6] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[5] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
a0 = x[-7]; c0 = *c; c++; b0 = x[6]; c1 = *c; c++;
x[-7] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[6] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
a0 = x[-8]; c0 = *c; c++; b0 = x[7]; c1 = *c; c++;
x[-8] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1;
x[7] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1;
}
}
/**************************************************************************************
* Function: WinPrevious
*
* Description: apply specified window to second half of previous IMDCT (overlap part)
*
* Inputs: vector of 9 coefficients (xPrev)
*
* Outputs: 18 windowed output coefficients (gain 1 integer bit)
* window type (0, 1, 2, 3)
*
* Return: none
*
* Notes: produces 9 output samples from 18 input samples via symmetry
* all blocks gain at least 1 guard bit via window (long blocks get extra
* sign bit, short blocks can have one addition but max gain < 1.0)
**************************************************************************************/
/*__attribute__ ((section (".data"))) */ static void WinPrevious(int *xPrev, int *xPrevWin, int btPrev)
{
int i, x, *xp, *xpwLo, *xpwHi, wLo, wHi;
const int *wpLo, *wpHi;
xp = xPrev;
/* mapping (see IMDCT12x3): xPrev[0-2] = sum[6-8], xPrev[3-8] = sum[12-17] */
if (btPrev == 2) {
/* this could be reordered for minimum loads/stores */
wpLo = imdctWin[btPrev];
xPrevWin[ 0] = MULSHIFT32(wpLo[ 6], xPrev[2]) + MULSHIFT32(wpLo[0], xPrev[6]);
xPrevWin[ 1] = MULSHIFT32(wpLo[ 7], xPrev[1]) + MULSHIFT32(wpLo[1], xPrev[7]);
xPrevWin[ 2] = MULSHIFT32(wpLo[ 8], xPrev[0]) + MULSHIFT32(wpLo[2], xPrev[8]);
xPrevWin[ 3] = MULSHIFT32(wpLo[ 9], xPrev[0]) + MULSHIFT32(wpLo[3], xPrev[8]);
xPrevWin[ 4] = MULSHIFT32(wpLo[10], xPrev[1]) + MULSHIFT32(wpLo[4], xPrev[7]);
xPrevWin[ 5] = MULSHIFT32(wpLo[11], xPrev[2]) + MULSHIFT32(wpLo[5], xPrev[6]);
xPrevWin[ 6] = MULSHIFT32(wpLo[ 6], xPrev[5]);
xPrevWin[ 7] = MULSHIFT32(wpLo[ 7], xPrev[4]);
xPrevWin[ 8] = MULSHIFT32(wpLo[ 8], xPrev[3]);
xPrevWin[ 9] = MULSHIFT32(wpLo[ 9], xPrev[3]);
xPrevWin[10] = MULSHIFT32(wpLo[10], xPrev[4]);
xPrevWin[11] = MULSHIFT32(wpLo[11], xPrev[5]);
xPrevWin[12] = xPrevWin[13] = xPrevWin[14] = xPrevWin[15] = xPrevWin[16] = xPrevWin[17] = 0;
} else {
/* use ARM-style pointers (*ptr++) so that ADS compiles well */
wpLo = imdctWin[btPrev] + 18;
wpHi = wpLo + 17;
xpwLo = xPrevWin;
xpwHi = xPrevWin + 17;
for (i = 9; i > 0; i--) {
x = *xp++; wLo = *wpLo++; wHi = *wpHi--;
*xpwLo++ = MULSHIFT32(wLo, x);
*xpwHi-- = MULSHIFT32(wHi, x);
}
}
}
/**************************************************************************************
* Function: FreqInvertRescale
*
* Description: do frequency inversion (odd samples of odd blocks) and rescale
* if necessary (extra guard bits added before IMDCT)
*
* Inputs: output vector y (18 new samples, spaced NBANDS apart)
* previous sample vector xPrev (9 samples)
* index of current block
* number of extra shifts added before IMDCT (usually 0)
*
* Outputs: inverted and rescaled (as necessary) outputs
* rescaled (as necessary) previous samples
*
* Return: updated mOut (from new outputs y)
**************************************************************************************/
/*__attribute__ ((section (".data")))*/ static int FreqInvertRescale(int *y, int *xPrev, int blockIdx, int es)
{
int i, d, mOut;
int y0, y1, y2, y3, y4, y5, y6, y7, y8;
if (es == 0) {
/* fast case - frequency invert only (no rescaling) - can fuse into overlap-add for speed, if desired */
if (blockIdx & 0x01) {
y += NBANDS;
y0 = *y; y += 2*NBANDS;
y1 = *y; y += 2*NBANDS;
y2 = *y; y += 2*NBANDS;
y3 = *y; y += 2*NBANDS;
y4 = *y; y += 2*NBANDS;
y5 = *y; y += 2*NBANDS;
y6 = *y; y += 2*NBANDS;
y7 = *y; y += 2*NBANDS;
y8 = *y; y += 2*NBANDS;
y -= 18*NBANDS;
*y = -y0; y += 2*NBANDS;
*y = -y1; y += 2*NBANDS;
*y = -y2; y += 2*NBANDS;
*y = -y3; y += 2*NBANDS;
*y = -y4; y += 2*NBANDS;
*y = -y5; y += 2*NBANDS;
*y = -y6; y += 2*NBANDS;
*y = -y7; y += 2*NBANDS;
*y = -y8; y += 2*NBANDS;
}
return 0;
} else {
/* undo pre-IMDCT scaling, clipping if necessary */
mOut = 0;
if (blockIdx & 0x01) {
/* frequency invert */
for (i = 0; i < 18; i+=2) {
d = *y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS;
d = -*y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS;
d = *xPrev; CLIP_2N(d, 31 - es); *xPrev++ = d << es;
}
} else {
for (i = 0; i < 18; i+=2) {
d = *y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS;
d = *y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS;
d = *xPrev; CLIP_2N(d, 31 - es); *xPrev++ = d << es;
}
}
return mOut;
}
}
/* format = Q31
* #define M_PI 3.14159265358979323846
* double u = 2.0 * M_PI / 9.0;
* float c0 = sqrt(3.0) / 2.0;
* float c1 = cos(u);
* float c2 = cos(2*u);
* float c3 = sin(u);
* float c4 = sin(2*u);
*/
static const int c9_0 = 0x6ed9eba1;
static const int c9_1 = 0x620dbe8b;
static const int c9_2 = 0x163a1a7e;
static const int c9_3 = 0x5246dd49;
static const int c9_4 = 0x7e0e2e32;
/* format = Q31
* cos(((0:8) + 0.5) * (pi/18))
*/
static const int c18[9] PROGMEM = {
0x7f834ed0, 0x7ba3751d, 0x7401e4c1, 0x68d9f964, 0x5a82799a, 0x496af3e2, 0x36185aee, 0x2120fb83, 0x0b27eb5c,
};
/* require at least 3 guard bits in x[] to ensure no overflow */
static __inline void idct9(int *x)
{
int a1, a2, a3, a4, a5, a6, a7, a8, a9;
int a10, a11, a12, a13, a14, a15, a16, a17, a18;
int a19, a20, a21, a22, a23, a24, a25, a26, a27;
int m1, m3, m5, m6, m7, m8, m9, m10, m11, m12;
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
x0 = x[0]; x1 = x[1]; x2 = x[2]; x3 = x[3]; x4 = x[4];
x5 = x[5]; x6 = x[6]; x7 = x[7]; x8 = x[8];
a1 = x0 - x6;
a2 = x1 - x5;
a3 = x1 + x5;
a4 = x2 - x4;
a5 = x2 + x4;
a6 = x2 + x8;
a7 = x1 + x7;
a8 = a6 - a5; /* ie x[8] - x[4] */
a9 = a3 - a7; /* ie x[5] - x[7] */
a10 = a2 - x7; /* ie x[1] - x[5] - x[7] */
a11 = a4 - x8; /* ie x[2] - x[4] - x[8] */
/* do the << 1 as constant shifts where mX is actually used (free, no stall or extra inst.) */
m1 = MULSHIFT32(c9_0, x3);
m3 = MULSHIFT32(c9_0, a10);
m5 = MULSHIFT32(c9_1, a5);
m6 = MULSHIFT32(c9_2, a6);
m7 = MULSHIFT32(c9_1, a8);
m8 = MULSHIFT32(c9_2, a5);
m9 = MULSHIFT32(c9_3, a9);
m10 = MULSHIFT32(c9_4, a7);
m11 = MULSHIFT32(c9_3, a3);
m12 = MULSHIFT32(c9_4, a9);
a12 = x[0] + (x[6] >> 1);
a13 = a12 + ( m1 << 1);
a14 = a12 - ( m1 << 1);
a15 = a1 + ( a11 >> 1);
a16 = ( m5 << 1) + (m6 << 1);
a17 = ( m7 << 1) - (m8 << 1);
a18 = a16 + a17;
a19 = ( m9 << 1) + (m10 << 1);
a20 = (m11 << 1) - (m12 << 1);
a21 = a20 - a19;
a22 = a13 + a16;
a23 = a14 + a16;
a24 = a14 + a17;
a25 = a13 + a17;
a26 = a14 - a18;
a27 = a13 - a18;
x0 = a22 + a19; x[0] = x0;
x1 = a15 + (m3 << 1); x[1] = x1;
x2 = a24 + a20; x[2] = x2;
x3 = a26 - a21; x[3] = x3;
x4 = a1 - a11; x[4] = x4;
x5 = a27 + a21; x[5] = x5;
x6 = a25 - a20; x[6] = x6;
x7 = a15 - (m3 << 1); x[7] = x7;
x8 = a23 - a19; x[8] = x8;
}
/* let c(j) = cos(M_PI/36 * ((j)+0.5)), s(j) = sin(M_PI/36 * ((j)+0.5))
* then fastWin[2*j+0] = c(j)*(s(j) + c(j)), j = [0, 8]
* fastWin[2*j+1] = c(j)*(s(j) - c(j))
* format = Q30
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
const int fastWin36[18] PROGMEM = {
0x42aace8b, 0xc2e92724, 0x47311c28, 0xc95f619a, 0x4a868feb, 0xd0859d8c,
0x4c913b51, 0xd8243ea0, 0x4d413ccc, 0xe0000000, 0x4c913b51, 0xe7dbc161,
0x4a868feb, 0xef7a6275, 0x47311c28, 0xf6a09e67, 0x42aace8b, 0xfd16d8dd,
};
#pragma GCC diagnostic pop
/**************************************************************************************
* Function: IMDCT36
*
* Description: 36-point modified DCT, with windowing and overlap-add (50% overlap)
*
* Inputs: vector of 18 coefficients (N/2 inputs produces N outputs, by symmetry)
* overlap part of last IMDCT (9 samples - see output comments)
* window type (0,1,2,3) of current and previous block
* current block index (for deciding whether to do frequency inversion)
* number of guard bits in input vector
*
* Outputs: 18 output samples, after windowing and overlap-add with last frame
* second half of (unwindowed) 36-point IMDCT - save for next time
* only save 9 xPrev samples, using symmetry (see WinPrevious())
*
* Notes: this is Ken's hyper-fast algorithm, including symmetric sin window
* optimization, if applicable
* total number of multiplies, general case:
* 2*10 (idct9) + 9 (last stage imdct) + 36 (for windowing) = 65
* total number of multiplies, btCurr == 0 && btPrev == 0:
* 2*10 (idct9) + 9 (last stage imdct) + 18 (for windowing) = 47
*
* blockType == 0 is by far the most common case, so it should be
* possible to use the fast path most of the time
* this is the fastest known algorithm for performing
* long IMDCT + windowing + overlap-add in MP3
*
* Return: mOut (OR of abs(y) for all y calculated here)
*
* TODO: optimize for ARM (reorder window coefs, ARM-style pointers in C,
* inline asm may or may not be helpful)
**************************************************************************************/
// barely faster in RAM
/*__attribute__ ((section (".data")))*/ static int IMDCT36(int *xCurr, int *xPrev, int *y, int btCurr, int btPrev, int blockIdx, int gb)
{
int i, es, xBuf[18], xPrevWin[18];
int acc1, acc2, s, d, t, mOut;
int xo, xe, c, *xp, yLo, yHi;
const int *cp, *wp;
acc1 = acc2 = 0;
xCurr += 17;
/* 7 gb is always adequate for antialias + accumulator loop + idct9 */
if (gb < 7) {
/* rarely triggered - 5% to 10% of the time on normal clips (with Q25 input) */
es = 7 - gb;
for (i = 8; i >= 0; i--) {
acc1 = ((*xCurr--) >> es) - acc1;
acc2 = acc1 - acc2;
acc1 = ((*xCurr--) >> es) - acc1;
xBuf[i+9] = acc2; /* odd */
xBuf[i+0] = acc1; /* even */
xPrev[i] >>= es;
}
} else {
es = 0;
/* max gain = 18, assume adequate guard bits */
for (i = 8; i >= 0; i--) {
acc1 = (*xCurr--) - acc1;
acc2 = acc1 - acc2;
acc1 = (*xCurr--) - acc1;
xBuf[i+9] = acc2; /* odd */
xBuf[i+0] = acc1; /* even */
}
}
/* xEven[0] and xOdd[0] scaled by 0.5 */
xBuf[9] >>= 1;
xBuf[0] >>= 1;
/* do 9-point IDCT on even and odd */
idct9(xBuf+0); /* even */
idct9(xBuf+9); /* odd */
xp = xBuf + 8;
cp = c18 + 8;
mOut = 0;
if (btPrev == 0 && btCurr == 0) {
/* fast path - use symmetry of sin window to reduce windowing multiplies to 18 (N/2) */
wp = fastWin36;
for (i = 0; i < 9; i++) {
/* do ARM-style pointer arithmetic (i still needed for y[] indexing - compiler spills if 2 y pointers) */
c = *cp--; xo = *(xp + 9); xe = *xp--;
/* gain 2 int bits here */
xo = MULSHIFT32(c, xo); /* 2*c18*xOdd (mul by 2 implicit in scaling) */
xe >>= 2;
s = -(*xPrev); /* sum from last block (always at least 2 guard bits) */
d = -(xe - xo); /* gain 2 int bits, don't shift xo (effective << 1 to eat sign bit, << 1 for mul by 2) */
(*xPrev++) = xe + xo; /* symmetry - xPrev[i] = xPrev[17-i] for long blocks */
t = s - d;
yLo = (d + (MULSHIFT32(t, *wp++) << 2));
yHi = (s + (MULSHIFT32(t, *wp++) << 2));
y[(i)*NBANDS] = yLo;
y[(17-i)*NBANDS] = yHi;
mOut |= FASTABS(yLo);
mOut |= FASTABS(yHi);
}
} else {
/* slower method - either prev or curr is using window type != 0 so do full 36-point window
* output xPrevWin has at least 3 guard bits (xPrev has 2, gain 1 in WinPrevious)
*/
WinPrevious(xPrev, xPrevWin, btPrev);
wp = imdctWin[btCurr];
for (i = 0; i < 9; i++) {
c = *cp--; xo = *(xp + 9); xe = *xp--;
/* gain 2 int bits here */
xo = MULSHIFT32(c, xo); /* 2*c18*xOdd (mul by 2 implicit in scaling) */
xe >>= 2;
d = xe - xo;
(*xPrev++) = xe + xo; /* symmetry - xPrev[i] = xPrev[17-i] for long blocks */
yLo = (xPrevWin[i] + MULSHIFT32(d, wp[i])) << 2;
yHi = (xPrevWin[17-i] + MULSHIFT32(d, wp[17-i])) << 2;
y[(i)*NBANDS] = yLo;
y[(17-i)*NBANDS] = yHi;
mOut |= FASTABS(yLo);
mOut |= FASTABS(yHi);
}
}
xPrev -= 9;
mOut |= FreqInvertRescale(y, xPrev, blockIdx, es);
return mOut;
}
static int c3_0 = 0x6ed9eba1; /* format = Q31, cos(pi/6) */
static int c6[3] = { 0x7ba3751d, 0x5a82799a, 0x2120fb83 }; /* format = Q31, cos(((0:2) + 0.5) * (pi/6)) */
/* 12-point inverse DCT, used in IMDCT12x3()
* 4 input guard bits will ensure no overflow
*/
static __inline void imdct12 (int *x, int *out)
{
int a0, a1, a2;
int x0, x1, x2, x3, x4, x5;
x0 = *x; x+=3; x1 = *x; x+=3;
x2 = *x; x+=3; x3 = *x; x+=3;
x4 = *x; x+=3; x5 = *x; x+=3;
x4 -= x5;
x3 -= x4;
x2 -= x3;
x3 -= x5;
x1 -= x2;
x0 -= x1;
x1 -= x3;
x0 >>= 1;
x1 >>= 1;
a0 = MULSHIFT32(c3_0, x2) << 1;
a1 = x0 + (x4 >> 1);
a2 = x0 - x4;
x0 = a1 + a0;
x2 = a2;
x4 = a1 - a0;
a0 = MULSHIFT32(c3_0, x3) << 1;
a1 = x1 + (x5 >> 1);
a2 = x1 - x5;
/* cos window odd samples, mul by 2, eat sign bit */
x1 = MULSHIFT32(c6[0], a1 + a0) << 2;
x3 = MULSHIFT32(c6[1], a2) << 2;
x5 = MULSHIFT32(c6[2], a1 - a0) << 2;
*out = x0 + x1; out++;
*out = x2 + x3; out++;
*out = x4 + x5; out++;
*out = x4 - x5; out++;
*out = x2 - x3; out++;
*out = x0 - x1;
}
/**************************************************************************************
* Function: IMDCT12x3
*
* Description: three 12-point modified DCT's for short blocks, with windowing,
* short block concatenation, and overlap-add
*
* Inputs: 3 interleaved vectors of 6 samples each
* (block0[0], block1[0], block2[0], block0[1], block1[1]....)
* overlap part of last IMDCT (9 samples - see output comments)
* window type (0,1,2,3) of previous block
* current block index (for deciding whether to do frequency inversion)
* number of guard bits in input vector
*
* Outputs: updated sample vector x, net gain of 1 integer bit
* second half of (unwindowed) IMDCT's - save for next time
* only save 9 xPrev samples, using symmetry (see WinPrevious())
*
* Return: mOut (OR of abs(y) for all y calculated here)
*
* TODO: optimize for ARM
**************************************************************************************/
// barely faster in RAM
/*__attribute__ ((section (".data")))*/ static int IMDCT12x3(int *xCurr, int *xPrev, int *y, int btPrev, int blockIdx, int gb)
{
int i, es, mOut, yLo, xBuf[18], xPrevWin[18]; /* need temp buffer for reordering short blocks */
const int *wp;
es = 0;
/* 7 gb is always adequate for accumulator loop + idct12 + window + overlap */
if (gb < 7) {
es = 7 - gb;
for (i = 0; i < 18; i+=2) {
xCurr[i+0] >>= es;
xCurr[i+1] >>= es;
*xPrev++ >>= es;
}
xPrev -= 9;
}
/* requires 4 input guard bits for each imdct12 */
imdct12(xCurr + 0, xBuf + 0);
imdct12(xCurr + 1, xBuf + 6);
imdct12(xCurr + 2, xBuf + 12);
/* window previous from last time */
WinPrevious(xPrev, xPrevWin, btPrev);
/* could unroll this for speed, minimum loads (short blocks usually rare, so doesn't make much overall difference)
* xPrevWin[i] << 2 still has 1 gb always, max gain of windowed xBuf stuff also < 1.0 and gain the sign bit
* so y calculations won't overflow
*/
wp = imdctWin[2];
mOut = 0;
for (i = 0; i < 3; i++) {
yLo = (xPrevWin[ 0+i] << 2);
mOut |= FASTABS(yLo); y[( 0+i)*NBANDS] = yLo;
yLo = (xPrevWin[ 3+i] << 2);
mOut |= FASTABS(yLo); y[( 3+i)*NBANDS] = yLo;
yLo = (xPrevWin[ 6+i] << 2) + (MULSHIFT32(wp[0+i], xBuf[3+i]));
mOut |= FASTABS(yLo); y[( 6+i)*NBANDS] = yLo;
yLo = (xPrevWin[ 9+i] << 2) + (MULSHIFT32(wp[3+i], xBuf[5-i]));
mOut |= FASTABS(yLo); y[( 9+i)*NBANDS] = yLo;
yLo = (xPrevWin[12+i] << 2) + (MULSHIFT32(wp[6+i], xBuf[2-i]) + MULSHIFT32(wp[0+i], xBuf[(6+3)+i]));
mOut |= FASTABS(yLo); y[(12+i)*NBANDS] = yLo;
yLo = (xPrevWin[15+i] << 2) + (MULSHIFT32(wp[9+i], xBuf[0+i]) + MULSHIFT32(wp[3+i], xBuf[(6+5)-i]));
mOut |= FASTABS(yLo); y[(15+i)*NBANDS] = yLo;
}
/* save previous (unwindowed) for overlap - only need samples 6-8, 12-17 */
for (i = 6; i < 9; i++)
*xPrev++ = xBuf[i] >> 2;
for (i = 12; i < 18; i++)
*xPrev++ = xBuf[i] >> 2;
xPrev -= 9;
mOut |= FreqInvertRescale(y, xPrev, blockIdx, es);
return mOut;
}
/**************************************************************************************
* Function: HybridTransform
*
* Description: IMDCT's, windowing, and overlap-add on long/short/mixed blocks
*
* Inputs: vector of input coefficients, length = nBlocksTotal * 18)
* vector of overlap samples from last time, length = nBlocksPrev * 9)
* buffer for output samples, length = MAXNSAMP
* SideInfoSub struct for this granule/channel
* BlockCount struct with necessary info
* number of non-zero input and overlap blocks
* number of long blocks in input vector (rest assumed to be short blocks)
* number of blocks which use long window (type) 0 in case of mixed block
* (bc->currWinSwitch, 0 for non-mixed blocks)
*
* Outputs: transformed, windowed, and overlapped sample buffer
* does frequency inversion on odd blocks
* updated buffer of samples for overlap
*
* Return: number of non-zero IMDCT blocks calculated in this call
* (including overlap-add)
*
* TODO: examine mixedBlock/winSwitch logic carefully (test he_mode.bit)
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static int HybridTransform(int *xCurr, int *xPrev, int y[BLOCK_SIZE][NBANDS], SideInfoSub *sis, BlockCount *bc)
{
int xPrevWin[18], currWinIdx, prevWinIdx;
int i, j, nBlocksOut, nonZero, mOut;
int fiBit, xp;
ASSERT(bc->nBlocksLong <= NBANDS);
ASSERT(bc->nBlocksTotal <= NBANDS);
ASSERT(bc->nBlocksPrev <= NBANDS);
mOut = 0;
/* do long blocks, if any */
for(i = 0; i < bc->nBlocksLong; i++) {
/* currWinIdx picks the right window for long blocks (if mixed, long blocks use window type 0) */
currWinIdx = sis->blockType;
if (sis->mixedBlock && i < bc->currWinSwitch)
currWinIdx = 0;
prevWinIdx = bc->prevType;
if (i < bc->prevWinSwitch)
prevWinIdx = 0;
/* do 36-point IMDCT, including windowing and overlap-add */
mOut |= IMDCT36(xCurr, xPrev, &(y[0][i]), currWinIdx, prevWinIdx, i, bc->gbIn);
xCurr += 18;
xPrev += 9;
}
/* do short blocks (if any) */
for ( ; i < bc->nBlocksTotal; i++) {
ASSERT(sis->blockType == 2);
prevWinIdx = bc->prevType;
if (i < bc->prevWinSwitch)
prevWinIdx = 0;
mOut |= IMDCT12x3(xCurr, xPrev, &(y[0][i]), prevWinIdx, i, bc->gbIn);
xCurr += 18;
xPrev += 9;
}
nBlocksOut = i;
/* window and overlap prev if prev longer that current */
for ( ; i < bc->nBlocksPrev; i++) {
prevWinIdx = bc->prevType;
if (i < bc->prevWinSwitch)
prevWinIdx = 0;
WinPrevious(xPrev, xPrevWin, prevWinIdx);
nonZero = 0;
fiBit = i << 31;
for (j = 0; j < 9; j++) {
xp = xPrevWin[2*j+0] << 2; /* << 2 temp for scaling */
nonZero |= xp;
y[2*j+0][i] = xp;
mOut |= FASTABS(xp);
/* frequency inversion on odd blocks/odd samples (flip sign if i odd, j odd) */
xp = xPrevWin[2*j+1] << 2;
xp = (xp ^ (fiBit >> 31)) + (i & 0x01);
nonZero |= xp;
y[2*j+1][i] = xp;
mOut |= FASTABS(xp);
xPrev[j] = 0;
}
xPrev += 9;
if (nonZero)
nBlocksOut = i;
}
/* clear rest of blocks */
for ( ; i < 32; i++) {
for (j = 0; j < 18; j++)
y[j][i] = 0;
}
bc->gbOut = CLZ(mOut) - 1;
return nBlocksOut;
}
/**************************************************************************************
* Function: IMDCT
*
* Description: do alias reduction, inverse MDCT, overlap-add, and frequency inversion
*
* Inputs: MP3DecInfo structure filled by UnpackFrameHeader(), UnpackSideInfo(),
* UnpackScaleFactors(), and DecodeHuffman() (for this granule, channel)
* includes PCM samples in overBuf (from last call to IMDCT) for OLA
* index of current granule and channel
*
* Outputs: PCM samples in outBuf, for input to subband transform
* PCM samples in overBuf, for OLA next time
* updated hi->nonZeroBound index for this channel
*
* Return: 0 on success, -1 if null input pointers
**************************************************************************************/
// a bit faster in RAM
/*__attribute__ ((section (".data")))*/ int IMDCT(MP3DecInfo *mp3DecInfo, int gr, int ch)
{
int nBfly, blockCutoff;
FrameHeader *fh;
SideInfo *si;
HuffmanInfo *hi;
IMDCTInfo *mi;
BlockCount bc;
/* validate pointers */
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS ||
!mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->IMDCTInfoPS)
return -1;
/* si is an array of up to 4 structs, stored as gr0ch0, gr0ch1, gr1ch0, gr1ch1 */
fh = (FrameHeader *)(mp3DecInfo->FrameHeaderPS);
si = (SideInfo *)(mp3DecInfo->SideInfoPS);
hi = (HuffmanInfo*)(mp3DecInfo->HuffmanInfoPS);
mi = (IMDCTInfo *)(mp3DecInfo->IMDCTInfoPS);
/* anti-aliasing done on whole long blocks only
* for mixed blocks, nBfly always 1, except 3 for 8 kHz MPEG 2.5 (see sfBandTab)
* nLongBlocks = number of blocks with (possibly) non-zero power
* nBfly = number of butterflies to do (nLongBlocks - 1, unless no long blocks)
*/
blockCutoff = fh->sfBand->l[(fh->ver == MPEG1 ? 8 : 6)] / 18; /* same as 3* num short sfb's in spec */
if (si->sis[gr][ch].blockType != 2) {
/* all long transforms */
bc.nBlocksLong = MIN((hi->nonZeroBound[ch] + 7) / 18 + 1, 32);
nBfly = bc.nBlocksLong - 1;
} else if (si->sis[gr][ch].blockType == 2 && si->sis[gr][ch].mixedBlock) {
/* mixed block - long transforms until cutoff, then short transforms */
bc.nBlocksLong = blockCutoff;
nBfly = bc.nBlocksLong - 1;
} else {
/* all short transforms */
bc.nBlocksLong = 0;
nBfly = 0;
}
AntiAlias(hi->huffDecBuf[ch], nBfly);
hi->nonZeroBound[ch] = MAX(hi->nonZeroBound[ch], (nBfly * 18) + 8);
ASSERT(hi->nonZeroBound[ch] <= MAX_NSAMP);
/* for readability, use a struct instead of passing a million parameters to HybridTransform() */
bc.nBlocksTotal = (hi->nonZeroBound[ch] + 17) / 18;
bc.nBlocksPrev = mi->numPrevIMDCT[ch];
bc.prevType = mi->prevType[ch];
bc.prevWinSwitch = mi->prevWinSwitch[ch];
bc.currWinSwitch = (si->sis[gr][ch].mixedBlock ? blockCutoff : 0); /* where WINDOW switches (not nec. transform) */
bc.gbIn = hi->gb[ch];
mi->numPrevIMDCT[ch] = HybridTransform(hi->huffDecBuf[ch], mi->overBuf[ch], mi->outBuf[ch], &si->sis[gr][ch], &bc);
mi->prevType[ch] = si->sis[gr][ch].blockType;
mi->prevWinSwitch[ch] = bc.currWinSwitch; /* 0 means not a mixed block (either all short or all long) */
mi->gb[ch] = bc.gbOut;
ASSERT(mi->numPrevIMDCT[ch] <= NBANDS);
/* output has gained 2 int bits */
return 0;
}

View File

@@ -1,124 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* mp3common.h - implementation-independent API's, datatypes, and definitions
**************************************************************************************/
#ifndef _MP3COMMON_H
#define _MP3COMMON_H
#include "mp3dec.h"
#include "statname.h" /* do name-mangling for static linking */
#define MAX_SCFBD 4 /* max scalefactor bands per channel */
#define NGRANS_MPEG1 2
#define NGRANS_MPEG2 1
/* 11-bit syncword if MPEG 2.5 extensions are enabled */
/*
#define SYNCWORDH 0xff
#define SYNCWORDL 0xe0
*/
/* 12-bit syncword if MPEG 1,2 only are supported */
#define SYNCWORDH 0xff
#define SYNCWORDL 0xf0
typedef struct _MP3DecInfo {
/* pointers to platform-specific data structures */
void *FrameHeaderPS;
void *SideInfoPS;
void *ScaleFactorInfoPS;
void *HuffmanInfoPS;
void *DequantInfoPS;
void *IMDCTInfoPS;
void *SubbandInfoPS;
/* buffer which must be large enough to hold largest possible main_data section */
unsigned char mainBuf[MAINBUF_SIZE];
/* special info for "free" bitrate files */
int freeBitrateFlag;
int freeBitrateSlots;
/* user-accessible info */
int bitrate;
int nChans;
int samprate;
int nGrans; /* granules per frame */
int nGranSamps; /* samples per granule */
int nSlots;
int layer;
MPEGVersion version;
int mainDataBegin;
int mainDataBytes;
int part23Length[MAX_NGRAN][MAX_NCHAN];
} MP3DecInfo;
typedef struct _SFBandTable {
int/*short*/ l[23];
int/*short*/ s[14];
} SFBandTable;
/* decoder functions which must be implemented for each platform */
MP3DecInfo *AllocateBuffers(void);
void FreeBuffers(MP3DecInfo *mp3DecInfo);
int CheckPadBit(MP3DecInfo *mp3DecInfo);
int UnpackFrameHeader(MP3DecInfo *mp3DecInfo, unsigned char *buf);
int UnpackSideInfo(MP3DecInfo *mp3DecInfo, unsigned char *buf);
int DecodeHuffman(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch);
int Dequantize(MP3DecInfo *mp3DecInfo, int gr);
int IMDCT(MP3DecInfo *mp3DecInfo, int gr, int ch);
int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch);
int Subband(MP3DecInfo *mp3DecInfo, short *pcmBuf);
/* mp3tabs.c - global ROM tables */
extern const int samplerateTab[3][3];
extern const int/*short*/ bitrateTab[3][3][15];
extern const int/*short*/ samplesPerFrameTab[3][3];
extern const short bitsPerSlotTab[3];
extern const int/*short*/ sideBytesTab[3][2];
extern const int/*short*/ slotTab[3][3][15];
extern const SFBandTable sfBandTable[3][3];
#endif /* _MP3COMMON_H */

View File

@@ -1,484 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* mp3dec.c - platform-independent top level MP3 decoder API
**************************************************************************************/
#include "string.h"
//#include "hlxclib/string.h" /* for memmove, memcpy (can replace with different implementations if desired) */
#include "mp3common.h" /* includes mp3dec.h (public API) and internal, platform-independent API */
//#define PROFILE
#ifdef PROFILE
#include "systime.h"
#endif
/**************************************************************************************
* Function: MP3InitDecoder
*
* Description: allocate memory for platform-specific data
* clear all the user-accessible fields
*
* Inputs: none
*
* Outputs: none
*
* Return: handle to mp3 decoder instance, 0 if malloc fails
**************************************************************************************/
HMP3Decoder MP3InitDecoder(void)
{
MP3DecInfo *mp3DecInfo;
mp3DecInfo = AllocateBuffers();
return (HMP3Decoder)mp3DecInfo;
}
/**************************************************************************************
* Function: MP3FreeDecoder
*
* Description: free platform-specific data allocated by InitMP3Decoder
* zero out the contents of MP3DecInfo struct
*
* Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
*
* Outputs: none
*
* Return: none
**************************************************************************************/
void MP3FreeDecoder(HMP3Decoder hMP3Decoder)
{
MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
if (!mp3DecInfo)
return;
FreeBuffers(mp3DecInfo);
}
/**************************************************************************************
* Function: MP3FindSyncWord
*
* Description: locate the next byte-alinged sync word in the raw mp3 stream
*
* Inputs: buffer to search for sync word
* max number of bytes to search in buffer
*
* Outputs: none
*
* Return: offset to first sync word (bytes from start of buf)
* -1 if sync not found after searching nBytes
**************************************************************************************/
int MP3FindSyncWord(unsigned char *buf, int nBytes)
{
int i;
/* find byte-aligned syncword - need 12 (MPEG 1,2) or 11 (MPEG 2.5) matching bits */
for (i = 0; i < nBytes - 1; i++) {
if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL )
return i;
}
return -1;
}
/**************************************************************************************
* Function: MP3FindFreeSync
*
* Description: figure out number of bytes between adjacent sync words in "free" mode
*
* Inputs: buffer to search for next sync word
* the 4-byte frame header starting at the current sync word
* max number of bytes to search in buffer
*
* Outputs: none
*
* Return: offset to next sync word, minus any pad byte (i.e. nSlots)
* -1 if sync not found after searching nBytes
*
* Notes: this checks that the first 22 bits of the next frame header are the
* same as the current frame header, but it's still not foolproof
* (could accidentally find a sequence in the bitstream which
* appears to match but is not actually the next frame header)
* this could be made more error-resilient by checking several frames
* in a row and verifying that nSlots is the same in each case
* since free mode requires CBR (see spec) we generally only call
* this function once (first frame) then store the result (nSlots)
* and just use it from then on
**************************************************************************************/
static int MP3FindFreeSync(unsigned char *buf, unsigned char firstFH[4], int nBytes)
{
int offset = 0;
unsigned char *bufPtr = buf;
/* loop until we either:
* - run out of nBytes (FindMP3SyncWord() returns -1)
* - find the next valid frame header (sync word, version, layer, CRC flag, bitrate, and sample rate
* in next header must match current header)
*/
while (1) {
offset = MP3FindSyncWord(bufPtr, nBytes);
bufPtr += offset;
if (offset < 0) {
return -1;
} else if ( (bufPtr[0] == firstFH[0]) && (bufPtr[1] == firstFH[1]) && ((bufPtr[2] & 0xfc) == (firstFH[2] & 0xfc)) ) {
/* want to return number of bytes per frame, NOT counting the padding byte, so subtract one if padFlag == 1 */
if ((firstFH[2] >> 1) & 0x01)
bufPtr--;
return bufPtr - buf;
}
bufPtr += 3;
nBytes -= (offset + 3);
};
return -1;
}
/**************************************************************************************
* Function: MP3GetLastFrameInfo
*
* Description: get info about last MP3 frame decoded (number of sampled decoded,
* sample rate, bitrate, etc.)
*
* Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
* pointer to MP3FrameInfo struct
*
* Outputs: filled-in MP3FrameInfo struct
*
* Return: none
*
* Notes: call this right after calling MP3Decode
**************************************************************************************/
void MP3GetLastFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo)
{
MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
if (!mp3DecInfo || mp3DecInfo->layer != 3) {
mp3FrameInfo->bitrate = 0;
mp3FrameInfo->nChans = 0;
mp3FrameInfo->samprate = 0;
mp3FrameInfo->bitsPerSample = 0;
mp3FrameInfo->outputSamps = 0;
mp3FrameInfo->layer = 0;
mp3FrameInfo->version = 0;
} else {
mp3FrameInfo->bitrate = mp3DecInfo->bitrate;
mp3FrameInfo->nChans = mp3DecInfo->nChans;
mp3FrameInfo->samprate = mp3DecInfo->samprate;
mp3FrameInfo->bitsPerSample = 16;
mp3FrameInfo->outputSamps = mp3DecInfo->nChans * (int)samplesPerFrameTab[mp3DecInfo->version][mp3DecInfo->layer - 1];
mp3FrameInfo->layer = mp3DecInfo->layer;
mp3FrameInfo->version = mp3DecInfo->version;
}
}
/**************************************************************************************
* Function: MP3GetNextFrameInfo
*
* Description: parse MP3 frame header
*
* Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
* pointer to MP3FrameInfo struct
* pointer to buffer containing valid MP3 frame header (located using
* MP3FindSyncWord(), above)
*
* Outputs: filled-in MP3FrameInfo struct
*
* Return: error code, defined in mp3dec.h (0 means no error, < 0 means error)
**************************************************************************************/
int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf)
{
MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
if (!mp3DecInfo)
return ERR_MP3_NULL_POINTER;
if (UnpackFrameHeader(mp3DecInfo, buf) == -1 || mp3DecInfo->layer != 3)
return ERR_MP3_INVALID_FRAMEHEADER;
MP3GetLastFrameInfo(mp3DecInfo, mp3FrameInfo);
return ERR_MP3_NONE;
}
/**************************************************************************************
* Function: MP3ClearBadFrame
*
* Description: zero out pcm buffer if error decoding MP3 frame
*
* Inputs: mp3DecInfo struct with correct frame size parameters filled in
* pointer pcm output buffer
*
* Outputs: zeroed out pcm buffer
*
* Return: none
**************************************************************************************/
static void MP3ClearBadFrame(MP3DecInfo *mp3DecInfo, short *outbuf)
{
int i;
if (!mp3DecInfo)
return;
for (i = 0; i < mp3DecInfo->nGrans * mp3DecInfo->nGranSamps * mp3DecInfo->nChans; i++)
outbuf[i] = 0;
}
/**************************************************************************************
* Function: MP3Decode
*
* Description: decode one frame of MP3 data
*
* Inputs: valid MP3 decoder instance pointer (HMP3Decoder)
* double pointer to buffer of MP3 data (containing headers + mainData)
* number of valid bytes remaining in inbuf
* pointer to outbuf, big enough to hold one frame of decoded PCM samples
* flag indicating whether MP3 data is normal MPEG format (useSize = 0)
* or reformatted as "self-contained" frames (useSize = 1)
*
* Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo
* number of output samples = nGrans * nGranSamps * nChans
* updated inbuf pointer, updated bytesLeft
*
* Return: error code, defined in mp3dec.h (0 means no error, < 0 means error)
*
* Notes: switching useSize on and off between frames in the same stream
* is not supported (bit reservoir is not maintained if useSize on)
**************************************************************************************/
int MP3Decode(HMP3Decoder hMP3Decoder, unsigned char **inbuf, int *bytesLeft, short *outbuf, int useSize)
{
int offset, bitOffset, mainBits, gr, ch, fhBytes, siBytes, freeFrameBytes;
int prevBitOffset, sfBlockBits, huffBlockBits;
unsigned char *mainPtr;
MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
#ifdef PROFILE
long time;
#endif
if (!mp3DecInfo)
return ERR_MP3_NULL_POINTER;
/* unpack frame header */
fhBytes = UnpackFrameHeader(mp3DecInfo, *inbuf);
if (fhBytes < 0)
return ERR_MP3_INVALID_FRAMEHEADER; /* don't clear outbuf since we don't know size (failed to parse header) */
*inbuf += fhBytes;
#ifdef PROFILE
time = systime_get();
#endif
/* unpack side info */
siBytes = UnpackSideInfo(mp3DecInfo, *inbuf);
if (siBytes < 0) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_SIDEINFO;
}
*inbuf += siBytes;
*bytesLeft -= (fhBytes + siBytes);
#ifdef PROFILE
time = systime_get() - time;
printf("UnpackSideInfo: %i ms\n", time);
#endif
/* if free mode, need to calculate bitrate and nSlots manually, based on frame size */
if (mp3DecInfo->bitrate == 0 || mp3DecInfo->freeBitrateFlag) {
if (!mp3DecInfo->freeBitrateFlag) {
/* first time through, need to scan for next sync word and figure out frame size */
mp3DecInfo->freeBitrateFlag = 1;
mp3DecInfo->freeBitrateSlots = MP3FindFreeSync(*inbuf, *inbuf - fhBytes - siBytes, *bytesLeft);
if (mp3DecInfo->freeBitrateSlots < 0) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_FREE_BITRATE_SYNC;
}
freeFrameBytes = mp3DecInfo->freeBitrateSlots + fhBytes + siBytes;
mp3DecInfo->bitrate = (freeFrameBytes * mp3DecInfo->samprate * 8) / (mp3DecInfo->nGrans * mp3DecInfo->nGranSamps);
}
mp3DecInfo->nSlots = mp3DecInfo->freeBitrateSlots + CheckPadBit(mp3DecInfo); /* add pad byte, if required */
}
/* useSize != 0 means we're getting reformatted (RTP) packets (see RFC 3119)
* - calling function assembles "self-contained" MP3 frames by shifting any main_data
* from the bit reservoir (in previous frames) to AFTER the sync word and side info
* - calling function should set mainDataBegin to 0, and tell us exactly how large this
* frame is (in bytesLeft)
*/
if (useSize) {
mp3DecInfo->nSlots = *bytesLeft;
if (mp3DecInfo->mainDataBegin != 0 || mp3DecInfo->nSlots <= 0) {
/* error - non self-contained frame, or missing frame (size <= 0), could do loss concealment here */
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_FRAMEHEADER;
}
/* can operate in-place on reformatted frames */
mp3DecInfo->mainDataBytes = mp3DecInfo->nSlots;
mainPtr = *inbuf;
*inbuf += mp3DecInfo->nSlots;
*bytesLeft -= (mp3DecInfo->nSlots);
} else {
/* out of data - assume last or truncated frame */
if (mp3DecInfo->nSlots > *bytesLeft) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INDATA_UNDERFLOW;
}
#ifdef PROFILE
time = systime_get();
#endif
/* fill main data buffer with enough new data for this frame */
if (mp3DecInfo->mainDataBytes >= mp3DecInfo->mainDataBegin) {
/* adequate "old" main data available (i.e. bit reservoir) */
memmove(mp3DecInfo->mainBuf, mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes - mp3DecInfo->mainDataBegin, mp3DecInfo->mainDataBegin);
memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBegin, *inbuf, mp3DecInfo->nSlots);
mp3DecInfo->mainDataBytes = mp3DecInfo->mainDataBegin + mp3DecInfo->nSlots;
*inbuf += mp3DecInfo->nSlots;
*bytesLeft -= (mp3DecInfo->nSlots);
mainPtr = mp3DecInfo->mainBuf;
} else {
/* not enough data in bit reservoir from previous frames (perhaps starting in middle of file) */
memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes, *inbuf, mp3DecInfo->nSlots);
mp3DecInfo->mainDataBytes += mp3DecInfo->nSlots;
*inbuf += mp3DecInfo->nSlots;
*bytesLeft -= (mp3DecInfo->nSlots);
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_MAINDATA_UNDERFLOW;
}
#ifdef PROFILE
time = systime_get() - time;
printf("data buffer filling: %i ms\n", time);
#endif
}
bitOffset = 0;
mainBits = mp3DecInfo->mainDataBytes * 8;
/* decode one complete frame */
for (gr = 0; gr < mp3DecInfo->nGrans; gr++) {
for (ch = 0; ch < mp3DecInfo->nChans; ch++) {
#ifdef PROFILE
time = systime_get();
#endif
/* unpack scale factors and compute size of scale factor block */
prevBitOffset = bitOffset;
offset = UnpackScaleFactors(mp3DecInfo, mainPtr, &bitOffset, mainBits, gr, ch);
#ifdef PROFILE
time = systime_get() - time;
printf("UnpackScaleFactors: %i ms\n", time);
#endif
sfBlockBits = 8*offset - prevBitOffset + bitOffset;
huffBlockBits = mp3DecInfo->part23Length[gr][ch] - sfBlockBits;
mainPtr += offset;
mainBits -= sfBlockBits;
if (offset < 0 || mainBits < huffBlockBits) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_SCALEFACT;
}
#ifdef PROFILE
time = systime_get();
#endif
/* decode Huffman code words */
prevBitOffset = bitOffset;
offset = DecodeHuffman(mp3DecInfo, mainPtr, &bitOffset, huffBlockBits, gr, ch);
if (offset < 0) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_HUFFCODES;
}
#ifdef PROFILE
time = systime_get() - time;
printf("Huffman: %i ms\n", time);
#endif
mainPtr += offset;
mainBits -= (8*offset - prevBitOffset + bitOffset);
}
#ifdef PROFILE
time = systime_get();
#endif
/* dequantize coefficients, decode stereo, reorder short blocks */
if (Dequantize(mp3DecInfo, gr) < 0) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_DEQUANTIZE;
}
#ifdef PROFILE
time = systime_get() - time;
printf("Dequantize: %i ms\n", time);
#endif
/* alias reduction, inverse MDCT, overlap-add, frequency inversion */
for (ch = 0; ch < mp3DecInfo->nChans; ch++)
{
#ifdef PROFILE
time = systime_get();
#endif
if (IMDCT(mp3DecInfo, gr, ch) < 0) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_IMDCT;
}
#ifdef PROFILE
time = systime_get() - time;
printf("IMDCT: %i ms\n", time);
#endif
}
#ifdef PROFILE
time = systime_get();
#endif
/* subband transform - if stereo, interleaves pcm LRLRLR */
if (Subband(mp3DecInfo, outbuf + gr*mp3DecInfo->nGranSamps*mp3DecInfo->nChans) < 0) {
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_SUBBAND;
}
#ifdef PROFILE
time = systime_get() - time;
printf("Subband: %i ms\n", time);
#endif
}
return ERR_MP3_NONE;
}

View File

@@ -1,148 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* mp3dec.h - public C API for MP3 decoder
**************************************************************************************/
#include <stdint.h>
#define Word64 uint64_t
#ifdef ESP8266
# include "pgmspace.h"
#elif defined(ESP_PLATFORM) && __has_include(<pgm_space.h>)
# include <pgm_space.h>
#else
# define PROGMEM
# define pgm_read_byte(addr) (*(const unsigned char *)(addr))
# define pgm_read_word(addr) (*(const unsigned short *)(addr))
#endif
#ifndef _MP3DEC_H
#define _MP3DEC_H
#if defined(_WIN32) && !defined(_WIN32_WCE)
#
#elif defined(_WIN32) && defined(WINCE_EMULATOR)
#
#elif defined(ARM_ADS)
#
#elif defined(__APPLE__)
#
#elif defined(_SYMBIAN) && defined(__WINS__) /* Symbian emulator for Ix86 */
#
#elif defined(__GNUC__) && defined(__thumb__)
#
#elif defined(__GNUC__) && defined(__i386__)
#
#elif defined(__amd64__)
#
#elif defined(_OPENWAVE_SIMULATOR) || defined(_OPENWAVE_ARMULATOR)
#
#elif defined (ESP_PLATFORM)
#
#else
#error No platform defined. See valid options in mp3dec.h
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* determining MAINBUF_SIZE:
* max mainDataBegin = (2^9 - 1) bytes (since 9-bit offset) = 511
* max nSlots (concatenated with mainDataBegin bytes from before) = 1440 - 9 - 4 + 1 = 1428
* 511 + 1428 = 1939, round up to 1940 (4-byte align)
*/
#define MAINBUF_SIZE 1940
#define MAX_NGRAN 2 /* max granules */
#define MAX_NCHAN 2 /* max channels */
#define MAX_NSAMP 576 /* max samples per channel, per granule */
/* map to 0,1,2 to make table indexing easier */
typedef enum {
MPEG1 = 0,
MPEG2 = 1,
MPEG25 = 2
} MPEGVersion;
typedef void *HMP3Decoder;
enum {
ERR_MP3_NONE = 0,
ERR_MP3_INDATA_UNDERFLOW = -1,
ERR_MP3_MAINDATA_UNDERFLOW = -2,
ERR_MP3_FREE_BITRATE_SYNC = -3,
ERR_MP3_OUT_OF_MEMORY = -4,
ERR_MP3_NULL_POINTER = -5,
ERR_MP3_INVALID_FRAMEHEADER = -6,
ERR_MP3_INVALID_SIDEINFO = -7,
ERR_MP3_INVALID_SCALEFACT = -8,
ERR_MP3_INVALID_HUFFCODES = -9,
ERR_MP3_INVALID_DEQUANTIZE = -10,
ERR_MP3_INVALID_IMDCT = -11,
ERR_MP3_INVALID_SUBBAND = -12,
ERR_UNKNOWN = -9999
};
typedef struct _MP3FrameInfo {
int bitrate;
int nChans;
int samprate;
int bitsPerSample;
int outputSamps;
int layer;
int version;
} MP3FrameInfo;
/* public API */
HMP3Decoder MP3InitDecoder(void);
void MP3FreeDecoder(HMP3Decoder hMP3Decoder);
int MP3Decode(HMP3Decoder hMP3Decoder, unsigned char **inbuf, int *bytesLeft, short *outbuf, int useSize);
void MP3GetLastFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo);
int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf);
int MP3FindSyncWord(unsigned char *buf, int nBytes);
#ifdef __cplusplus
}
#endif
#endif /* _MP3DEC_H */

View File

@@ -1,182 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* mp3tabs.c - platform-independent tables for MP3 decoder (global, read-only)
**************************************************************************************/
#include "mp3common.h"
#include <pgmspace.h>
/* indexing = [version][samplerate index]
* sample rate of frame (Hz)
*/
const int samplerateTab[3][3] PROGMEM = {
{44100, 48000, 32000}, /* MPEG-1 */
{22050, 24000, 16000}, /* MPEG-2 */
{11025, 12000, 8000}, /* MPEG-2.5 */
};
/* indexing = [version][layer][bitrate index]
* bitrate (kbps) of frame
* - bitrate index == 0 is "free" mode (bitrate determined on the fly by
* counting bits between successive sync words)
*/
const int/*short*/ bitrateTab[3][3][15] PROGMEM = {
{
/* MPEG-1 */
{ 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448}, /* Layer 1 */
{ 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384}, /* Layer 2 */
{ 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}, /* Layer 3 */
},
{
/* MPEG-2 */
{ 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256}, /* Layer 1 */
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 2 */
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 3 */
},
{
/* MPEG-2.5 */
{ 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256}, /* Layer 1 */
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 2 */
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 3 */
},
};
/* indexing = [version][layer]
* number of samples in one frame (per channel)
*/
const int/*short*/ samplesPerFrameTab[3][3] PROGMEM = {
{384, 1152, 1152 }, /* MPEG1 */
{384, 1152, 576 }, /* MPEG2 */
{384, 1152, 576 }, /* MPEG2.5 */
};
/* layers 1, 2, 3 */
const short bitsPerSlotTab[3] = {32, 8, 8};
/* indexing = [version][mono/stereo]
* number of bytes in side info section of bitstream
*/
const int/*short*/ sideBytesTab[3][2] PROGMEM = {
{17, 32}, /* MPEG-1: mono, stereo */
{ 9, 17}, /* MPEG-2: mono, stereo */
{ 9, 17}, /* MPEG-2.5: mono, stereo */
};
/* indexing = [version][sampleRate][bitRate]
* for layer3, nSlots = floor(samps/frame * bitRate / sampleRate / 8)
* - add one pad slot if necessary
*/
const int/*short*/ slotTab[3][3][15] PROGMEM = {
{
/* MPEG-1 */
{ 0, 104, 130, 156, 182, 208, 261, 313, 365, 417, 522, 626, 731, 835,1044 }, /* 44 kHz */
{ 0, 96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960 }, /* 48 kHz */
{ 0, 144, 180, 216, 252, 288, 360, 432, 504, 576, 720, 864,1008,1152,1440 }, /* 32 kHz */
},
{
/* MPEG-2 */
{ 0, 26, 52, 78, 104, 130, 156, 182, 208, 261, 313, 365, 417, 470, 522 }, /* 22 kHz */
{ 0, 24, 48, 72, 96, 120, 144, 168, 192, 240, 288, 336, 384, 432, 480 }, /* 24 kHz */
{ 0, 36, 72, 108, 144, 180, 216, 252, 288, 360, 432, 504, 576, 648, 720 }, /* 16 kHz */
},
{
/* MPEG-2.5 */
{ 0, 52, 104, 156, 208, 261, 313, 365, 417, 522, 626, 731, 835, 940,1044 }, /* 11 kHz */
{ 0, 48, 96, 144, 192, 240, 288, 336, 384, 480, 576, 672, 768, 864, 960 }, /* 12 kHz */
{ 0, 72, 144, 216, 288, 360, 432, 504, 576, 720, 864,1008,1152,1296,1440 }, /* 8 kHz */
},
};
/* indexing = [version][sampleRate][long (.l) or short (.s) block]
* sfBandTable[v][s].l[cb] = index of first bin in critical band cb (long blocks)
* sfBandTable[v][s].s[cb] = index of first bin in critical band cb (short blocks)
*/
const SFBandTable sfBandTable[3][3] PROGMEM = {
{
/* MPEG-1 (44, 48, 32 kHz) */
{
{ 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90,110,134,162,196,238,288,342,418,576 },
{ 0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84,106,136,192 }
},
{
{ 0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88,106,128,156,190,230,276,330,384,576 },
{ 0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80,100,126,192 }
},
{
{ 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82,102,126,156,194,240,296,364,448,550,576 },
{ 0, 4, 8, 12, 16, 22, 30, 42, 58, 78,104,138,180,192 }
}
},
{
/* MPEG-2 (22, 24, 16 kHz) */
{
{ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 },
{ 0, 4, 8, 12, 18, 24, 32, 42, 56, 74,100,132,174,192 }
},
{
{ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,114,136,162,194,232,278,332,394,464,540,576 },
{ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,136,180,192 }
},
{
{ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 },
{ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 }
},
},
{
/* MPEG-2.5 (11, 12, 8 kHz) */
{
{ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 },
{ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 }
},
{
{ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 },
{ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 }
},
{
{ 0, 12, 24, 36, 48, 60, 72, 88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576 },
{ 0, 8, 16, 24, 36, 52, 72, 96,124,160,162,164,166,192 }
},
},
};

View File

@@ -1,108 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 ***** */
#ifndef _MPADECOBJFIXPT_H_
#define _MPADECOBJFIXPT_H_
#include "mp3dec.h" /* public C API for new MP3 decoder */
class CMpaDecObj
{
public:
CMpaDecObj();
~CMpaDecObj();
///////////////////////////////////////////////////////////////////////////
// Function: Init_n
// Purpose: Initialize the mp3 decoder.
// Parameters: pSync a pointer to a syncword
// ulSize the size of the buffer pSync points to
// bUseSize this tells the decoder to use the input frame
// size on the decode instead of calculating
// the frame size. This is necessary when
// our formatted mp3 data (main_data_begin always
// equal to 0).
//
// Returns: returns 1 on success, 0 on failure
///////////////////////////////////////////////////////////////////////////
int Init_n(unsigned char *pSync,
unsigned long ulSize,
unsigned char bUseSize=0);
///////////////////////////////////////////////////////////////////////////
// Function: DecodeFrame_v
// Purpose: Decodes one mp3 frame
// Parameters: pSource pointer to an mp3 frame (at a syncword)
// pulSize size of the buffer pSource points to. It will
// contain the number of mp3 bytes decoded upon
// return.
// pPCM pointer to a buffer to decode into
// pulPCMSize size of the PCM buffer. It will contain the
// number of PCM bytes prodced upon return.
///////////////////////////////////////////////////////////////////////////
void DecodeFrame_v(unsigned char *pSource,
unsigned long *pulSize,
unsigned char *pPCM,
unsigned long *pulPCMSize);
// overloaded new version that returns error code in errCode
void DecodeFrame_v(unsigned char *pSource,
unsigned long *pulSize,
unsigned char *pPCM,
unsigned long *pulPCMSize,
int *errCode);
void GetPCMInfo_v(unsigned long &ulSampRate,
int &nChannels,
int &nBitsPerSample);
// return number of samples per frame, PER CHANNEL (renderer multiplies this result by nChannels)
int GetSamplesPerFrame_n();
void SetTrustPackets(unsigned char bTrust) { m_bTrustPackets = bTrust; }
private:
void * m_pDec; // generic void ptr
void * m_pDecL1; // not implemented (could use old Xing mpadecl1.cpp)
void * m_pDecL2; // not implemented (could use old Xing mpadecl2.cpp)
HMP3Decoder m_pDecL3;
MP3FrameInfo m_lastMP3FrameInfo;
unsigned char m_bUseFrameSize;
unsigned char m_bTrustPackets;
};
#endif /* _MPADECOBJFIXPT_H_ */

View File

@@ -1,9 +0,0 @@
#ifdef ESP8266
# include "pgmspace.h"
#elif defined(ESP_PLATFORM) && __has_include(<pgm_space.h>)
# include <pgm_space.h>
#else
# define PROGMEM
# define pgm_read_byte(addr) (*(const unsigned char *)(addr))
# define pgm_read_word(addr) (*(const unsigned short *)(addr))
#endif

View File

@@ -1,13 +0,0 @@
//SPI
#define PIN_SPI_SCK 14
#define PIN_SPI_MOSI 7
#define PIN_SPI_SDCARD_CS 10 //SD-Card CS
#define PIN_SPI_MEM_CS 6 //Flashmem CS
//3V3 Voltage Regulator
#define PIN_SHUTDOWNPWR3V3 5
#define PWR3V3_ON HIGH
#define PWR3V3_OFF LOW

View File

@@ -1,295 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* polyphase.c - final stage of subband transform (polyphase synthesis filter)
*
* This is the C reference version using __int64
* Look in the appropriate subdirectories for optimized asm implementations
* (e.g. arm/asmpoly.s)
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/* input to Polyphase = Q(DQ_FRACBITS_OUT-2), gain 2 bits in convolution
* we also have the implicit bias of 2^15 to add back, so net fraction bits =
* DQ_FRACBITS_OUT - 2 - 2 - 15
* (see comment on Dequantize() for more info)
*/
#define DEF_NFRACBITS (DQ_FRACBITS_OUT - 2 - 2 - 15)
#define CSHIFT 12 /* coefficients have 12 leading sign bits for early-terminating mulitplies */
static __inline short ClipToShort(int x, int fracBits)
{
int sign;
/* assumes you've already rounded (x += (1 << (fracBits-1))) */
x >>= fracBits;
/* Ken's trick: clips to [-32768, 32767] */
sign = x >> 31;
if (sign != (x >> 15))
x = sign ^ ((1 << 15) - 1);
return (short)x;
}
#define MC0M(x) { \
c1 = *coef; coef++; c2 = *coef; coef++; \
vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
sum1L = MADD64(sum1L, vLo, c1); sum1L = MADD64(sum1L, vHi, -c2); \
}
#define MC1M(x) { \
c1 = *coef; coef++; \
vLo = *(vb1+(x)); \
sum1L = MADD64(sum1L, vLo, c1); \
}
#define MC2M(x) { \
c1 = *coef; coef++; c2 = *coef; coef++; \
vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
sum1L = MADD64(sum1L, vLo, c1); sum2L = MADD64(sum2L, vLo, c2); \
sum1L = MADD64(sum1L, vHi, -c2); sum2L = MADD64(sum2L, vHi, c1); \
}
/**************************************************************************************
* Function: PolyphaseMono
*
* Description: filter one subband and produce 32 output PCM samples for one channel
*
* Inputs: pointer to PCM output buffer
* number of "extra shifts" (vbuf format = Q(DQ_FRACBITS_OUT-2))
* pointer to start of vbuf (preserved from last call)
* start of filter coefficient table (in proper, shuffled order)
* no minimum number of guard bits is required for input vbuf
* (see additional scaling comments below)
*
* Outputs: 32 samples of one channel of decoded PCM data, (i.e. Q16.0)
*
* Return: none
*
* TODO: add 32-bit version for platforms where 64-bit mul-acc is not supported
* (note max filter gain - see polyCoef[] comments)
**************************************************************************************/
void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase)
{
int i;
const int *coef;
int *vb1;
int vLo, vHi, c1, c2;
Word64 sum1L, sum2L, rndVal;
rndVal = (Word64)( 1 << (DEF_NFRACBITS - 1 + (32 - CSHIFT)) );
/* special case, output sample 0 */
coef = coefBase;
vb1 = vbuf;
sum1L = rndVal;
MC0M(0)
MC0M(1)
MC0M(2)
MC0M(3)
MC0M(4)
MC0M(5)
MC0M(6)
MC0M(7)
*(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
/* special case, output sample 16 */
coef = coefBase + 256;
vb1 = vbuf + 64*16;
sum1L = rndVal;
MC1M(0)
MC1M(1)
MC1M(2)
MC1M(3)
MC1M(4)
MC1M(5)
MC1M(6)
MC1M(7)
*(pcm + 16) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
/* main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */
coef = coefBase + 16;
vb1 = vbuf + 64;
pcm++;
/* right now, the compiler creates bad asm from this... */
for (i = 15; i > 0; i--) {
sum1L = sum2L = rndVal;
MC2M(0)
MC2M(1)
MC2M(2)
MC2M(3)
MC2M(4)
MC2M(5)
MC2M(6)
MC2M(7)
vb1 += 64;
*(pcm) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
*(pcm + 2*i) = ClipToShort((int)SAR64(sum2L, (32-CSHIFT)), DEF_NFRACBITS);
pcm++;
}
}
#define MC0S(x) { \
c1 = *coef; coef++; c2 = *coef; coef++; \
vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
sum1L = MADD64(sum1L, vLo, c1); sum1L = MADD64(sum1L, vHi, -c2); \
vLo = *(vb1+32+(x)); vHi = *(vb1+32+(23-(x))); \
sum1R = MADD64(sum1R, vLo, c1); sum1R = MADD64(sum1R, vHi, -c2); \
}
#define MC1S(x) { \
c1 = *coef; coef++; \
vLo = *(vb1+(x)); \
sum1L = MADD64(sum1L, vLo, c1); \
vLo = *(vb1+32+(x)); \
sum1R = MADD64(sum1R, vLo, c1); \
}
#define MC2S(x) { \
c1 = *coef; coef++; c2 = *coef; coef++; \
vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \
sum1L = MADD64(sum1L, vLo, c1); sum2L = MADD64(sum2L, vLo, c2); \
sum1L = MADD64(sum1L, vHi, -c2); sum2L = MADD64(sum2L, vHi, c1); \
vLo = *(vb1+32+(x)); vHi = *(vb1+32+(23-(x))); \
sum1R = MADD64(sum1R, vLo, c1); sum2R = MADD64(sum2R, vLo, c2); \
sum1R = MADD64(sum1R, vHi, -c2); sum2R = MADD64(sum2R, vHi, c1); \
}
/**************************************************************************************
* Function: PolyphaseStereo
*
* Description: filter one subband and produce 32 output PCM samples for each channel
*
* Inputs: pointer to PCM output buffer
* number of "extra shifts" (vbuf format = Q(DQ_FRACBITS_OUT-2))
* pointer to start of vbuf (preserved from last call)
* start of filter coefficient table (in proper, shuffled order)
* no minimum number of guard bits is required for input vbuf
* (see additional scaling comments below)
*
* Outputs: 32 samples of two channels of decoded PCM data, (i.e. Q16.0)
*
* Return: none
*
* Notes: interleaves PCM samples LRLRLR...
*
* TODO: add 32-bit version for platforms where 64-bit mul-acc is not supported
**************************************************************************************/
void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase)
{
int i;
const int *coef;
int *vb1;
int vLo, vHi, c1, c2;
Word64 sum1L, sum2L, sum1R, sum2R, rndVal;
rndVal = (Word64)( 1 << (DEF_NFRACBITS - 1 + (32 - CSHIFT)) );
/* special case, output sample 0 */
coef = coefBase;
vb1 = vbuf;
sum1L = sum1R = rndVal;
MC0S(0)
MC0S(1)
MC0S(2)
MC0S(3)
MC0S(4)
MC0S(5)
MC0S(6)
MC0S(7)
*(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
*(pcm + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS);
/* special case, output sample 16 */
coef = coefBase + 256;
vb1 = vbuf + 64*16;
sum1L = sum1R = rndVal;
MC1S(0)
MC1S(1)
MC1S(2)
MC1S(3)
MC1S(4)
MC1S(5)
MC1S(6)
MC1S(7)
*(pcm + 2*16 + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
*(pcm + 2*16 + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS);
/* main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */
coef = coefBase + 16;
vb1 = vbuf + 64;
pcm += 2;
/* right now, the compiler creates bad asm from this... */
for (i = 15; i > 0; i--) {
sum1L = sum2L = rndVal;
sum1R = sum2R = rndVal;
MC2S(0)
MC2S(1)
MC2S(2)
MC2S(3)
MC2S(4)
MC2S(5)
MC2S(6)
MC2S(7)
vb1 += 64;
*(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS);
*(pcm + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS);
*(pcm + 2*2*i + 0) = ClipToShort((int)SAR64(sum2L, (32-CSHIFT)), DEF_NFRACBITS);
*(pcm + 2*2*i + 1) = ClipToShort((int)SAR64(sum2R, (32-CSHIFT)), DEF_NFRACBITS);
pcm += 2;
}
}

View File

@@ -1,392 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* scalfact.c - scalefactor unpacking functions
**************************************************************************************/
#include "coder.h"
/* scale factor lengths (num bits) */
static const char SFLenTab[16][2] = {
{0, 0}, {0, 1},
{0, 2}, {0, 3},
{3, 0}, {1, 1},
{1, 2}, {1, 3},
{2, 1}, {2, 2},
{2, 3}, {3, 1},
{3, 2}, {3, 3},
{4, 2}, {4, 3},
};
/**************************************************************************************
* Function: UnpackSFMPEG1
*
* Description: unpack MPEG 1 scalefactors from bitstream
*
* Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this
* granule/channel
* vector of scfsi flags from side info, length = 4 (MAX_SCFBD)
* index of current granule
* ScaleFactorInfoSub from granule 0 (for granule 1, if scfsi[i] is set,
* then we just replicate the scale factors from granule 0 in the
* i'th set of scalefactor bands)
*
* Outputs: updated BitStreamInfo struct
* scalefactors in sfis (short and/or long arrays, as appropriate)
*
* Return: none
*
* Notes: set order of short blocks to s[band][window] instead of s[window][band]
* so that we index through consectutive memory locations when unpacking
* (make sure dequantizer follows same convention)
* Illegal Intensity Position = 7 (always) for MPEG1 scale factors
**************************************************************************************/
static void UnpackSFMPEG1(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int *scfsi, int gr, ScaleFactorInfoSub *sfisGr0)
{
int sfb;
int slen0, slen1;
/* these can be 0, so make sure GetBits(bsi, 0) returns 0 (no >> 32 or anything) */
slen0 = (int)SFLenTab[sis->sfCompress][0];
slen1 = (int)SFLenTab[sis->sfCompress][1];
if (sis->blockType == 2) {
/* short block, type 2 (implies winSwitchFlag == 1) */
if (sis->mixedBlock) {
/* do long block portion */
for (sfb = 0; sfb < 8; sfb++)
sfis->l[sfb] = (char)GetBits(bsi, slen0);
sfb = 3;
} else {
/* all short blocks */
sfb = 0;
}
for ( ; sfb < 6; sfb++) {
sfis->s[sfb][0] = (char)GetBits(bsi, slen0);
sfis->s[sfb][1] = (char)GetBits(bsi, slen0);
sfis->s[sfb][2] = (char)GetBits(bsi, slen0);
}
for ( ; sfb < 12; sfb++) {
sfis->s[sfb][0] = (char)GetBits(bsi, slen1);
sfis->s[sfb][1] = (char)GetBits(bsi, slen1);
sfis->s[sfb][2] = (char)GetBits(bsi, slen1);
}
/* last sf band not transmitted */
sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0;
} else {
/* long blocks, type 0, 1, or 3 */
if(gr == 0) {
/* first granule */
for (sfb = 0; sfb < 11; sfb++)
sfis->l[sfb] = (char)GetBits(bsi, slen0);
for (sfb = 11; sfb < 21; sfb++)
sfis->l[sfb] = (char)GetBits(bsi, slen1);
return;
} else {
/* second granule
* scfsi: 0 = different scalefactors for each granule, 1 = copy sf's from granule 0 into granule 1
* for block type == 2, scfsi is always 0
*/
sfb = 0;
if(scfsi[0]) for( ; sfb < 6 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
else for( ; sfb < 6 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0);
if(scfsi[1]) for( ; sfb <11 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
else for( ; sfb <11 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0);
if(scfsi[2]) for( ; sfb <16 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
else for( ; sfb <16 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1);
if(scfsi[3]) for( ; sfb <21 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb];
else for( ; sfb <21 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1);
}
/* last sf band not transmitted */
sfis->l[21] = 0;
sfis->l[22] = 0;
}
}
/* NRTab[size + 3*is_right][block type][partition]
* block type index: 0 = (bt0,bt1,bt3), 1 = bt2 non-mixed, 2 = bt2 mixed
* partition: scale factor groups (sfb1 through sfb4)
* for block type = 2 (mixed or non-mixed) / by 3 is rolled into this table
* (for 3 short blocks per long block)
* see 2.4.3.2 in MPEG 2 (low sample rate) spec
* stuff rolled into this table:
* NRTab[x][1][y] --> (NRTab[x][1][y]) / 3
* NRTab[x][2][>=1] --> (NRTab[x][2][>=1]) / 3 (first partition is long block)
*/
static const char NRTab[6][3][4] = {
/* non-intensity stereo */
{ {6, 5, 5, 5},
{3, 3, 3, 3}, /* includes / 3 */
{6, 3, 3, 3}, /* includes / 3 except for first entry */
},
{ {6, 5, 7, 3},
{3, 3, 4, 2},
{6, 3, 4, 2},
},
{ {11, 10, 0, 0},
{6, 6, 0, 0},
{6, 3, 6, 0}, /* spec = [15,18,0,0], but 15 = 6L + 9S, so move 9/3=3 into col 1, 18/3=6 into col 2 and adj. slen[1,2] below */
},
/* intensity stereo, right chan */
{ {7, 7, 7, 0},
{4, 4, 4, 0},
{6, 5, 4, 0},
},
{ {6, 6, 6, 3},
{4, 3, 3, 2},
{6, 4, 3, 2},
},
{ {8, 8, 5, 0},
{5, 4, 3, 0},
{6, 6, 3, 0},
}
};
/**************************************************************************************
* Function: UnpackSFMPEG2
*
* Description: unpack MPEG 2 scalefactors from bitstream
*
* Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this
* granule/channel
* index of current granule and channel
* ScaleFactorInfoSub from this granule
* modeExt field from frame header, to tell whether intensity stereo is on
* ScaleFactorJS struct for storing IIP info used in Dequant()
*
* Outputs: updated BitStreamInfo struct
* scalefactors in sfis (short and/or long arrays, as appropriate)
* updated intensityScale and preFlag flags
*
* Return: none
*
* Notes: Illegal Intensity Position = (2^slen) - 1 for MPEG2 scale factors
*
* TODO: optimize the / and % stuff (only do one divide, get modulo x
* with (x / m) * m, etc.)
**************************************************************************************/
static void UnpackSFMPEG2(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int gr, int ch, int modeExt, ScaleFactorJS *sfjs)
{
int i, sfb, sfcIdx, btIdx, nrIdx;// iipTest;
int slen[4], nr[4];
int sfCompress, preFlag, intensityScale;
(void)gr;
sfCompress = sis->sfCompress;
preFlag = 0;
intensityScale = 0;
/* stereo mode bits (1 = on): bit 1 = mid-side on/off, bit 0 = intensity on/off */
if (! ((modeExt & 0x01) && (ch == 1)) ) {
/* in other words: if ((modeExt & 0x01) == 0 || ch == 0) */
if (sfCompress < 400) {
/* max slen = floor[(399/16) / 5] = 4 */
slen[0] = (sfCompress >> 4) / 5;
slen[1]= (sfCompress >> 4) % 5;
slen[2]= (sfCompress & 0x0f) >> 2;
slen[3]= (sfCompress & 0x03);
sfcIdx = 0;
} else if (sfCompress < 500) {
/* max slen = floor[(99/4) / 5] = 4 */
sfCompress -= 400;
slen[0] = (sfCompress >> 2) / 5;
slen[1]= (sfCompress >> 2) % 5;
slen[2]= (sfCompress & 0x03);
slen[3]= 0;
sfcIdx = 1;
} else {
/* max slen = floor[11/3] = 3 (sfCompress = 9 bits in MPEG2) */
sfCompress -= 500;
slen[0] = sfCompress / 3;
slen[1] = sfCompress % 3;
slen[2] = slen[3] = 0;
if (sis->mixedBlock) {
/* adjust for long/short mix logic (see comment above in NRTab[] definition) */
slen[2] = slen[1];
slen[1] = slen[0];
}
preFlag = 1;
sfcIdx = 2;
}
} else {
/* intensity stereo ch = 1 (right) */
intensityScale = sfCompress & 0x01;
sfCompress >>= 1;
if (sfCompress < 180) {
/* max slen = floor[35/6] = 5 (from mod 36) */
slen[0] = (sfCompress / 36);
slen[1] = (sfCompress % 36) / 6;
slen[2] = (sfCompress % 36) % 6;
slen[3] = 0;
sfcIdx = 3;
} else if (sfCompress < 244) {
/* max slen = floor[63/16] = 3 */
sfCompress -= 180;
slen[0] = (sfCompress & 0x3f) >> 4;
slen[1] = (sfCompress & 0x0f) >> 2;
slen[2] = (sfCompress & 0x03);
slen[3] = 0;
sfcIdx = 4;
} else {
/* max slen = floor[11/3] = 3 (max sfCompress >> 1 = 511/2 = 255) */
sfCompress -= 244;
slen[0] = (sfCompress / 3);
slen[1] = (sfCompress % 3);
slen[2] = slen[3] = 0;
sfcIdx = 5;
}
}
/* set index based on block type: (0,1,3) --> 0, (2 non-mixed) --> 1, (2 mixed) ---> 2 */
btIdx = 0;
if (sis->blockType == 2)
btIdx = (sis->mixedBlock ? 2 : 1);
for (i = 0; i < 4; i++)
nr[i] = (int)NRTab[sfcIdx][btIdx][i];
/* save intensity stereo scale factor info */
if( (modeExt & 0x01) && (ch == 1) ) {
for (i = 0; i < 4; i++) {
sfjs->slen[i] = slen[i];
sfjs->nr[i] = nr[i];
}
sfjs->intensityScale = intensityScale;
}
sis->preFlag = preFlag;
/* short blocks */
if(sis->blockType == 2) {
if(sis->mixedBlock) {
/* do long block portion */
//iipTest = (1 << slen[0]) - 1;
for (sfb=0; sfb < 6; sfb++) {
sfis->l[sfb] = (char)GetBits(bsi, slen[0]);
}
sfb = 3; /* start sfb for short */
nrIdx = 1;
} else {
/* all short blocks, so start nr, sfb at 0 */
sfb = 0;
nrIdx = 0;
}
/* remaining short blocks, sfb just keeps incrementing */
for ( ; nrIdx <= 3; nrIdx++) {
//iipTest = (1 << slen[nrIdx]) - 1;
for (i=0; i < nr[nrIdx]; i++, sfb++) {
sfis->s[sfb][0] = (char)GetBits(bsi, slen[nrIdx]);
sfis->s[sfb][1] = (char)GetBits(bsi, slen[nrIdx]);
sfis->s[sfb][2] = (char)GetBits(bsi, slen[nrIdx]);
}
}
/* last sf band not transmitted */
sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0;
} else {
/* long blocks */
sfb = 0;
for (nrIdx = 0; nrIdx <= 3; nrIdx++) {
//iipTest = (1 << slen[nrIdx]) - 1;
for(i=0; i < nr[nrIdx]; i++, sfb++) {
sfis->l[sfb] = (char)GetBits(bsi, slen[nrIdx]);
}
}
/* last sf band not transmitted */
sfis->l[21] = sfis->l[22] = 0;
}
}
/**************************************************************************************
* Function: UnpackScaleFactors
*
* Description: parse the fields of the MP3 scale factor data section
*
* Inputs: MP3DecInfo structure filled by UnpackFrameHeader() and UnpackSideInfo()
* buffer pointing to the MP3 scale factor data
* pointer to bit offset (0-7) indicating starting bit in buf[0]
* number of bits available in data buffer
* index of current granule and channel
*
* Outputs: updated platform-specific ScaleFactorInfo struct
* updated bitOffset
*
* Return: length (in bytes) of scale factor data, -1 if null input pointers
**************************************************************************************/
int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch)
{
int bitsUsed;
unsigned char *startBuf;
BitStreamInfo bitStreamInfo, *bsi;
FrameHeader *fh;
SideInfo *si;
ScaleFactorInfo *sfi;
/* validate pointers */
if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS)
return -1;
fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS));
si = ((SideInfo *)(mp3DecInfo->SideInfoPS));
sfi = ((ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS));
/* init GetBits reader */
startBuf = buf;
bsi = &bitStreamInfo;
SetBitstreamPointer(bsi, (bitsAvail + *bitOffset + 7) / 8, buf);
if (*bitOffset)
GetBits(bsi, *bitOffset);
if (fh->ver == MPEG1)
UnpackSFMPEG1(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], si->scfsi[ch], gr, &sfi->sfis[0][ch]);
else
UnpackSFMPEG2(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], gr, ch, fh->modeExt, &sfi->sfjs);
mp3DecInfo->part23Length[gr][ch] = si->sis[gr][ch].part23Length;
bitsUsed = CalcBitsUsed(bsi, buf, *bitOffset);
buf += (bitsUsed + *bitOffset) >> 3;
*bitOffset = (bitsUsed + *bitOffset) & 0x07;
return (buf - startBuf);
}

View File

@@ -1,89 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* statname.h - name mangling macros for static linking
**************************************************************************************/
#ifndef _STATNAME_H
#define _STATNAME_H
/* define STAT_PREFIX to a unique name for static linking
* all the C functions and global variables will be mangled by the preprocessor
* e.g. void FFT(int *fftbuf) becomes void cook_FFT(int *fftbuf)
*/
#define STAT_PREFIX xmp3
#define STATCC1(x,y,z) STATCC2(x,y,z)
#define STATCC2(x,y,z) x##y##z
#ifdef STAT_PREFIX
#define STATNAME(func) STATCC1(STAT_PREFIX, _, func)
#else
#define STATNAME(func) func
#endif
/* these symbols are common to all implementations */
#define CheckPadBit STATNAME(CheckPadBit)
#define UnpackFrameHeader STATNAME(UnpackFrameHeader)
#define UnpackSideInfo STATNAME(UnpackSideInfo)
#define AllocateBuffers STATNAME(AllocateBuffers)
#define FreeBuffers STATNAME(FreeBuffers)
#define DecodeHuffman STATNAME(DecodeHuffman)
#define Dequantize STATNAME(Dequantize)
#define IMDCT STATNAME(IMDCT)
#define UnpackScaleFactors STATNAME(UnpackScaleFactors)
#define Subband STATNAME(Subband)
#define samplerateTab STATNAME(samplerateTab)
#define bitrateTab STATNAME(bitrateTab)
#define samplesPerFrameTab STATNAME(samplesPerFrameTab)
#define bitsPerSlotTab STATNAME(bitsPerSlotTab)
#define sideBytesTab STATNAME(sideBytesTab)
#define slotTab STATNAME(slotTab)
#define sfBandTable STATNAME(sfBandTable)
/* in your implementation's top-level include file (e.g. real\coder.h) you should
* add new #define sym STATNAME(sym) lines for all the
* additional global functions or variables which your
* implementation uses
*/
#endif /* _STATNAME_H */

View File

@@ -1,299 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* stproc.c - mid-side and intensity (MPEG1 and MPEG2) stereo processing
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: MidSideProc
*
* Description: sum-difference stereo reconstruction
*
* Inputs: vector x with dequantized samples from left and right channels
* number of non-zero samples (MAX of left and right)
* assume 1 guard bit in input
* guard bit mask (left and right channels)
*
* Outputs: updated sample vector x
* updated guard bit mask
*
* Return: none
*
* Notes: assume at least 1 GB in input
**************************************************************************************/
void MidSideProc(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, int mOut[2])
{
int i, xr, xl, mOutL, mOutR;
/* L = (M+S)/sqrt(2), R = (M-S)/sqrt(2)
* NOTE: 1/sqrt(2) done in DequantChannel() - see comments there
*/
mOutL = mOutR = 0;
for(i = 0; i < nSamps; i++) {
xl = x[0][i];
xr = x[1][i];
x[0][i] = xl + xr;
x[1][i] = xl - xr;
mOutL |= FASTABS(x[0][i]);
mOutR |= FASTABS(x[1][i]);
}
mOut[0] |= mOutL;
mOut[1] |= mOutR;
}
/**************************************************************************************
* Function: IntensityProcMPEG1
*
* Description: intensity stereo processing for MPEG1
*
* Inputs: vector x with dequantized samples from left and right channels
* number of non-zero samples in left channel
* valid FrameHeader struct
* two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels)
* flags indicating midSide on/off, mixedBlock on/off
* guard bit mask (left and right channels)
*
* Outputs: updated sample vector x
* updated guard bit mask
*
* Return: none
*
* Notes: assume at least 1 GB in input
*
* TODO: combine MPEG1/2 into one function (maybe)
* make sure all the mixed-block and IIP logic is right
**************************************************************************************/
void IntensityProcMPEG1(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis,
CriticalBandInfo *cbi, int midSideFlag, int mixFlag, int mOut[2])
{
int i=0, j=0, n=0, cb=0, w=0;
int sampsLeft, isf, mOutL, mOutR, xl, xr;
int fl, fr, fls[3], frs[3];
int cbStartL=0, cbStartS=0, cbEndL=0, cbEndS=0;
int *isfTab;
(void)mixFlag;
/* NOTE - this works fine for mixed blocks, as long as the switch point starts in the
* short block section (i.e. on or after sample 36 = sfBand->l[8] = 3*sfBand->s[3]
* is this a safe assumption?
* TODO - intensity + mixed not quite right (diff = 11 on he_mode)
* figure out correct implementation (spec ambiguous about when to do short block reorder)
*/
if (cbi[1].cbType == 0) {
/* long block */
cbStartL = cbi[1].cbEndL + 1;
cbEndL = cbi[0].cbEndL + 1;
cbStartS = cbEndS = 0;
i = fh->sfBand->l[cbStartL];
} else if (cbi[1].cbType == 1 || cbi[1].cbType == 2) {
/* short or mixed block */
cbStartS = cbi[1].cbEndSMax + 1;
cbEndS = cbi[0].cbEndSMax + 1;
cbStartL = cbEndL = 0;
i = 3 * fh->sfBand->s[cbStartS];
}
sampsLeft = nSamps - i; /* process to length of left */
isfTab = (int *)ISFMpeg1[midSideFlag];
mOutL = mOutR = 0;
/* long blocks */
for (cb = cbStartL; cb < cbEndL && sampsLeft > 0; cb++) {
isf = sfis->l[cb];
if (isf == 7) {
fl = ISFIIP[midSideFlag][0];
fr = ISFIIP[midSideFlag][1];
} else {
fl = isfTab[isf];
fr = isfTab[6] - isfTab[isf];
}
n = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb];
for (j = 0; j < n && sampsLeft > 0; j++, i++) {
xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr);
xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl);
sampsLeft--;
}
}
/* short blocks */
for (cb = cbStartS; cb < cbEndS && sampsLeft >= 3; cb++) {
for (w = 0; w < 3; w++) {
isf = sfis->s[cb][w];
if (isf == 7) {
fls[w] = ISFIIP[midSideFlag][0];
frs[w] = ISFIIP[midSideFlag][1];
} else {
fls[w] = isfTab[isf];
frs[w] = isfTab[6] - isfTab[isf];
}
}
n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb];
for (j = 0; j < n && sampsLeft >= 3; j++, i+=3) {
xr = MULSHIFT32(frs[0], x[0][i+0]) << 2; x[1][i+0] = xr; mOutR |= FASTABS(xr);
xl = MULSHIFT32(fls[0], x[0][i+0]) << 2; x[0][i+0] = xl; mOutL |= FASTABS(xl);
xr = MULSHIFT32(frs[1], x[0][i+1]) << 2; x[1][i+1] = xr; mOutR |= FASTABS(xr);
xl = MULSHIFT32(fls[1], x[0][i+1]) << 2; x[0][i+1] = xl; mOutL |= FASTABS(xl);
xr = MULSHIFT32(frs[2], x[0][i+2]) << 2; x[1][i+2] = xr; mOutR |= FASTABS(xr);
xl = MULSHIFT32(fls[2], x[0][i+2]) << 2; x[0][i+2] = xl; mOutL |= FASTABS(xl);
sampsLeft -= 3;
}
}
mOut[0] = mOutL;
mOut[1] = mOutR;
return;
}
/**************************************************************************************
* Function: IntensityProcMPEG2
*
* Description: intensity stereo processing for MPEG2
*
* Inputs: vector x with dequantized samples from left and right channels
* number of non-zero samples in left channel
* valid FrameHeader struct
* two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels)
* ScaleFactorJS struct with joint stereo info from UnpackSFMPEG2()
* flags indicating midSide on/off, mixedBlock on/off
* guard bit mask (left and right channels)
*
* Outputs: updated sample vector x
* updated guard bit mask
*
* Return: none
*
* Notes: assume at least 1 GB in input
*
* TODO: combine MPEG1/2 into one function (maybe)
* make sure all the mixed-block and IIP logic is right
* probably redo IIP logic to be simpler
**************************************************************************************/
void IntensityProcMPEG2(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis,
CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int midSideFlag, int mixFlag, int mOut[2])
{
int i, j, k, n, r, cb, w;
int fl, fr, mOutL, mOutR, xl, xr;
int sampsLeft;
int isf, sfIdx, tmp, il[23];
int *isfTab;
int cbStartL, cbStartS, cbEndL, cbEndS;
(void)mixFlag;
isfTab = (int *)ISFMpeg2[sfjs->intensityScale][midSideFlag];
mOutL = mOutR = 0;
/* fill buffer with illegal intensity positions (depending on slen) */
for (k = r = 0; r < 4; r++) {
tmp = (1 << sfjs->slen[r]) - 1;
for (j = 0; j < sfjs->nr[r]; j++, k++)
il[k] = tmp;
}
if (cbi[1].cbType == 0) {
/* long blocks */
il[21] = il[22] = 1;
cbStartL = cbi[1].cbEndL + 1; /* start at end of right */
cbEndL = cbi[0].cbEndL + 1; /* process to end of left */
i = fh->sfBand->l[cbStartL];
sampsLeft = nSamps - i;
for(cb = cbStartL; cb < cbEndL; cb++) {
sfIdx = sfis->l[cb];
if (sfIdx == il[cb]) {
fl = ISFIIP[midSideFlag][0];
fr = ISFIIP[midSideFlag][1];
} else {
isf = (sfis->l[cb] + 1) >> 1;
fl = isfTab[(sfIdx & 0x01 ? isf : 0)];
fr = isfTab[(sfIdx & 0x01 ? 0 : isf)];
}
n = MIN(fh->sfBand->l[cb + 1] - fh->sfBand->l[cb], sampsLeft);
for(j = 0; j < n; j++, i++) {
xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr);
xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl);
}
/* early exit once we've used all the non-zero samples */
sampsLeft -= n;
if (sampsLeft == 0)
break;
}
} else {
/* short or mixed blocks */
il[12] = 1;
for(w = 0; w < 3; w++) {
cbStartS = cbi[1].cbEndS[w] + 1; /* start at end of right */
cbEndS = cbi[0].cbEndS[w] + 1; /* process to end of left */
i = 3 * fh->sfBand->s[cbStartS] + w;
/* skip through sample array by 3, so early-exit logic would be more tricky */
for(cb = cbStartS; cb < cbEndS; cb++) {
sfIdx = sfis->s[cb][w];
if (sfIdx == il[cb]) {
fl = ISFIIP[midSideFlag][0];
fr = ISFIIP[midSideFlag][1];
} else {
isf = (sfis->s[cb][w] + 1) >> 1;
fl = isfTab[(sfIdx & 0x01 ? isf : 0)];
fr = isfTab[(sfIdx & 0x01 ? 0 : isf)];
}
n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb];
for(j = 0; j < n; j++, i+=3) {
xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr);
xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl);
}
}
}
}
mOut[0] = mOutL;
mOut[1] = mOutR;
return;
}

View File

@@ -1,96 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* subband.c - subband transform (synthesis filterbank implemented via 32-point DCT
* followed by polyphase filter)
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: Subband
*
* Description: do subband transform on all the blocks in one granule, all channels
*
* Inputs: filled MP3DecInfo structure, after calling IMDCT for all channels
* vbuf[ch] and vindex[ch] must be preserved between calls
*
* Outputs: decoded PCM data, interleaved LRLRLR... if stereo
*
* Return: 0 on success, -1 if null input pointers
**************************************************************************************/
/*__attribute__ ((section (".data"))) */ int Subband(MP3DecInfo *mp3DecInfo, short *pcmBuf)
{
int b;
//HuffmanInfo *hi;
IMDCTInfo *mi;
SubbandInfo *sbi;
/* validate pointers */
if (!mp3DecInfo || !mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->IMDCTInfoPS || !mp3DecInfo->SubbandInfoPS)
return -1;
//hi = (HuffmanInfo *)mp3DecInfo->HuffmanInfoPS;
mi = (IMDCTInfo *)(mp3DecInfo->IMDCTInfoPS);
sbi = (SubbandInfo*)(mp3DecInfo->SubbandInfoPS);
if (mp3DecInfo->nChans == 2) {
/* stereo */
for (b = 0; b < BLOCK_SIZE; b++) {
FDCT32(mi->outBuf[0][b], sbi->vbuf + 0*32, sbi->vindex, (b & 0x01), mi->gb[0]);
FDCT32(mi->outBuf[1][b], sbi->vbuf + 1*32, sbi->vindex, (b & 0x01), mi->gb[1]);
PolyphaseStereo(pcmBuf, sbi->vbuf + sbi->vindex + VBUF_LENGTH * (b & 0x01), polyCoef);
sbi->vindex = (sbi->vindex - (b & 0x01)) & 7;
pcmBuf += (2 * NBANDS);
}
} else {
/* mono */
for (b = 0; b < BLOCK_SIZE; b++) {
FDCT32(mi->outBuf[0][b], sbi->vbuf + 0*32, sbi->vindex, (b & 0x01), mi->gb[0]);
PolyphaseMono(pcmBuf, sbi->vbuf + sbi->vindex + VBUF_LENGTH * (b & 0x01), polyCoef);
sbi->vindex = (sbi->vindex - (b & 0x01)) & 7;
pcmBuf += NBANDS;
}
}
return 0;
}

View File

@@ -1,319 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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 MP3 decoder
* Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com)
* June 2003
*
* trigtabs.c - global ROM tables for pre-calculated trig coefficients
**************************************************************************************/
// constants in RAM are not significantly faster
#include "coder.h"
#include <pgmspace.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
/* post-IMDCT window, win[blockType][i]
* format = Q31
* Fused sin window with final stage of IMDCT
* includes 1/sqrt(2) scaling, since we scale by sqrt(2) in dequant in order
* for fast IMDCT36 to be usable
*
* for(i=0;i<9;i++) win[0][i] = sin(pi/36 *(i+0.5));
* for(i=9;i<36;i++) win[0][i] = -sin(pi/36 *(i+0.5));
*
* for(i=0;i<9;i++) win[1][i] = sin(pi/36 *(i+0.5));
* for(i=9;i<18;i++) win[1][i] = -sin(pi/36 *(i+0.5));
* for(i=18;i<24;i++) win[1][i] = -1;
* for(i=24;i<30;i++) win[1][i] = -sin(pi/12 *(i+0.5-18));
* for(i=30;i<36;i++) win[1][i] = 0;
*
* for(i=0;i<6;i++) win[3][i] = 0;
* for(i=6;i<9;i++) win[3][i] = sin(pi/12 *(i+0.5-6));
* for(i=9;i<12;i++) win[3][i] = -sin(pi/12 *(i+0.5-6));
* for(i=12;i<18;i++) win[3][i] = -1;
* for(i=18;i<36;i++) win[3][i] = -sin(pi/36*(i+0.5));
*
* for(i=0;i<3;i++) win[2][i] = sin(pi/12*(i+0.5));
* for(i=3;i<12;i++) win[2][i] = -sin(pi/12*(i+0.5));
* for(i=12;i<36;i++) win[2][i] = 0;
*
* for (i = 0; i < 4; i++) {
* if (i == 2) {
* win[i][8] *= cos(pi/12 * (0+0.5));
* win[i][9] *= cos(pi/12 * (0+0.5));
* win[i][7] *= cos(pi/12 * (1+0.5));
* win[i][10] *= cos(pi/12 * (1+0.5));
* win[i][6] *= cos(pi/12 * (2+0.5));
* win[i][11] *= cos(pi/12 * (2+0.5));
* win[i][0] *= cos(pi/12 * (3+0.5));
* win[i][5] *= cos(pi/12 * (3+0.5));
* win[i][1] *= cos(pi/12 * (4+0.5));
* win[i][4] *= cos(pi/12 * (4+0.5));
* win[i][2] *= cos(pi/12 * (5+0.5));
* win[i][3] *= cos(pi/12 * (5+0.5));
* } else {
* for (j = 0; j < 9; j++) {
* win[i][8-j] *= cos(pi/36 * (17-j+0.5));
* win[i][9+j] *= cos(pi/36 * (17-j+0.5));
* }
* for (j = 0; j < 9; j++) {
* win[i][18+8-j] *= cos(pi/36 * (j+0.5));
* win[i][18+9+j] *= cos(pi/36 * (j+0.5));
* }
* }
* }
* for (i = 0; i < 4; i++)
* for (j = 0; j < 36; j++)
* win[i][j] *= 1.0 / sqrt(2);
*/
const int imdctWin[4][36] PROGMEM = {
{
0x02aace8b, 0x07311c28, 0x0a868fec, 0x0c913b52, 0x0d413ccd, 0x0c913b52, 0x0a868fec, 0x07311c28,
0x02aace8b, 0xfd16d8dd, 0xf6a09e66, 0xef7a6275, 0xe7dbc161, 0xe0000000, 0xd8243e9f, 0xd0859d8b,
0xc95f619a, 0xc2e92723, 0xbd553175, 0xb8cee3d8, 0xb5797014, 0xb36ec4ae, 0xb2bec333, 0xb36ec4ae,
0xb5797014, 0xb8cee3d8, 0xbd553175, 0xc2e92723, 0xc95f619a, 0xd0859d8b, 0xd8243e9f, 0xe0000000,
0xe7dbc161, 0xef7a6275, 0xf6a09e66, 0xfd16d8dd,
},
{
0x02aace8b, 0x07311c28, 0x0a868fec, 0x0c913b52, 0x0d413ccd, 0x0c913b52, 0x0a868fec, 0x07311c28,
0x02aace8b, 0xfd16d8dd, 0xf6a09e66, 0xef7a6275, 0xe7dbc161, 0xe0000000, 0xd8243e9f, 0xd0859d8b,
0xc95f619a, 0xc2e92723, 0xbd44ef14, 0xb831a052, 0xb3aa3837, 0xafb789a4, 0xac6145bb, 0xa9adecdc,
0xa864491f, 0xad1868f0, 0xb8431f49, 0xc8f42236, 0xdda8e6b1, 0xf47755dc, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
{
0x07311c28, 0x0d413ccd, 0x07311c28, 0xf6a09e66, 0xe0000000, 0xc95f619a, 0xb8cee3d8, 0xb2bec333,
0xb8cee3d8, 0xc95f619a, 0xe0000000, 0xf6a09e66, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
},
{
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x028e9709, 0x04855ec0,
0x026743a1, 0xfcde2c10, 0xf515dc82, 0xec93e53b, 0xe4c880f8, 0xdd5d0b08, 0xd63510b7, 0xcf5e834a,
0xc8e6b562, 0xc2da4105, 0xbd553175, 0xb8cee3d8, 0xb5797014, 0xb36ec4ae, 0xb2bec333, 0xb36ec4ae,
0xb5797014, 0xb8cee3d8, 0xbd553175, 0xc2e92723, 0xc95f619a, 0xd0859d8b, 0xd8243e9f, 0xe0000000,
0xe7dbc161, 0xef7a6275, 0xf6a09e66, 0xfd16d8dd,
},
};
/* indexing = [mid-side off/on][intensity scale factor]
* format = Q30, range = [0.0, 1.414]
*
* mid-side off:
* ISFMpeg1[0][i] = tan(i*pi/12) / [1 + tan(i*pi/12)] (left scalefactor)
* = 1 / [1 + tan(i*pi/12)] (right scalefactor)
*
* mid-side on:
* ISFMpeg1[1][i] = sqrt(2) * ISFMpeg1[0][i]
*
* output L = ISFMpeg1[midSide][isf][0] * input L
* output R = ISFMpeg1[midSide][isf][1] * input L
*
* obviously left scalefactor + right scalefactor = 1 (m-s off) or sqrt(2) (m-s on)
* so just store left and calculate right as 1 - left
* (can derive as right = ISFMpeg1[x][6] - left)
*
* if mid-side enabled, multiply joint stereo scale factors by sqrt(2)
* - we scaled whole spectrum by 1/sqrt(2) in Dequant for the M+S/sqrt(2) in MidSideProc
* - but the joint stereo part of the spectrum doesn't need this, so we have to undo it
*
* if scale factor is and illegal intensity position, this becomes a passthrough
* - gain = [1, 0] if mid-side off, since L is coded directly and R = 0 in this region
* - gain = [1, 1] if mid-side on, since L = (M+S)/sqrt(2), R = (M-S)/sqrt(2)
* - and since S = 0 in the joint stereo region (above NZB right) then L = R = M * 1.0
*/
const int ISFMpeg1[2][7] PROGMEM = {
{0x00000000, 0x0d8658ba, 0x176cf5d0, 0x20000000, 0x28930a2f, 0x3279a745, 0x40000000},
{0x00000000, 0x13207f5c, 0x2120fb83, 0x2d413ccc, 0x39617e16, 0x4761fa3d, 0x5a827999}
};
/* indexing = [intensity scale on/off][mid-side off/on][intensity scale factor]
* format = Q30, range = [0.0, 1.414]
*
* if (isf == 0) kl = 1.0 kr = 1.0
* else if (isf & 0x01 == 0x01) kl = i0^((isf+1)/2), kr = 1.0
* else if (isf & 0x01 == 0x00) kl = 1.0, kr = i0^(isf/2)
*
* if (intensityScale == 1) i0 = 1/sqrt(2) = 0x2d413ccc (Q30)
* else i0 = 1/sqrt(sqrt(2)) = 0x35d13f32 (Q30)
*
* see comments for ISFMpeg1 (just above) regarding scaling, sqrt(2), etc.
*
* compress the MPEG2 table using the obvious identities above...
* for isf = [0, 1, 2, ... 30], let sf = table[(isf+1) >> 1]
* - if isf odd, L = sf*L, R = tab[0]*R
* - if isf even, L = tab[0]*L, R = sf*R
*/
const int ISFMpeg2[2][2][16] PROGMEM = {
{
{
/* intensityScale off, mid-side off */
0x40000000, 0x35d13f32, 0x2d413ccc, 0x260dfc14, 0x1fffffff, 0x1ae89f99, 0x16a09e66, 0x1306fe0a,
0x0fffffff, 0x0d744fcc, 0x0b504f33, 0x09837f05, 0x07ffffff, 0x06ba27e6, 0x05a82799, 0x04c1bf82,
},
{
/* intensityScale off, mid-side on */
0x5a827999, 0x4c1bf827, 0x3fffffff, 0x35d13f32, 0x2d413ccc, 0x260dfc13, 0x1fffffff, 0x1ae89f99,
0x16a09e66, 0x1306fe09, 0x0fffffff, 0x0d744fcc, 0x0b504f33, 0x09837f04, 0x07ffffff, 0x06ba27e6,
},
},
{
{
/* intensityScale on, mid-side off */
0x40000000, 0x2d413ccc, 0x20000000, 0x16a09e66, 0x10000000, 0x0b504f33, 0x08000000, 0x05a82799,
0x04000000, 0x02d413cc, 0x02000000, 0x016a09e6, 0x01000000, 0x00b504f3, 0x00800000, 0x005a8279,
},
/* intensityScale on, mid-side on */
{
0x5a827999, 0x3fffffff, 0x2d413ccc, 0x1fffffff, 0x16a09e66, 0x0fffffff, 0x0b504f33, 0x07ffffff,
0x05a82799, 0x03ffffff, 0x02d413cc, 0x01ffffff, 0x016a09e6, 0x00ffffff, 0x00b504f3, 0x007fffff,
}
}
};
/* indexing = [intensity scale on/off][left/right]
* format = Q30, range = [0.0, 1.414]
*
* illegal intensity position scalefactors (see comments on ISFMpeg1)
*/
const int ISFIIP[2][2] PROGMEM = {
{0x40000000, 0x00000000}, /* mid-side off */
{0x40000000, 0x40000000}, /* mid-side on */
};
const unsigned char uniqueIDTab[8] = {0x5f, 0x4b, 0x43, 0x5f, 0x5f, 0x4a, 0x52, 0x5f};
/* anti-alias coefficients - see spec Annex B, table 3-B.9
* csa[0][i] = CSi, csa[1][i] = CAi
* format = Q31
*/
const int csa[8][2] PROGMEM = {
{0x6dc253f0, 0xbe2500aa},
{0x70dcebe4, 0xc39e4949},
{0x798d6e73, 0xd7e33f4a},
{0x7ddd40a7, 0xe8b71176},
{0x7f6d20b7, 0xf3e4fe2f},
{0x7fe47e40, 0xfac1a3c7},
{0x7ffcb263, 0xfe2ebdc6},
{0x7fffc694, 0xff86c25d},
};
/* format = Q30, range = [0.0981, 1.9976]
*
* n = 16;
* k = 0;
* for(i=0; i<5; i++, n=n/2) {
* for(p=0; p<n; p++, k++) {
* t = (PI / (4*n)) * (2*p + 1);
* coef32[k] = 2.0 * cos(t);
* }
* }
* coef32[30] *= 0.5; / *** for initial back butterfly (i.e. two-point DCT) *** /
*/
const int coef32[31] PROGMEM = {
0x7fd8878d, 0x7e9d55fc, 0x7c29fbee, 0x78848413, 0x73b5ebd0, 0x6dca0d14, 0x66cf811f, 0x5ed77c89,
0x55f5a4d2, 0x4c3fdff3, 0x41ce1e64, 0x36ba2013, 0x2b1f34eb, 0x1f19f97b, 0x12c8106e, 0x0647d97c,
0x7f62368f, 0x7a7d055b, 0x70e2cbc6, 0x62f201ac, 0x5133cc94, 0x3c56ba70, 0x25280c5d, 0x0c8bd35e,
0x7d8a5f3f, 0x6a6d98a4, 0x471cece6, 0x18f8b83c, 0x7641af3c, 0x30fbc54d, 0x2d413ccc,
};
/* format = Q30, right shifted by 12 (sign bits only in top 12 - undo this when rounding to short)
* this is to enable early-terminating multiplies on ARM
* range = [-1.144287109, 1.144989014]
* max gain of filter (per output sample) ~= 2.731
*
* new (properly sign-flipped) values
* - these actually are correct to 32 bits, (floating-pt coefficients in spec
* chosen such that only ~20 bits are required)
*
* Reordering - see table 3-B.3 in spec (appendix B)
*
* polyCoef[i] =
* D[ 0, 32, 64, ... 480], i = [ 0, 15]
* D[ 1, 33, 65, ... 481], i = [ 16, 31]
* D[ 2, 34, 66, ... 482], i = [ 32, 47]
* ...
* D[15, 47, 79, ... 495], i = [240,255]
*
* also exploits symmetry: D[i] = -D[512 - i], for i = [1, 255]
*
* polyCoef[256, 257, ... 263] are for special case of sample 16 (out of 0)
* see PolyphaseStereo() and PolyphaseMono()
*/
const int polyCoef[264] PROGMEM = {
/* shuffled vs. original from 0, 1, ... 15 to 0, 15, 2, 13, ... 14, 1 */
0x00000000, 0x00000074, 0x00000354, 0x0000072c, 0x00001fd4, 0x00005084, 0x000066b8, 0x000249c4,
0x00049478, 0xfffdb63c, 0x000066b8, 0xffffaf7c, 0x00001fd4, 0xfffff8d4, 0x00000354, 0xffffff8c,
0xfffffffc, 0x00000068, 0x00000368, 0x00000644, 0x00001f40, 0x00004ad0, 0x00005d1c, 0x00022ce0,
0x000493c0, 0xfffd9960, 0x00006f78, 0xffffa9cc, 0x0000203c, 0xfffff7e4, 0x00000340, 0xffffff84,
0xfffffffc, 0x00000060, 0x00000378, 0x0000056c, 0x00001e80, 0x00004524, 0x000052a0, 0x00020ffc,
0x000491a0, 0xfffd7ca0, 0x00007760, 0xffffa424, 0x00002080, 0xfffff6ec, 0x00000328, 0xffffff74,
0xfffffffc, 0x00000054, 0x00000384, 0x00000498, 0x00001d94, 0x00003f7c, 0x00004744, 0x0001f32c,
0x00048e18, 0xfffd6008, 0x00007e70, 0xffff9e8c, 0x0000209c, 0xfffff5ec, 0x00000310, 0xffffff68,
0xfffffffc, 0x0000004c, 0x0000038c, 0x000003d0, 0x00001c78, 0x000039e4, 0x00003b00, 0x0001d680,
0x00048924, 0xfffd43ac, 0x000084b0, 0xffff990c, 0x00002094, 0xfffff4e4, 0x000002f8, 0xffffff5c,
0xfffffffc, 0x00000044, 0x00000390, 0x00000314, 0x00001b2c, 0x0000345c, 0x00002ddc, 0x0001ba04,
0x000482d0, 0xfffd279c, 0x00008a20, 0xffff93a4, 0x0000206c, 0xfffff3d4, 0x000002dc, 0xffffff4c,
0xfffffffc, 0x00000040, 0x00000390, 0x00000264, 0x000019b0, 0x00002ef0, 0x00001fd4, 0x00019dc8,
0x00047b1c, 0xfffd0be8, 0x00008ecc, 0xffff8e64, 0x00002024, 0xfffff2c0, 0x000002c0, 0xffffff3c,
0xfffffff8, 0x00000038, 0x0000038c, 0x000001bc, 0x000017fc, 0x0000299c, 0x000010e8, 0x000181d8,
0x0004720c, 0xfffcf09c, 0x000092b4, 0xffff894c, 0x00001fc0, 0xfffff1a4, 0x000002a4, 0xffffff2c,
0xfffffff8, 0x00000034, 0x00000380, 0x00000120, 0x00001618, 0x00002468, 0x00000118, 0x00016644,
0x000467a4, 0xfffcd5cc, 0x000095e0, 0xffff8468, 0x00001f44, 0xfffff084, 0x00000284, 0xffffff18,
0xfffffff8, 0x0000002c, 0x00000374, 0x00000090, 0x00001400, 0x00001f58, 0xfffff068, 0x00014b14,
0x00045bf0, 0xfffcbb88, 0x00009858, 0xffff7fbc, 0x00001ea8, 0xffffef60, 0x00000268, 0xffffff04,
0xfffffff8, 0x00000028, 0x0000035c, 0x00000008, 0x000011ac, 0x00001a70, 0xffffded8, 0x00013058,
0x00044ef8, 0xfffca1d8, 0x00009a1c, 0xffff7b54, 0x00001dfc, 0xffffee3c, 0x0000024c, 0xfffffef0,
0xfffffff4, 0x00000024, 0x00000340, 0xffffff8c, 0x00000f28, 0x000015b0, 0xffffcc70, 0x0001161c,
0x000440bc, 0xfffc88d8, 0x00009b3c, 0xffff7734, 0x00001d38, 0xffffed18, 0x0000022c, 0xfffffedc,
0xfffffff4, 0x00000020, 0x00000320, 0xffffff1c, 0x00000c68, 0x0000111c, 0xffffb92c, 0x0000fc6c,
0x00043150, 0xfffc708c, 0x00009bb8, 0xffff7368, 0x00001c64, 0xffffebf4, 0x00000210, 0xfffffec4,
0xfffffff0, 0x0000001c, 0x000002f4, 0xfffffeb4, 0x00000974, 0x00000cb8, 0xffffa518, 0x0000e350,
0x000420b4, 0xfffc5908, 0x00009b9c, 0xffff6ff4, 0x00001b7c, 0xffffead0, 0x000001f4, 0xfffffeac,
0xfffffff0, 0x0000001c, 0x000002c4, 0xfffffe58, 0x00000648, 0x00000884, 0xffff9038, 0x0000cad0,
0x00040ef8, 0xfffc425c, 0x00009af0, 0xffff6ce0, 0x00001a88, 0xffffe9b0, 0x000001d4, 0xfffffe94,
0xffffffec, 0x00000018, 0x0000028c, 0xfffffe04, 0x000002e4, 0x00000480, 0xffff7a90, 0x0000b2fc,
0x0003fc28, 0xfffc2c90, 0x000099b8, 0xffff6a3c, 0x00001988, 0xffffe898, 0x000001bc, 0xfffffe7c,
0x000001a0, 0x0000187c, 0x000097fc, 0x0003e84c, 0xffff6424, 0xffffff4c, 0x00000248, 0xffffffec,
};
#pragma GCC diagnostic pop

View File

@@ -1,484 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: noiseless.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* noiseless.c - decode channel info, scalefactors, quantized coefficients,
* scalefactor band codebook, and TNS coefficients from bitstream
**************************************************************************************/
#include "coder.h"
//#include "profile.h"
//#define PROFILE_START(x)
//#define PROFILE_END()
/**************************************************************************************
* Function: DecodeICSInfo
*
* Description: decode individual channel stream info
*
* Inputs: BitStreamInfo struct pointing to start of ICS info
* (14496-3, table 4.4.6)
* sample rate index
*
* Outputs: updated icsInfo struct
*
* Return: none
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ void DecodeICSInfo(BitStreamInfo *bsi, ICSInfo *icsInfo, int sampRateIdx)
{
int sfb, g, mask;
icsInfo->icsResBit = GetBits(bsi, 1);
icsInfo->winSequence = GetBits(bsi, 2);
icsInfo->winShape = GetBits(bsi, 1);
if (icsInfo->winSequence == 2) {
/* short block */
icsInfo->maxSFB = GetBits(bsi, 4);
icsInfo->sfGroup = GetBits(bsi, 7);
icsInfo->numWinGroup = 1;
icsInfo->winGroupLen[0] = 1;
mask = 0x40; /* start with bit 6 */
for (g = 0; g < 7; g++) {
if (icsInfo->sfGroup & mask) {
icsInfo->winGroupLen[icsInfo->numWinGroup - 1]++;
} else {
icsInfo->numWinGroup++;
icsInfo->winGroupLen[icsInfo->numWinGroup - 1] = 1;
}
mask >>= 1;
}
} else {
/* long block */
icsInfo->maxSFB = GetBits(bsi, 6);
icsInfo->predictorDataPresent = GetBits(bsi, 1);
if (icsInfo->predictorDataPresent) {
icsInfo->predictorReset = GetBits(bsi, 1);
if (icsInfo->predictorReset)
icsInfo->predictorResetGroupNum = GetBits(bsi, 5);
for (sfb = 0; sfb < MIN(icsInfo->maxSFB, predSFBMax[sampRateIdx]); sfb++)
icsInfo->predictionUsed[sfb] = GetBits(bsi, 1);
}
icsInfo->numWinGroup = 1;
icsInfo->winGroupLen[0] = 1;
}
}
/**************************************************************************************
* Function: DecodeSectionData
*
* Description: decode section data (scale factor band groupings and
* associated Huffman codebooks)
*
* Inputs: BitStreamInfo struct pointing to start of ICS info
* (14496-3, table 4.4.25)
* window sequence (short or long blocks)
* number of window groups (1 for long blocks, 1-8 for short blocks)
* max coded scalefactor band
*
* Outputs: index of Huffman codebook for each scalefactor band in each section
*
* Return: none
*
* Notes: sectCB, sectEnd, sfbCodeBook, ordered by window groups for short blocks
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void DecodeSectionData(BitStreamInfo *bsi, int winSequence, int numWinGrp, int maxSFB, unsigned char *sfbCodeBook)
{
int g, cb, sfb;
int sectLen, sectLenBits, sectLenIncr, sectEscapeVal;
sectLenBits = (winSequence == 2 ? 3 : 5);
sectEscapeVal = (1 << sectLenBits) - 1;
for (g = 0; g < numWinGrp; g++) {
sfb = 0;
while (sfb < maxSFB) {
cb = GetBits(bsi, 4); /* next section codebook */
sectLen = 0;
do {
sectLenIncr = GetBits(bsi, sectLenBits);
sectLen += sectLenIncr;
} while (sectLenIncr == sectEscapeVal);
sfb += sectLen;
while (sectLen--)
*sfbCodeBook++ = (unsigned char)cb;
}
ASSERT(sfb == maxSFB);
}
}
/**************************************************************************************
* Function: DecodeOneScaleFactor
*
* Description: decode one scalefactor using scalefactor Huffman codebook
*
* Inputs: BitStreamInfo struct pointing to start of next coded scalefactor
*
* Outputs: updated BitstreamInfo struct
*
* Return: one decoded scalefactor, including index_offset of -60
**************************************************************************************/
static int DecodeOneScaleFactor(BitStreamInfo *bsi)
{
int nBits, val;
unsigned int bitBuf;
/* decode next scalefactor from bitstream */
bitBuf = GetBitsNoAdvance(bsi, huffTabScaleFactInfo.maxBits) << (32 - huffTabScaleFactInfo.maxBits);
//PROFILE_START("DecodeHuffmanScalar");
nBits = DecodeHuffmanScalar(huffTabScaleFact, &huffTabScaleFactInfo, bitBuf, &val);
AdvanceBitstream(bsi, nBits);
//PROFILE_END();
return val;
}
/**************************************************************************************
* Function: DecodeScaleFactors
*
* Description: decode scalefactors, PNS energy, and intensity stereo weights
*
* Inputs: BitStreamInfo struct pointing to start of ICS info
* (14496-3, table 4.4.26)
* number of window groups (1 for long blocks, 1-8 for short blocks)
* max coded scalefactor band
* global gain (starting value for differential scalefactor coding)
* index of Huffman codebook for each scalefactor band in each section
*
* Outputs: decoded scalefactor for each section
*
* Return: none
*
* Notes: sfbCodeBook, scaleFactors ordered by window groups for short blocks
* for section with codebook 13, scaleFactors buffer has decoded PNS
* energy instead of regular scalefactor
* for section with codebook 14 or 15, scaleFactors buffer has intensity
* stereo weight instead of regular scalefactor
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void DecodeScaleFactors(BitStreamInfo *bsi, int numWinGrp, int maxSFB, int globalGain,
unsigned char *sfbCodeBook, short *scaleFactors)
{
int g, sfbCB, nrg, npf, val, sf, is;
/* starting values for differential coding */
sf = globalGain;
is = 0;
nrg = globalGain - 90 - 256;
npf = 1;
for (g = 0; g < numWinGrp * maxSFB; g++) {
sfbCB = *sfbCodeBook++;
if (sfbCB == 14 || sfbCB == 15) {
/* intensity stereo - differential coding */
val = DecodeOneScaleFactor(bsi);
is += val;
*scaleFactors++ = (short)is;
} else if (sfbCB == 13) {
/* PNS - first energy is directly coded, rest are Huffman coded (npf = noise_pcm_flag) */
if (npf) {
val = GetBits(bsi, 9);
npf = 0;
} else {
val = DecodeOneScaleFactor(bsi);
}
nrg += val;
*scaleFactors++ = (short)nrg;
} else if (sfbCB >= 1 && sfbCB <= 11) {
/* regular (non-zero) region - differential coding */
val = DecodeOneScaleFactor(bsi);
sf += val;
*scaleFactors++ = (short)sf;
} else {
/* inactive scalefactor band if codebook 0 */
*scaleFactors++ = 0;
}
}
}
/**************************************************************************************
* Function: DecodePulseInfo
*
* Description: decode pulse information
*
* Inputs: BitStreamInfo struct pointing to start of pulse info
* (14496-3, table 4.4.7)
*
* Outputs: updated PulseInfo struct
*
* Return: none
**************************************************************************************/
/* __attribute__ ((section (".data"))) */ static void DecodePulseInfo(BitStreamInfo *bsi, PulseInfo *pi)
{
int i;
pi->numPulse = GetBits(bsi, 2) + 1; /* add 1 here */
pi->startSFB = GetBits(bsi, 6);
for (i = 0; i < pi->numPulse; i++) {
pi->offset[i] = GetBits(bsi, 5);
pi->amp[i] = GetBits(bsi, 4);
}
}
/**************************************************************************************
* Function: DecodeTNSInfo
*
* Description: decode TNS filter information
*
* Inputs: BitStreamInfo struct pointing to start of TNS info
* (14496-3, table 4.4.27)
* window sequence (short or long blocks)
*
* Outputs: updated TNSInfo struct
* buffer of decoded (signed) TNS filter coefficients
*
* Return: none
**************************************************************************************/
static const signed char sgnMask[3] = {0x02, 0x04, 0x08};
static const signed char negMask[3] = {~0x03, ~0x07, ~0x0f};
static void DecodeTNSInfo(BitStreamInfo *bsi, int winSequence, TNSInfo *ti, signed char *tnsCoef)
{
int i, w, f, coefBits, compress;
signed char c, s, n;
unsigned char *filtLength, *filtOrder, *filtDir;
filtLength = ti->length;
filtOrder = ti->order;
filtDir = ti->dir;
if (winSequence == 2) {
/* short blocks */
for (w = 0; w < NWINDOWS_SHORT; w++) {
ti->numFilt[w] = GetBits(bsi, 1);
if (ti->numFilt[w]) {
ti->coefRes[w] = GetBits(bsi, 1) + 3;
*filtLength = GetBits(bsi, 4);
*filtOrder = GetBits(bsi, 3);
if (*filtOrder) {
*filtDir++ = GetBits(bsi, 1);
compress = GetBits(bsi, 1);
coefBits = (int)ti->coefRes[w] - compress; /* 2, 3, or 4 */
s = sgnMask[coefBits - 2];
n = negMask[coefBits - 2];
for (i = 0; i < *filtOrder; i++) {
c = GetBits(bsi, coefBits);
if (c & s) c |= n;
*tnsCoef++ = c;
}
}
filtLength++;
filtOrder++;
}
}
} else {
/* long blocks */
ti->numFilt[0] = GetBits(bsi, 2);
if (ti->numFilt[0])
ti->coefRes[0] = GetBits(bsi, 1) + 3;
for (f = 0; f < ti->numFilt[0]; f++) {
*filtLength = GetBits(bsi, 6);
*filtOrder = GetBits(bsi, 5);
if (*filtOrder) {
*filtDir++ = GetBits(bsi, 1);
compress = GetBits(bsi, 1);
coefBits = (int)ti->coefRes[0] - compress; /* 2, 3, or 4 */
s = sgnMask[coefBits - 2];
n = negMask[coefBits - 2];
for (i = 0; i < *filtOrder; i++) {
c = GetBits(bsi, coefBits);
if (c & s) c |= n;
*tnsCoef++ = c;
}
}
filtLength++;
filtOrder++;
}
}
}
/* bitstream field lengths for gain control data:
* gainBits[winSequence][0] = maxWindow (how many gain windows there are)
* gainBits[winSequence][1] = locBitsZero (bits for alocCode if window == 0)
* gainBits[winSequence][2] = locBits (bits for alocCode if window != 0)
*/
static const unsigned char gainBits[4][3] = {
{1, 5, 5}, /* long */
{2, 4, 2}, /* start */
{8, 2, 2}, /* short */
{2, 4, 5}, /* stop */
};
/**************************************************************************************
* Function: DecodeGainControlInfo
*
* Description: decode gain control information (SSR profile only)
*
* Inputs: BitStreamInfo struct pointing to start of gain control info
* (14496-3, table 4.4.12)
* window sequence (short or long blocks)
*
* Outputs: updated GainControlInfo struct
*
* Return: none
**************************************************************************************/
static void DecodeGainControlInfo(BitStreamInfo *bsi, int winSequence, GainControlInfo *gi)
{
int bd, wd, ad;
int locBits, locBitsZero, maxWin;
gi->maxBand = GetBits(bsi, 2);
maxWin = (int)gainBits[winSequence][0];
locBitsZero = (int)gainBits[winSequence][1];
locBits = (int)gainBits[winSequence][2];
for (bd = 1; bd <= gi->maxBand; bd++) {
for (wd = 0; wd < maxWin; wd++) {
gi->adjNum[bd][wd] = GetBits(bsi, 3);
for (ad = 0; ad < gi->adjNum[bd][wd]; ad++) {
gi->alevCode[bd][wd][ad] = GetBits(bsi, 4);
gi->alocCode[bd][wd][ad] = GetBits(bsi, (wd == 0 ? locBitsZero : locBits));
}
}
}
}
/**************************************************************************************
* Function: DecodeICS
*
* Description: decode individual channel stream
*
* Inputs: platform specific info struct
* BitStreamInfo struct pointing to start of individual channel stream
* (14496-3, table 4.4.24)
* index of current channel
*
* Outputs: updated section data, scale factor data, pulse data, TNS data,
* and gain control data
*
* Return: none
**************************************************************************************/
static void DecodeICS(PSInfoBase *psi, BitStreamInfo *bsi, int ch)
{
int globalGain;
ICSInfo *icsInfo;
PulseInfo *pi;
TNSInfo *ti;
GainControlInfo *gi;
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
globalGain = GetBits(bsi, 8);
if (!psi->commonWin)
DecodeICSInfo(bsi, icsInfo, psi->sampRateIdx);
DecodeSectionData(bsi, icsInfo->winSequence, icsInfo->numWinGroup, icsInfo->maxSFB, psi->sfbCodeBook[ch]);
DecodeScaleFactors(bsi, icsInfo->numWinGroup, icsInfo->maxSFB, globalGain, psi->sfbCodeBook[ch], psi->scaleFactors[ch]);
pi = &psi->pulseInfo[ch];
pi->pulseDataPresent = GetBits(bsi, 1);
if (pi->pulseDataPresent)
DecodePulseInfo(bsi, pi);
ti = &psi->tnsInfo[ch];
ti->tnsDataPresent = GetBits(bsi, 1);
if (ti->tnsDataPresent)
DecodeTNSInfo(bsi, icsInfo->winSequence, ti, ti->coef);
gi = &psi->gainControlInfo[ch];
gi->gainControlDataPresent = GetBits(bsi, 1);
if (gi->gainControlDataPresent)
DecodeGainControlInfo(bsi, icsInfo->winSequence, gi);
}
/**************************************************************************************
* Function: DecodeNoiselessData
*
* Description: decode noiseless data (side info and transform coefficients)
*
* Inputs: valid AACDecInfo struct
* double pointer to buffer pointing to start of individual channel stream
* (14496-3, table 4.4.24)
* pointer to bit offset
* pointer to number of valid bits remaining in buf
* index of current channel
*
* Outputs: updated global gain, section data, scale factor data, pulse data,
* TNS data, gain control data, and spectral data
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int DecodeNoiselessData(AACDecInfo *aacDecInfo, unsigned char **buf, int *bitOffset, int *bitsAvail, int ch)
{
int bitsUsed;
BitStreamInfo bsi;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
SetBitstreamPointer(&bsi, (*bitsAvail+7) >> 3, *buf);
GetBits(&bsi, *bitOffset);
DecodeICS(psi, &bsi, ch);
if (icsInfo->winSequence == 2)
DecodeSpectrumShort(psi, &bsi, ch);
else
DecodeSpectrumLong(psi, &bsi, ch);
bitsUsed = CalcBitsUsed(&bsi, *buf, *bitOffset);
*buf += ((bitsUsed + *bitOffset) >> 3);
*bitOffset = ((bitsUsed + *bitOffset) & 0x07);
*bitsAvail -= bitsUsed;
aacDecInfo->sbDeinterleaveReqd[ch] = 0;
aacDecInfo->tnsUsed |= psi->tnsInfo[ch].tnsDataPresent; /* set flag if TNS used for any channel */
return ERR_AAC_NONE;
}

View File

@@ -1,357 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: pns.c,v 1.2 2005/03/10 17:01:56 jrecker 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
*
* pns.c - perceptual noise substitution
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: Get32BitVal
*
* Description: generate 32-bit unsigned random number
*
* Inputs: last number calculated (seed, first time through)
*
* Outputs: new number, saved in *last
*
* Return: 32-bit number, uniformly distributed between [0, 2^32)
*
* Notes: uses simple linear congruential generator
**************************************************************************************/
static unsigned int Get32BitVal(unsigned int *last)
{
unsigned int r = *last;
/* use same coefs as MPEG reference code (classic LCG)
* use unsigned multiply to force reliable wraparound behavior in C (mod 2^32)
*/
r = (1664525U * r) + 1013904223U;
*last = r;
return r;
}
#define NUM_ITER_INVSQRT 4
#define X0_COEF_2 0xc0000000 /* Q29: -2.0 */
#define X0_OFF_2 0x60000000 /* Q29: 3.0 */
#define Q26_3 0x0c000000 /* Q26: 3.0 */
/**************************************************************************************
* Function: InvRootR
*
* Description: use Newton's method to solve for x = 1/sqrt(r)
*
* Inputs: r in Q30 format, range = [0.25, 1] (normalize inputs to this range)
*
* Outputs: none
*
* Return: x = Q29, range = (1, 2)
*
* Notes: guaranteed to converge and not overflow for any r in this range
*
* xn+1 = xn - f(xn)/f'(xn)
* f(x) = 1/sqrt(r) - x = 0 (find root)
* = 1/x^2 - r
* f'(x) = -2/x^3
*
* so xn+1 = xn/2 * (3 - r*xn^2)
*
* NUM_ITER_INVSQRT = 3, maxDiff = 1.3747e-02
* NUM_ITER_INVSQRT = 4, maxDiff = 3.9832e-04
**************************************************************************************/
static int InvRootR(int r)
{
int i, xn, t;
/* use linear equation for initial guess
* x0 = -2*r + 3 (so x0 always >= correct answer in range [0.25, 1))
* xn = Q29 (at every step)
*/
xn = (MULSHIFT32(r, X0_COEF_2) << 2) + X0_OFF_2;
for (i = 0; i < NUM_ITER_INVSQRT; i++) {
t = MULSHIFT32(xn, xn); /* Q26 = Q29*Q29 */
t = Q26_3 - (MULSHIFT32(r, t) << 2); /* Q26 = Q26 - (Q31*Q26 << 1) */
xn = MULSHIFT32(xn, t) << (6 - 1); /* Q29 = (Q29*Q26 << 6), and -1 for division by 2 */
}
/* clip to range (1.0, 2.0)
* (because of rounding, this can converge to xn slightly > 2.0 when r is near 0.25)
*/
if (xn >> 30)
xn = (1 << 30) - 1;
return xn;
}
/**************************************************************************************
* Function: ScaleNoiseVector
*
* Description: apply scaling to vector of noise coefficients for one scalefactor band
*
* Inputs: unscaled coefficients
* number of coefficients in vector (one scalefactor band of coefs)
* scalefactor for this band (i.e. noise energy)
*
* Outputs: nVals coefficients in Q(FBITS_OUT_DQ_OFF)
*
* Return: guard bit mask (OR of abs value of all noise coefs)
**************************************************************************************/
static int ScaleNoiseVector(int *coef, int nVals, int sf)
{
/* pow(2, i/4.0) for i = [0,1,2,3], format = Q30 */
static const int pow14[4] PROGMEM = {
0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65
};
int i, c, spec, energy, sq, scalef, scalei, invSqrtEnergy, z, gbMask;
energy = 0;
for (i = 0; i < nVals; i++) {
spec = coef[i];
/* max nVals = max SFB width = 96, so energy can gain < 2^7 bits in accumulation */
sq = (spec * spec) >> 8; /* spec*spec range = (-2^30, 2^30) */
energy += sq;
}
/* unless nVals == 1 (or the number generator is broken...), this should not happen */
if (energy == 0)
return 0; /* coef[i] must = 0 for i = [0, nVals-1], so gbMask = 0 */
/* pow(2, sf/4) * pow(2, FBITS_OUT_DQ_OFF) */
scalef = pow14[sf & 0x3];
scalei = (sf >> 2) + FBITS_OUT_DQ_OFF;
/* energy has implied factor of 2^-8 since we shifted the accumulator
* normalize energy to range [0.25, 1.0), calculate 1/sqrt(1), and denormalize
* i.e. divide input by 2^(30-z) and convert to Q30
* output of 1/sqrt(i) now has extra factor of 2^((30-z)/2)
* for energy > 0, z is an even number between 0 and 28
* final scaling of invSqrtEnergy:
* 2^(15 - z/2) to compensate for implicit 2^(30-z) factor in input
* +4 to compensate for implicit 2^-8 factor in input
*/
z = CLZ(energy) - 2; /* energy has at least 2 leading zeros (see acc loop) */
z &= 0xfffffffe; /* force even */
invSqrtEnergy = InvRootR(energy << z); /* energy << z must be in range [0x10000000, 0x40000000] */
scalei -= (15 - z/2 + 4); /* nInt = 1/sqrt(energy) in Q29 */
/* normalize for final scaling */
z = CLZ(invSqrtEnergy) - 1;
invSqrtEnergy <<= z;
scalei -= (z - 3 - 2); /* -2 for scalef, z-3 for invSqrtEnergy */
scalef = MULSHIFT32(scalef, invSqrtEnergy); /* scalef (input) = Q30, invSqrtEnergy = Q29 * 2^z */
gbMask = 0;
if (scalei < 0) {
scalei = -scalei;
if (scalei > 31)
scalei = 31;
for (i = 0; i < nVals; i++) {
c = MULSHIFT32(coef[i], scalef) >> scalei;
gbMask |= FASTABS(c);
coef[i] = c;
}
} else {
/* for scalei <= 16, no clipping possible (coef[i] is < 2^15 before scaling)
* for scalei > 16, just saturate exponent (rare)
* scalef is close to full-scale (since we normalized invSqrtEnergy)
* remember, we are just producing noise here
*/
if (scalei > 16)
scalei = 16;
for (i = 0; i < nVals; i++) {
c = MULSHIFT32(coef[i] << scalei, scalef);
coef[i] = c;
gbMask |= FASTABS(c);
}
}
return gbMask;
}
/**************************************************************************************
* Function: GenerateNoiseVector
*
* Description: create vector of noise coefficients for one scalefactor band
*
* Inputs: seed for number generator
* number of coefficients to generate
*
* Outputs: buffer of nVals coefficients, range = [-2^15, 2^15)
* updated seed for number generator
*
* Return: none
**************************************************************************************/
static void GenerateNoiseVector(int *coef, int *last, int nVals)
{
int i;
for (i = 0; i < nVals; i++)
coef[i] = ((signed int)Get32BitVal((unsigned int *)last)) >> 16;
}
/**************************************************************************************
* Function: CopyNoiseVector
*
* Description: copy vector of noise coefficients for one scalefactor band from L to R
*
* Inputs: buffer of left coefficients
* number of coefficients to copy
*
* Outputs: buffer of right coefficients
*
* Return: none
**************************************************************************************/
static void CopyNoiseVector(int *coefL, int *coefR, int nVals)
{
int i;
for (i = 0; i < nVals; i++)
coefR[i] = coefL[i];
}
/**************************************************************************************
* Function: PNS
*
* Description: apply perceptual noise substitution, if enabled (MPEG-4 only)
*
* Inputs: valid AACDecInfo struct
* index of current channel
*
* Outputs: shaped noise in scalefactor bands where PNS is active
* updated minimum guard bit count for this channel
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
int PNS(AACDecInfo *aacDecInfo, int ch)
{
int gp, sfb, win, width, nSamps, gb, gbMask;
int *coef;
const /*short*/ int *sfbTab;
unsigned char *sfbCodeBook;
short *scaleFactors;
int msMaskOffset, checkCorr, genNew;
unsigned char msMask;
unsigned char *msMaskPtr;
PSInfoBase *psi;
ICSInfo *icsInfo;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
if (!psi->pnsUsed[ch])
return 0;
if (icsInfo->winSequence == 2) {
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
nSamps = NSAMPS_SHORT;
} else {
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
nSamps = NSAMPS_LONG;
}
coef = psi->coef[ch];
sfbCodeBook = psi->sfbCodeBook[ch];
scaleFactors = psi->scaleFactors[ch];
checkCorr = (aacDecInfo->currBlockID == AAC_ID_CPE && psi->commonWin == 1 ? 1 : 0);
gbMask = 0;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
msMaskPtr = psi->msMaskBits + ((gp*icsInfo->maxSFB) >> 3);
msMaskOffset = ((gp*icsInfo->maxSFB) & 0x07);
msMask = (*msMaskPtr++) >> msMaskOffset;
for (sfb = 0; sfb < icsInfo->maxSFB; sfb++) {
width = sfbTab[sfb+1] - sfbTab[sfb];
if (sfbCodeBook[sfb] == 13) {
if (ch == 0) {
/* generate new vector, copy into ch 1 if it's possible that the channels will be correlated
* if ch 1 has PNS enabled for this SFB but it's uncorrelated (i.e. ms_used == 0),
* the copied values will be overwritten when we process ch 1
*/
GenerateNoiseVector(coef, &psi->pnsLastVal, width);
if (checkCorr && psi->sfbCodeBook[1][gp*icsInfo->maxSFB + sfb] == 13)
CopyNoiseVector(coef, psi->coef[1] + (coef - psi->coef[0]), width);
} else {
/* generate new vector if no correlation between channels */
genNew = 1;
if (checkCorr && psi->sfbCodeBook[0][gp*icsInfo->maxSFB + sfb] == 13) {
if ( (psi->msMaskPresent == 1 && (msMask & 0x01)) || psi->msMaskPresent == 2 )
genNew = 0;
}
if (genNew)
GenerateNoiseVector(coef, &psi->pnsLastVal, width);
}
gbMask |= ScaleNoiseVector(coef, width, psi->scaleFactors[ch][gp*icsInfo->maxSFB + sfb]);
}
coef += width;
/* get next mask bit (should be branchless on ARM) */
msMask >>= 1;
if (++msMaskOffset == 8) {
msMask = *msMaskPtr++;
msMaskOffset = 0;
}
}
coef += (nSamps - sfbTab[icsInfo->maxSFB]);
}
sfbCodeBook += icsInfo->maxSFB;
scaleFactors += icsInfo->maxSFB;
}
/* update guard bit count if necessary */
gb = CLZ(gbMask) - 1;
if (psi->gbCurrent[ch] > gb)
psi->gbCurrent[ch] = gb;
return 0;
}

View File

@@ -1,127 +0,0 @@
Fixed-point HE-AAC decoder
Developed by RealNetworks, 2005
===============================
Overview
--------
This module contains a high-performance HE-AAC decoder for 32-bit fixed-point
processors. The following is a summary of what is and is not supported:
Supported:
- MPEG2, MPEG4 low complexity decoding (intensity stereo, M-S, TNS, PNS)
- spectral band replication (SBR), high-quality mode
- mono, stereo, and multichannel modes
- ADTS, ADIF, and raw data block file formats
Not currently supported:
- main or SSR profile, LTP
- coupling channel elements (CCE)
- 960/1920-sample frame size
- low-power mode SBR
- downsampled (single-rate) SBR
- parametric stereo
Highlights
----------
- highly optimized for ARM processors (details in docs/ subdirectory)
- reference x86 implementation
- C and assembly code only (C++ not required for codec library)
- reentrant, statically linkable
- low memory (details in docs/ subdirectory)
- option to use Intel Integrated Performance Primitives (details below)
Supported platforms and toolchains
----------------------------------
This codec should run on any 32-bit fixed-point processor which can perform a full 32x32-bit
multiply (providing a 64-bit result). The following processors and toolchains are supported:
- x86, Microsoft Visual C++
- x86, GNU toolchain (gcc)
- ARM, ARM Developer Suite (ADS)
- ARM, Microsoft Embedded Visual C++
- ARM, GNU toolchain (gcc)
ARM refers to any processor supporting ARM architecture v.4 or above. Thumb is not required.
Generally ADS produces the fastest code. EVC 3 does not support inline assembly code for
ARM targets, so calls to MULSHIFT32 (smull on ARM) are left as function calls. This incurs
a significant performance penalty. For the fastest code on targets which do not normally use
ADS consider compiling with ADS, using the -S option to output assembly code, and
feeding this assembly code to the assembler of your choice. This might require some
syntax changes in the .S file.
Adding support for a new processor is fairly simple. Simply add a new block to the file
real/assembly.h which implements the required inline assembly functions for your processor.
Something like
...
#elif defined NEW_PROCESSOR
/* you implement MULSHIFT32() and so forth */
#else
#error Unsupported platform in assembly.h
#endif
Optionally you can rewrite or add assembly language files optimized for your platform. Note
that many of the algorithms are designed for an ARM-type processor, so performance of the
unmodified C code might be noticeably worse on other architectures.
Adding support for a new toolchain is straightforward. Use the sample projects or the
Helix makefiles as a template for which source files to include.
Multichannel
------------
For multichannel, just set AAC_MAX_NCHANS in pub/aacdec.h to the desired max number
of channels (default = 2) and recompile. This increases RAM usage since more memory
is required to save state for multiple channels. See docs/memory.xls for details.
Directory structure
-------------------
fixpt/ platform-independent code and tables, public API
fixpt/docs memory and CPU usage figures, callgraphs
fixpt/hxwrap Helix wrapper code and makefiles
fixpt/ipp source code which uses IPP for decoding (see the "IPP" section below)
fixpt/pub public header files
fixpt/real source code for RealNetworks' AAC decoder
fixpt/testwrap sample code to build a command-line test application
Code organization
-----------------
fixpt/
aacdec.c main decode functions, exports C-only API
aactabs.c common tables used by all implementations
fixpt/pub/
aaccommon.h low-level codec API which aacdec.c calls
aacdec.h high-level codec API which applications call
statname.h symbols which get name-mangled by C preprocessor to allow static linking
fixpt/ipp source code for wrapper files which link in IPP libraries
fixpt/real full source code for RealNetworks AAC decoder, including SBR
fixpt/real/asm optimized assembly code files for certain platforms
To build an AAC decoder library, you'll need to compile the top-level files and EITHER
real/*.c OR ipp/*.c and the appropriate IPP library.
Decoder using Real code: aacdec.c + aactabs.c + real/*.c + real/asm/[platform]/*.s (if necessary)
Decoder using IPP code: aacdec.c + aactabs.c + ipp/*.c + ippac*.lib
IPP
---
For certain platforms Intel<65> has created highly-optimized object code libraries of DSP
routines. These are called the Intel<65> Integrated Performance Primitives (IPP). If IPP
libraries are available for a platform, this AAC decoder can link them in and use them
instead of the RealNetworks source code. To use IPP, you still need to build the top-level
files (aacdec.c, aactabs.c). You also build the files in ipp/*.c. These are just thin
wrappers which provide the glue logic between the top-level decode functions in
aacdec.c and the optimized DSP primitives in the IPP libraries. IPP libraries are not
included in this module. You must obtain them WITH A LICENSE directly from Intel.
Further info on the latest versions of IPP (as of the date of this readme) is available
from the URL below:
http://www.intel.com/software/products/ipp/
This site explains how to obtain IPP and the terms under which IPP libraries may be used.
The code in this module is merely wrapper code which calls IPP functions. You are fully
responsible for adhering to the license agreement under which you obtain the IPP
libraries from Intel.
readme.txt last updated 02/25/05

View File

@@ -1,431 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbr.c,v 1.3 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
*
* sbr.c - top level functions for SBR
**************************************************************************************/
#if defined(USE_DEFAULT_STDLIB) || defined(ESP_PLATFORM)
#include <stdio.h>
#include <stdlib.h>
#else
#include "hlxclib/stdlib.h"
#endif
#include "sbr.h"
/**************************************************************************************
* Function: InitSBRState
*
* Description: initialize PSInfoSBR struct at start of stream or after flush
*
* Inputs: valid AACDecInfo struct
*
* Outputs: PSInfoSBR struct with proper initial state
*
* Return: none
**************************************************************************************/
static void InitSBRState(PSInfoSBR *psi)
{
int i, ch;
unsigned char *c;
if (!psi)
return;
/* clear SBR state structure */
c = (unsigned char *)psi;
for (i = 0; i < (int)sizeof(PSInfoSBR); i++)
*c++ = 0;
/* initialize non-zero state variables */
for (ch = 0; ch < AAC_MAX_NCHANS; ch++) {
psi->sbrChan[ch].reset = 1;
psi->sbrChan[ch].laPrev = -1;
}
}
/**************************************************************************************
* Function: InitSBR
*
* Description: initialize SBR decoder
*
* Inputs: valid AACDecInfo struct
*
* Outputs: PSInfoSBR struct to hold SBR state information
*
* Return: 0 if successful, error code (< 0) if error
*
* Note: memory allocation for SBR is only done here
**************************************************************************************/
int InitSBR(AACDecInfo *aacDecInfo)
{
PSInfoSBR *psi;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* allocate SBR state structure */
psi = (PSInfoSBR *)malloc(sizeof(PSInfoSBR));
if (!psi) {
printf("OOM in SBR, can't allocate %d bytes\n", sizeof(PSInfoSBR));
return ERR_AAC_SBR_INIT;
}
InitSBRState(psi);
aacDecInfo->psInfoSBR = psi;
return ERR_AAC_NONE;
}
int InitSBRPre(AACDecInfo *aacDecInfo, void **ptr, int *sz)
{
PSInfoSBR *psi;
if (!aacDecInfo)
return ERR_AAC_NULL_POINTER;
/* allocate SBR state structure */
psi = (PSInfoSBR *)*ptr;
*sz -= sizeof(PSInfoSBR);
if (*sz < 0) {
printf("OOM in SBR, can't allocate %d bytes\n", sizeof(PSInfoSBR));
return ERR_AAC_SBR_INIT;
}
InitSBRState(psi);
*ptr = (void*)((char*)(*ptr) + sizeof(PSInfoSBR));
aacDecInfo->psInfoSBR = psi;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: FreeSBR
*
* Description: free SBR decoder
*
* Inputs: valid AACDecInfo struct
*
* Outputs: none
*
* Return: none
*
* Note: memory deallocation for SBR is only done here
**************************************************************************************/
void FreeSBR(AACDecInfo *aacDecInfo)
{
if (aacDecInfo && aacDecInfo->psInfoSBR)
free(aacDecInfo->psInfoSBR);
return;
}
/**************************************************************************************
* Function: DecodeSBRBitstream
*
* Description: decode sideband information for SBR
*
* Inputs: valid AACDecInfo struct
* fill buffer with SBR extension block
* number of bytes in fill buffer
* base output channel (range = [0, nChans-1])
*
* Outputs: initialized state structs (SBRHdr, SBRGrid, SBRFreq, SBRChan)
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: SBR payload should be in aacDecInfo->fillBuf
* returns with no error if fill buffer is not an SBR extension block,
* or if current block is not a fill block (e.g. for LFE upsampling)
**************************************************************************************/
int DecodeSBRBitstream(AACDecInfo *aacDecInfo, int chBase)
{
int headerFlag;
BitStreamInfo bsi;
PSInfoSBR *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoSBR)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR);
if (aacDecInfo->currBlockID != AAC_ID_FIL || (aacDecInfo->fillExtType != EXT_SBR_DATA && aacDecInfo->fillExtType != EXT_SBR_DATA_CRC))
return ERR_AAC_NONE;
SetBitstreamPointer(&bsi, aacDecInfo->fillCount, aacDecInfo->fillBuf);
if (GetBits(&bsi, 4) != (unsigned int)aacDecInfo->fillExtType)
return ERR_AAC_SBR_BITSTREAM;
if (aacDecInfo->fillExtType == EXT_SBR_DATA_CRC)
psi->crcCheckWord = GetBits(&bsi, 10);
headerFlag = GetBits(&bsi, 1);
if (headerFlag) {
/* get sample rate index for output sample rate (2x base rate) */
psi->sampRateIdx = GetSampRateIdx(2 * aacDecInfo->sampRate);
if (psi->sampRateIdx < 0 || psi->sampRateIdx >= NUM_SAMPLE_RATES)
return ERR_AAC_SBR_BITSTREAM;
else if (psi->sampRateIdx >= NUM_SAMPLE_RATES_SBR)
return ERR_AAC_SBR_SINGLERATE_UNSUPPORTED;
/* reset flag = 1 if header values changed */
if (UnpackSBRHeader(&bsi, &(psi->sbrHdr[chBase])))
psi->sbrChan[chBase].reset = 1;
/* first valid SBR header should always trigger CalcFreqTables(), since psi->reset was set in InitSBR() */
if (psi->sbrChan[chBase].reset)
CalcFreqTables(&(psi->sbrHdr[chBase+0]), &(psi->sbrFreq[chBase]), psi->sampRateIdx);
/* copy and reset state to right channel for CPE */
if (aacDecInfo->prevBlockID == AAC_ID_CPE)
psi->sbrChan[chBase+1].reset = psi->sbrChan[chBase+0].reset;
}
/* if no header has been received, upsample only */
if (psi->sbrHdr[chBase].count == 0)
return ERR_AAC_NONE;
if (aacDecInfo->prevBlockID == AAC_ID_SCE) {
UnpackSBRSingleChannel(&bsi, psi, chBase);
} else if (aacDecInfo->prevBlockID == AAC_ID_CPE) {
UnpackSBRChannelPair(&bsi, psi, chBase);
} else {
return ERR_AAC_SBR_BITSTREAM;
}
ByteAlignBitstream(&bsi);
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: DecodeSBRData
*
* Description: apply SBR to one frame of PCM data
*
* Inputs: 1024 samples of decoded 32-bit PCM, before SBR
* size of input PCM samples (must be 4 bytes)
* number of fraction bits in input PCM samples
* base output channel (range = [0, nChans-1])
* initialized state structs (SBRHdr, SBRGrid, SBRFreq, SBRChan)
*
* Outputs: 2048 samples of decoded 16-bit PCM, after SBR
*
* Return: 0 if successful, error code (< 0) if error
**************************************************************************************/
int DecodeSBRData(AACDecInfo *aacDecInfo, int chBase, short *outbuf)
{
int k, l, ch, chBlock, qmfaBands, qmfsBands;
int upsampleOnly, gbIdx, gbMask;
int *inbuf;
short *outptr;
PSInfoSBR *psi;
SBRHeader *sbrHdr;
SBRGrid *sbrGrid;
SBRFreq *sbrFreq;
SBRChan *sbrChan;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoSBR)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR);
/* same header and freq tables for both channels in CPE */
sbrHdr = &(psi->sbrHdr[chBase]);
sbrFreq = &(psi->sbrFreq[chBase]);
/* upsample only if we haven't received an SBR header yet or if we have an LFE block */
if (aacDecInfo->currBlockID == AAC_ID_LFE) {
chBlock = 1;
upsampleOnly = 1;
} else if (aacDecInfo->currBlockID == AAC_ID_FIL) {
if (aacDecInfo->prevBlockID == AAC_ID_SCE)
chBlock = 1;
else if (aacDecInfo->prevBlockID == AAC_ID_CPE)
chBlock = 2;
else
return ERR_AAC_NONE;
upsampleOnly = (sbrHdr->count == 0 ? 1 : 0);
if (aacDecInfo->fillExtType != EXT_SBR_DATA && aacDecInfo->fillExtType != EXT_SBR_DATA_CRC)
return ERR_AAC_NONE;
} else {
/* ignore non-SBR blocks */
return ERR_AAC_NONE;
}
if (upsampleOnly) {
sbrFreq->kStart = 32;
sbrFreq->numQMFBands = 0;
}
for (ch = 0; ch < chBlock; ch++) {
sbrGrid = &(psi->sbrGrid[chBase + ch]);
sbrChan = &(psi->sbrChan[chBase + ch]);
if (aacDecInfo->rawSampleBuf[ch] == 0 || aacDecInfo->rawSampleBytes != 4)
return ERR_AAC_SBR_PCM_FORMAT;
inbuf = (int *)aacDecInfo->rawSampleBuf[ch];
outptr = outbuf + chBase + ch;
/* restore delay buffers (could use ring buffer or keep in temp buffer for nChans == 1) */
for (l = 0; l < HF_GEN; l++) {
for (k = 0; k < 64; k++) {
psi->XBuf[l][k][0] = psi->XBufDelay[chBase + ch][l][k][0];
psi->XBuf[l][k][1] = psi->XBufDelay[chBase + ch][l][k][1];
}
}
/* step 1 - analysis QMF */
qmfaBands = sbrFreq->kStart;
for (l = 0; l < 32; l++) {
gbMask = QMFAnalysis(inbuf + l*32, psi->delayQMFA[chBase + ch], psi->XBuf[l + HF_GEN][0],
aacDecInfo->rawSampleFBits, &(psi->delayIdxQMFA[chBase + ch]), qmfaBands);
gbIdx = ((l + HF_GEN) >> 5) & 0x01;
sbrChan->gbMask[gbIdx] |= gbMask; /* gbIdx = (0 if i < 32), (1 if i >= 32) */
}
if (upsampleOnly) {
/* no SBR - just run synthesis QMF to upsample by 2x */
qmfsBands = 32;
for (l = 0; l < 32; l++) {
/* step 4 - synthesis QMF */
QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans);
outptr += 64*aacDecInfo->nChans;
}
} else {
/* if previous frame had lower SBR starting freq than current, zero out the synthesized QMF
* bands so they aren't used as sources for patching
* after patch generation, restore from delay buffer
* can only happen after header reset
*/
for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) {
for (l = 0; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) {
psi->XBuf[l][k][0] = 0;
psi->XBuf[l][k][1] = 0;
}
}
/* step 2 - HF generation */
GenerateHighFreq(psi, sbrGrid, sbrFreq, sbrChan, ch);
/* restore SBR bands that were cleared before patch generation (time slots 0, 1 no longer needed) */
for (k = sbrFreq->kStartPrev; k < sbrFreq->kStart; k++) {
for (l = HF_ADJ; l < sbrGrid->envTimeBorder[0] + HF_ADJ; l++) {
psi->XBuf[l][k][0] = psi->XBufDelay[chBase + ch][l][k][0];
psi->XBuf[l][k][1] = psi->XBufDelay[chBase + ch][l][k][1];
}
}
/* step 3 - HF adjustment */
AdjustHighFreq(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch);
/* step 4 - synthesis QMF */
qmfsBands = sbrFreq->kStartPrev + sbrFreq->numQMFBandsPrev;
for (l = 0; l < sbrGrid->envTimeBorder[0]; l++) {
/* if new envelope starts mid-frame, use old settings until start of first envelope in this frame */
QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans);
outptr += 64*aacDecInfo->nChans;
}
qmfsBands = sbrFreq->kStart + sbrFreq->numQMFBands;
for ( ; l < 32; l++) {
/* use new settings for rest of frame (usually the entire frame, unless the first envelope starts mid-frame) */
QMFSynthesis(psi->XBuf[l + HF_ADJ][0], psi->delayQMFS[chBase + ch], &(psi->delayIdxQMFS[chBase + ch]), qmfsBands, outptr, aacDecInfo->nChans);
outptr += 64*aacDecInfo->nChans;
}
}
/* save delay */
for (l = 0; l < HF_GEN; l++) {
for (k = 0; k < 64; k++) {
psi->XBufDelay[chBase + ch][l][k][0] = psi->XBuf[l+32][k][0];
psi->XBufDelay[chBase + ch][l][k][1] = psi->XBuf[l+32][k][1];
}
}
sbrChan->gbMask[0] = sbrChan->gbMask[1];
sbrChan->gbMask[1] = 0;
if (sbrHdr->count > 0)
sbrChan->reset = 0;
}
sbrFreq->kStartPrev = sbrFreq->kStart;
sbrFreq->numQMFBandsPrev = sbrFreq->numQMFBands;
if (aacDecInfo->nChans > 0 && (chBase + ch) == aacDecInfo->nChans)
psi->frameCount++;
return ERR_AAC_NONE;
}
/**************************************************************************************
* Function: FlushCodecSBR
*
* Description: flush internal SBR codec state (after seeking, for example)
*
* Inputs: valid AACDecInfo struct
*
* Outputs: updated state variables for SBR
*
* Return: 0 if successful, error code (< 0) if error
*
* Notes: SBR is heavily dependent on state from previous frames
* (e.g. delta coded scalefactors, previous envelope boundaries, etc.)
* On flush, we reset everything as if SBR had just been initialized
* for the first time. This triggers "upsample-only" mode until
* the first valid SBR header is received. Then SBR starts as usual.
**************************************************************************************/
int FlushCodecSBR(AACDecInfo *aacDecInfo)
{
PSInfoSBR *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoSBR)
return ERR_AAC_NULL_POINTER;
psi = (PSInfoSBR *)(aacDecInfo->psInfoSBR);
InitSBRState(psi);
return 0;
}

View File

@@ -1,383 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbr.h,v 1.2 2005/05/20 18:05:41 jrecker 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
*
* sbr.h - definitions of platform-specific SBR data structures, functions, and tables
**************************************************************************************/
#ifndef _SBR_H
#define _SBR_H
#include "aaccommon.h"
#include "bitstream.h"
#ifndef ASSERT
#if defined(_WIN32) && defined(_M_IX86) && (defined (_DEBUG) || defined (REL_ENABLE_ASSERTS))
#define ASSERT(x) if (!(x)) __asm int 3;
#else
#define ASSERT(x) /* do nothing */
#endif
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#define NUM_TIME_SLOTS 16
#define SAMPLES_PER_SLOT 2 /* RATE in spec */
#define NUM_SAMPLE_RATES_SBR 9 /* downsampled (single-rate) mode unsupported, so only use Fs_sbr >= 16 kHz */
#define MAX_NUM_ENV 5
#define MAX_NUM_NOISE_FLOORS 2
#define MAX_NUM_NOISE_FLOOR_BANDS 5 /* max Nq, see 4.6.18.3.6 */
#define MAX_NUM_PATCHES 5
#define MAX_NUM_SMOOTH_COEFS 5
#define HF_GEN 8
#define HF_ADJ 2
#define MAX_QMF_BANDS 48 /* max QMF subbands covered by SBR (4.6.18.3.6) */
#define FBITS_IN_QMFA 14
#define FBITS_LOST_QMFA (1 + 2 + 3 + 2 + 1) /* 1 from cTab, 2 in premul, 3 in FFT, 2 in postmul, 1 for implicit scaling by 2.0 */
#define FBITS_OUT_QMFA (FBITS_IN_QMFA - FBITS_LOST_QMFA)
#define MIN_GBITS_IN_QMFS 2
#define FBITS_IN_QMFS FBITS_OUT_QMFA
#define FBITS_LOST_DCT4_64 (2 + 3 + 2) /* 2 in premul, 3 in FFT, 2 in postmul */
#define FBITS_OUT_DQ_ENV 29 /* dequantized env scalefactors are Q(29 - envDataDequantScale) */
#define FBITS_OUT_DQ_NOISE 24 /* range of Q_orig = [2^-24, 2^6] */
#define NOISE_FLOOR_OFFSET 6
/* see comments in ApplyBoost() */
#define FBITS_GLIM_BOOST 24
#define FBITS_QLIM_BOOST 14
#define MAX_HUFF_BITS 20
#define NUM_QMF_DELAY_BUFS 10
#define DELAY_SAMPS_QMFA (NUM_QMF_DELAY_BUFS * 32)
#define DELAY_SAMPS_QMFS (NUM_QMF_DELAY_BUFS * 128)
/* additional external symbols to name-mangle for static linking */
#define FFT32C STATNAME(FFT32C)
#define CalcFreqTables STATNAME(CalcFreqTables)
#define AdjustHighFreq STATNAME(AdjustHighFreq)
#define GenerateHighFreq STATNAME(GenerateHighFreq)
#define DecodeSBREnvelope STATNAME(DecodeSBREnvelope)
#define DecodeSBRNoise STATNAME(DecodeSBRNoise)
#define UncoupleSBREnvelope STATNAME(UncoupleSBREnvelope)
#define UncoupleSBRNoise STATNAME(UncoupleSBRNoise)
#define InvRNormalized STATNAME(InvRNormalized)
#define RatioPowInv STATNAME(RatioPowInv)
#define SqrtFix STATNAME(SqrtFix)
#define QMFAnalysis STATNAME(QMFAnalysis)
#define QMFSynthesis STATNAME(QMFSynthesis)
#define GetSampRateIdx STATNAME(GetSampRateIdx)
#define UnpackSBRHeader STATNAME(UnpackSBRHeader)
#define UnpackSBRSingleChannel STATNAME(UnpackSBRSingleChannel)
#define UnpackSBRChannelPair STATNAME(UnpackSBRChannelPair)
/* asm functions */
#define CVKernel1 STATNAME(CVKernel1)
#define CVKernel2 STATNAME(CVKernel2)
#define QMFAnalysisConv STATNAME(QMFAnalysisConv)
#define QMFSynthesisConv STATNAME(QMFSynthesisConv)
#define k0Tab STATNAME(k0Tab)
#define k2Tab STATNAME(k2Tab)
#define goalSBTab STATNAME(goalSBTab)
#define huffTabSBR STATNAME(huffTabSBR)
#define huffTabSBRInfo STATNAME(huffTabSBRInfo)
#define log2Tab STATNAME(log2Tab)
#define noiseTab STATNAME(noiseTab)
#define cTabA STATNAME(cTabA)
#define cTabS STATNAME(cTabS)
/* do y <<= n, clipping to range [-2^30, 2^30 - 1] (i.e. output has one guard bit) */
#define CLIP_2N_SHIFT30(y, n) { \
int sign = (y) >> 31; \
if (sign != (y) >> (30 - (n))) { \
(y) = sign ^ (0x3fffffff); \
} else { \
(y) = (y) << (n); \
} \
}
/*
#define CLIP_2N(y, n) { \
int sign = (y) >> 31; \
if (sign != ((y) >> (n))) { \
(y) = sign ^ ((1 << (n)) - 1); \
} \
}
*/
enum {
SBR_GRID_FIXFIX = 0,
SBR_GRID_FIXVAR = 1,
SBR_GRID_VARFIX = 2,
SBR_GRID_VARVAR = 3
};
enum {
HuffTabSBR_tEnv15 = 0,
HuffTabSBR_fEnv15 = 1,
HuffTabSBR_tEnv15b = 2,
HuffTabSBR_fEnv15b = 3,
HuffTabSBR_tEnv30 = 4,
HuffTabSBR_fEnv30 = 5,
HuffTabSBR_tEnv30b = 6,
HuffTabSBR_fEnv30b = 7,
HuffTabSBR_tNoise30 = 8,
HuffTabSBR_fNoise30 = 5,
HuffTabSBR_tNoise30b = 9,
HuffTabSBR_fNoise30b = 7
};
typedef struct _HuffInfo {
int maxBits; /* number of bits in longest codeword */
unsigned /*char*/ int count[MAX_HUFF_BITS]; /* count[i] = number of codes with length i+1 bits */
int offset; /* offset into symbol table */
} HuffInfo;
/* need one SBRHeader per element (SCE/CPE), updated only on new header */
typedef struct _SBRHeader {
int count;
unsigned char ampRes;
unsigned char startFreq;
unsigned char stopFreq;
unsigned char crossOverBand;
unsigned char resBitsHdr;
unsigned char hdrExtra1;
unsigned char hdrExtra2;
unsigned char freqScale;
unsigned char alterScale;
unsigned char noiseBands;
unsigned char limiterBands;
unsigned char limiterGains;
unsigned char interpFreq;
unsigned char smoothMode;
} SBRHeader;
/* need one SBRGrid per channel, updated every frame */
typedef struct _SBRGrid {
unsigned char frameClass;
unsigned char ampResFrame;
unsigned char pointer;
unsigned char numEnv; /* L_E */
unsigned char envTimeBorder[MAX_NUM_ENV+1]; /* t_E */
unsigned char freqRes[MAX_NUM_ENV]; /* r */
unsigned char numNoiseFloors; /* L_Q */
unsigned char noiseTimeBorder[MAX_NUM_NOISE_FLOORS+1]; /* t_Q */
unsigned char numEnvPrev;
unsigned char numNoiseFloorsPrev;
unsigned char freqResPrev;
} SBRGrid;
/* need one SBRFreq per element (SCE/CPE/LFE), updated only on header reset */
typedef struct _SBRFreq {
int kStart; /* k_x */
int nMaster;
int nHigh;
int nLow;
int nLimiter; /* N_l */
int numQMFBands; /* M */
int numNoiseFloorBands; /* Nq */
int kStartPrev;
int numQMFBandsPrev;
unsigned char freqMaster[MAX_QMF_BANDS + 1]; /* not necessary to save this after derived tables are generated */
unsigned char freqHigh[MAX_QMF_BANDS + 1];
unsigned char freqLow[MAX_QMF_BANDS / 2 + 1]; /* nLow = nHigh - (nHigh >> 1) */
unsigned char freqNoise[MAX_NUM_NOISE_FLOOR_BANDS+1];
unsigned char freqLimiter[MAX_QMF_BANDS / 2 + MAX_NUM_PATCHES]; /* max (intermediate) size = nLow + numPatches - 1 */
unsigned char numPatches;
unsigned char patchNumSubbands[MAX_NUM_PATCHES + 1];
unsigned char patchStartSubband[MAX_NUM_PATCHES + 1];
} SBRFreq;
typedef struct _SBRChan {
int reset;
unsigned char deltaFlagEnv[MAX_NUM_ENV];
unsigned char deltaFlagNoise[MAX_NUM_NOISE_FLOORS];
signed char envDataQuant[MAX_NUM_ENV][MAX_QMF_BANDS]; /* range = [0, 127] */
signed char noiseDataQuant[MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS];
unsigned char invfMode[2][MAX_NUM_NOISE_FLOOR_BANDS]; /* invfMode[0/1][band] = prev/curr */
int chirpFact[MAX_NUM_NOISE_FLOOR_BANDS]; /* bwArray */
unsigned char addHarmonicFlag[2]; /* addHarmonicFlag[0/1] = prev/curr */
unsigned char addHarmonic[2][64]; /* addHarmonic[0/1][band] = prev/curr */
int gbMask[2]; /* gbMask[0/1] = XBuf[0-31]/XBuf[32-39] */
signed char laPrev;
int noiseTabIndex;
int sinIndex;
int gainNoiseIndex;
int gTemp[MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS];
int qTemp[MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS];
} SBRChan;
typedef struct _PSInfoSBR {
/* save for entire file */
int frameCount;
int sampRateIdx;
/* state info that must be saved for each channel */
SBRHeader sbrHdr[AAC_MAX_NCHANS];
SBRGrid sbrGrid[AAC_MAX_NCHANS];
SBRFreq sbrFreq[AAC_MAX_NCHANS];
SBRChan sbrChan[AAC_MAX_NCHANS];
/* temp variables, no need to save between blocks */
unsigned char dataExtra;
unsigned char resBitsData;
unsigned char extendedDataPresent;
int extendedDataSize;
signed char envDataDequantScale[MAX_NCHANS_ELEM][MAX_NUM_ENV];
int envDataDequant[MAX_NCHANS_ELEM][MAX_NUM_ENV][MAX_QMF_BANDS];
int noiseDataDequant[MAX_NCHANS_ELEM][MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS];
int eCurr[MAX_QMF_BANDS];
unsigned char eCurrExp[MAX_QMF_BANDS];
unsigned char eCurrExpMax;
signed char la;
int crcCheckWord;
int couplingFlag;
int envBand;
int eOMGainMax;
int gainMax;
int gainMaxFBits;
int noiseFloorBand;
int qp1Inv;
int qqp1Inv;
int sMapped;
int sBand;
int highBand;
int sumEOrigMapped;
int sumECurrGLim;
int sumSM;
int sumQM;
int gLimBoost[MAX_QMF_BANDS];
int qmLimBoost[MAX_QMF_BANDS];
int smBoost[MAX_QMF_BANDS];
int smBuf[MAX_QMF_BANDS];
int qmLimBuf[MAX_QMF_BANDS];
int gLimBuf[MAX_QMF_BANDS];
int gLimFbits[MAX_QMF_BANDS];
int gFiltLast[MAX_QMF_BANDS];
int qFiltLast[MAX_QMF_BANDS];
/* large buffers */
int delayIdxQMFA[AAC_MAX_NCHANS];
int delayQMFA[AAC_MAX_NCHANS][DELAY_SAMPS_QMFA];
int delayIdxQMFS[AAC_MAX_NCHANS];
int delayQMFS[AAC_MAX_NCHANS][DELAY_SAMPS_QMFS];
int XBufDelay[AAC_MAX_NCHANS][HF_GEN][64][2];
int XBuf[32+8][64][2];
} PSInfoSBR;
/* sbrfft.c */
void FFT32C(int *x);
/* sbrfreq.c */
int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx);
/* sbrhfadj.c */
void AdjustHighFreq(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
/* sbrhfgen.c */
void GenerateHighFreq(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
/* sbrhuff.c */
void DecodeSBREnvelope(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
void DecodeSBRNoise(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
void UncoupleSBREnvelope(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
void UncoupleSBRNoise(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
/* sbrmath.c */
int InvRNormalized(int r);
int RatioPowInv(int a, int b, int c);
int SqrtFix(int x, int fBitsIn, int *fBitsOut);
/* sbrqmf.c */
int QMFAnalysis(int *inbuf, int *delay, int *XBuf, int fBitsIn, int *delayIdx, int qmfaBands);
void QMFSynthesis(int *inbuf, int *delay, int *delayIdx, int qmfsBands, short *outbuf, int nChans);
/* sbrside.c */
int GetSampRateIdx(int sampRate);
int UnpackSBRHeader(BitStreamInfo *bsi, SBRHeader *sbrHdr);
void UnpackSBRSingleChannel(BitStreamInfo *bsi, PSInfoSBR *psi, int chOut);
void UnpackSBRChannelPair(BitStreamInfo *bsi, PSInfoSBR *psi, int chOut);
/* sbrtabs.c */
extern const unsigned char k0Tab[NUM_SAMPLE_RATES_SBR][16];
extern const unsigned char k2Tab[NUM_SAMPLE_RATES_SBR][14];
extern const unsigned char goalSBTab[NUM_SAMPLE_RATES_SBR];
extern const HuffInfo huffTabSBRInfo[10];
extern const signed int /*short*/ huffTabSBR[604];
extern const int log2Tab[65];
extern const int noiseTab[512*2];
extern const int cTabA[165];
extern const int cTabS[640];
#endif /* _SBR_H */

View File

@@ -1,368 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrfft.c,v 1.1 2005/02/26 01:47:35 jrecker 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), Ken Cooke (kenc@real.com)
* February 2005
*
* sbrfft.c - optimized FFT for SBR QMF filters
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
#define SQRT1_2 0x5a82799a
/* swap RE{p0} with RE{p1} and IM{P0} with IM{P1} */
#define swapcplx(p0,p1) \
t = p0; t1 = *(&(p0)+1); p0 = p1; *(&(p0)+1) = *(&(p1)+1); p1 = t; *(&(p1)+1) = t1
/* nfft = 32, hard coded since small, fixed size FFT
static const unsigned char bitrevtab32[9] = {
0x01, 0x04, 0x03, 0x06, 0x00, 0x02, 0x05, 0x07, 0x00,
};
*/
/* twiddle table for radix 4 pass, format = Q31 */
static const int twidTabOdd32[8*6] = {
0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x539eba45, 0xe7821d59,
0x4b418bbe, 0xf383a3e2, 0x58c542c5, 0xdc71898d, 0x5a82799a, 0xd2bec333, 0x539eba45, 0xe7821d59,
0x539eba45, 0xc4df2862, 0x539eba45, 0xc4df2862, 0x58c542c5, 0xdc71898d, 0x3248d382, 0xc13ad060,
0x40000000, 0xc0000000, 0x5a82799a, 0xd2bec333, 0x00000000, 0xd2bec333, 0x22a2f4f8, 0xc4df2862,
0x58c542c5, 0xcac933ae, 0xcdb72c7e, 0xf383a3e2, 0x00000000, 0xd2bec333, 0x539eba45, 0xc4df2862,
0xac6145bb, 0x187de2a7, 0xdd5d0b08, 0xe7821d59, 0x4b418bbe, 0xc13ad060, 0xa73abd3b, 0x3536cc52,
};
/**************************************************************************************
* Function: BitReverse32
*
* Description: Ken's fast in-place bit reverse
*
* Inputs: buffer of 32 complex samples
*
* Outputs: bit-reversed samples in same buffer
*
* Return: none
**************************************************************************************/
static void BitReverse32(int *inout)
{
int t, t1;
swapcplx(inout[2], inout[32]);
swapcplx(inout[4], inout[16]);
swapcplx(inout[6], inout[48]);
swapcplx(inout[10], inout[40]);
swapcplx(inout[12], inout[24]);
swapcplx(inout[14], inout[56]);
swapcplx(inout[18], inout[36]);
swapcplx(inout[22], inout[52]);
swapcplx(inout[26], inout[44]);
swapcplx(inout[30], inout[60]);
swapcplx(inout[38], inout[50]);
swapcplx(inout[46], inout[58]);
}
/**************************************************************************************
* Function: R8FirstPass32
*
* Description: radix-8 trivial pass for decimation-in-time FFT (log2(N) = 5)
*
* Inputs: buffer of (bit-reversed) samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 3 guard bits, gains 1 integer bit
* guard bits out = guard bits in - 3 (if inputs are full scale)
* or guard bits in - 2 (if inputs bounded to +/- sqrt(2)/2)
* see scaling comments in fft.c for base AAC
* should compile with no stack spills on ARM (verify compiled output)
* current instruction count (per pass): 16 LDR, 16 STR, 4 SMULL, 61 ALU
**************************************************************************************/
static void R8FirstPass32(int *r0)
{
int r1, r2, r3, r4, r5, r6, r7;
int r8, r9, r10, r11, r12, r14;
/* number of passes = fft size / 8 = 32 / 8 = 4 */
r1 = (32 >> 3);
do {
r2 = r0[8];
r3 = r0[9];
r4 = r0[10];
r5 = r0[11];
r6 = r0[12];
r7 = r0[13];
r8 = r0[14];
r9 = r0[15];
r10 = r2 + r4;
r11 = r3 + r5;
r12 = r6 + r8;
r14 = r7 + r9;
r2 -= r4;
r3 -= r5;
r6 -= r8;
r7 -= r9;
r4 = r2 - r7;
r5 = r2 + r7;
r8 = r3 - r6;
r9 = r3 + r6;
r2 = r4 - r9;
r3 = r4 + r9;
r6 = r5 - r8;
r7 = r5 + r8;
r2 = MULSHIFT32(SQRT1_2, r2); /* can use r4, r5, r8, or r9 for constant and lo32 scratch reg */
r3 = MULSHIFT32(SQRT1_2, r3);
r6 = MULSHIFT32(SQRT1_2, r6);
r7 = MULSHIFT32(SQRT1_2, r7);
r4 = r10 + r12;
r5 = r10 - r12;
r8 = r11 + r14;
r9 = r11 - r14;
r10 = r0[0];
r11 = r0[2];
r12 = r0[4];
r14 = r0[6];
r10 += r11;
r12 += r14;
r4 >>= 1;
r10 += r12;
r4 += (r10 >> 1);
r0[ 0] = r4;
r4 -= (r10 >> 1);
r4 = (r10 >> 1) - r4;
r0[ 8] = r4;
r9 >>= 1;
r10 -= 2*r12;
r4 = (r10 >> 1) + r9;
r0[ 4] = r4;
r4 = (r10 >> 1) - r9;
r0[12] = r4;
r10 += r12;
r10 -= 2*r11;
r12 -= 2*r14;
r4 = r0[1];
r9 = r0[3];
r11 = r0[5];
r14 = r0[7];
r4 += r9;
r11 += r14;
r8 >>= 1;
r4 += r11;
r8 += (r4 >> 1);
r0[ 1] = r8;
r8 -= (r4 >> 1);
r8 = (r4 >> 1) - r8;
r0[ 9] = r8;
r5 >>= 1;
r4 -= 2*r11;
r8 = (r4 >> 1) - r5;
r0[ 5] = r8;
r8 = (r4 >> 1) + r5;
r0[13] = r8;
r4 += r11;
r4 -= 2*r9;
r11 -= 2*r14;
r9 = r10 - r11;
r10 += r11;
r14 = r4 + r12;
r4 -= r12;
r5 = (r10 >> 1) + r7;
r8 = (r4 >> 1) - r6;
r0[ 2] = r5;
r0[ 3] = r8;
r5 = (r9 >> 1) - r2;
r8 = (r14 >> 1) - r3;
r0[ 6] = r5;
r0[ 7] = r8;
r5 = (r10 >> 1) - r7;
r8 = (r4 >> 1) + r6;
r0[10] = r5;
r0[11] = r8;
r5 = (r9 >> 1) + r2;
r8 = (r14 >> 1) + r3;
r0[14] = r5;
r0[15] = r8;
r0 += 16;
r1--;
} while (r1 != 0);
}
/**************************************************************************************
* Function: R4Core32
*
* Description: radix-4 pass for 32-point decimation-in-time FFT
*
* Inputs: buffer of samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: gain 2 integer bits
* guard bits out = guard bits in - 1 (if inputs are full scale)
* see scaling comments in fft.c for base AAC
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
* should compile with no stack spills on ARM (verify compiled output)
* current instruction count (per pass): 16 LDR, 16 STR, 4 SMULL, 61 ALU
**************************************************************************************/
static void R4Core32(int *r0)
{
int r2, r3, r4, r5, r6, r7;
int r8, r9, r10, r12, r14;
int *r1;
r1 = (int *)twidTabOdd32;
r10 = 8;
do {
/* can use r14 for lo32 scratch register in all MULSHIFT32 */
r2 = r1[0];
r3 = r1[1];
r4 = r0[16];
r5 = r0[17];
r12 = r4 + r5;
r12 = MULSHIFT32(r3, r12);
r5 = MULSHIFT32(r2, r5) + r12;
r2 += 2*r3;
r4 = MULSHIFT32(r2, r4) - r12;
r2 = r1[2];
r3 = r1[3];
r6 = r0[32];
r7 = r0[33];
r12 = r6 + r7;
r12 = MULSHIFT32(r3, r12);
r7 = MULSHIFT32(r2, r7) + r12;
r2 += 2*r3;
r6 = MULSHIFT32(r2, r6) - r12;
r2 = r1[4];
r3 = r1[5];
r8 = r0[48];
r9 = r0[49];
r12 = r8 + r9;
r12 = MULSHIFT32(r3, r12);
r9 = MULSHIFT32(r2, r9) + r12;
r2 += 2*r3;
r8 = MULSHIFT32(r2, r8) - r12;
r2 = r0[0];
r3 = r0[1];
r12 = r6 + r8;
r8 = r6 - r8;
r14 = r9 - r7;
r9 = r9 + r7;
r6 = (r2 >> 2) - r4;
r7 = (r3 >> 2) - r5;
r4 += (r2 >> 2);
r5 += (r3 >> 2);
r2 = r4 + r12;
r3 = r5 + r9;
r0[0] = r2;
r0[1] = r3;
r2 = r6 - r14;
r3 = r7 - r8;
r0[16] = r2;
r0[17] = r3;
r2 = r4 - r12;
r3 = r5 - r9;
r0[32] = r2;
r0[33] = r3;
r2 = r6 + r14;
r3 = r7 + r8;
r0[48] = r2;
r0[49] = r3;
r0 += 2;
r1 += 6;
r10--;
} while (r10 != 0);
}
/**************************************************************************************
* Function: FFT32C
*
* Description: Ken's very fast in-place radix-4 decimation-in-time FFT
*
* Inputs: buffer of 32 complex samples (before bit-reversal)
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: assumes 3 guard bits in, gains 3 integer bits
* guard bits out = guard bits in - 2
* (guard bit analysis includes assumptions about steps immediately
* before and after, i.e. PreMul and PostMul for DCT)
**************************************************************************************/
void FFT32C(int *x)
{
/* decimation in time */
BitReverse32(x);
/* 32-point complex FFT */
R8FirstPass32(x); /* gain 1 int bit, lose 2 GB (making assumptions about input) */
R4Core32(x); /* gain 2 int bits, lose 0 GB (making assumptions about input) */
}

View File

@@ -1,641 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrfreq.c,v 1.2 2005/05/20 18:05:41 jrecker 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
*
* sbrfreq.c - frequency band table calculation for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/**************************************************************************************
* Function: BubbleSort
*
* Description: in-place sort of unsigned chars
*
* Inputs: buffer of elements to sort
* number of elements to sort
*
* Outputs: sorted buffer
*
* Return: none
**************************************************************************************/
static void BubbleSort(unsigned char *v, int nItems)
{
int i;
unsigned char t;
while (nItems >= 2) {
for (i = 0; i < nItems-1; i++) {
if (v[i+1] < v[i]) {
t = v[i+1];
v[i+1] = v[i];
v[i] = t;
}
}
nItems--;
}
}
/**************************************************************************************
* Function: VMin
*
* Description: find smallest element in a buffer of unsigned chars
*
* Inputs: buffer of elements to search
* number of elements to search
*
* Outputs: none
*
* Return: smallest element in buffer
**************************************************************************************/
static unsigned char VMin(unsigned char *v, int nItems)
{
int i;
unsigned char vMin;
vMin = v[0];
for (i = 1; i < nItems; i++) {
if (v[i] < vMin)
vMin = v[i];
}
return vMin;
}
/**************************************************************************************
* Function: VMax
*
* Description: find largest element in a buffer of unsigned chars
*
* Inputs: buffer of elements to search
* number of elements to search
*
* Outputs: none
*
* Return: largest element in buffer
**************************************************************************************/
static unsigned char VMax(unsigned char *v, int nItems)
{
int i;
unsigned char vMax;
vMax = v[0];
for (i = 1; i < nItems; i++) {
if (v[i] > vMax)
vMax = v[i];
}
return vMax;
}
/**************************************************************************************
* Function: CalcFreqMasterScaleZero
*
* Description: calculate master frequency table when freqScale == 0
* (4.6.18.3.2.1, figure 4.39)
*
* Inputs: alterScale flag
* index of first QMF subband in master freq table (k0)
* index of last QMF subband (k2)
*
* Outputs: master frequency table
*
* Return: number of bands in master frequency table
*
* Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
**************************************************************************************/
static int CalcFreqMasterScaleZero(unsigned char *freqMaster, int alterScale, int k0, int k2)
{
int nMaster, k, nBands, k2Achieved, dk, vDk[64], k2Diff;
if (alterScale) {
dk = 2;
nBands = 2 * ((k2 - k0 + 2) >> 2);
} else {
dk = 1;
nBands = 2 * ((k2 - k0) >> 1);
}
if (nBands <= 0)
return 0;
k2Achieved = k0 + nBands * dk;
k2Diff = k2 - k2Achieved;
for (k = 0; k < nBands; k++)
vDk[k] = dk;
if (k2Diff > 0) {
k = nBands - 1;
while (k2Diff) {
vDk[k]++;
k--;
k2Diff--;
}
} else if (k2Diff < 0) {
k = 0;
while (k2Diff) {
vDk[k]--;
k++;
k2Diff++;
}
}
nMaster = nBands;
freqMaster[0] = k0;
for (k = 1; k <= nBands; k++)
freqMaster[k] = freqMaster[k-1] + vDk[k-1];
return nMaster;
}
/* mBandTab[i] = temp1[i] / 2 */
static const int mBandTab[3] PROGMEM = {6, 5, 4};
/* invWarpTab[i] = 1.0 / temp2[i], Q30 (see 4.6.18.3.2.1) */
static const int invWarpTab[2] PROGMEM = {0x40000000, 0x313b13b1};
/**************************************************************************************
* Function: CalcFreqMasterScale
*
* Description: calculate master frequency table when freqScale > 0
* (4.6.18.3.2.1, figure 4.39)
*
* Inputs: alterScale flag
* freqScale flag
* index of first QMF subband in master freq table (k0)
* index of last QMF subband (k2)
*
* Outputs: master frequency table
*
* Return: number of bands in master frequency table
*
* Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
**************************************************************************************/
static int CalcFreqMaster(unsigned char *freqMaster, int freqScale, int alterScale, int k0, int k2)
{
int bands, twoRegions, k, k1, t, vLast, vCurr, pCurr;
int invWarp, nBands0, nBands1, change;
unsigned char vDk1Min, vDk0Max;
unsigned char *vDelta;
if (freqScale < 1 || freqScale > 3)
return -1;
bands = mBandTab[freqScale - 1];
invWarp = invWarpTab[alterScale];
/* tested for all k0 = [5, 64], k2 = [k0, 64] */
if (k2*10000 > 22449*k0) {
twoRegions = 1;
k1 = 2*k0;
} else {
twoRegions = 0;
k1 = k2;
}
/* tested for all k0 = [5, 64], k1 = [k0, 64], freqScale = [1,3] */
t = (log2Tab[k1] - log2Tab[k0]) >> 3; /* log2(k1/k0), Q28 to Q25 */
nBands0 = 2 * (((bands * t) + (1 << 24)) >> 25); /* multiply by bands/2, round to nearest int (mBandTab has factor of 1/2 rolled in) */
/* tested for all valid combinations of k0, k1, nBands (from sampRate, freqScale, alterScale)
* roundoff error can be a problem with fixpt (e.g. pCurr = 12.499999 instead of 12.50003)
* because successive multiplication always undershoots a little bit, but this
* doesn't occur in any of the ratios we encounter from the valid k0/k1 bands in the spec
*/
t = RatioPowInv(k1, k0, nBands0);
pCurr = k0 << 24;
vLast = k0;
vDelta = freqMaster + 1; /* operate in-place */
for (k = 0; k < nBands0; k++) {
pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
vCurr = (pCurr + (1 << 23)) >> 24;
vDelta[k] = (vCurr - vLast);
vLast = vCurr;
}
/* sort the deltas and find max delta for first region */
BubbleSort(vDelta, nBands0);
vDk0Max = VMax(vDelta, nBands0);
/* fill master frequency table with bands from first region */
freqMaster[0] = k0;
for (k = 1; k <= nBands0; k++)
freqMaster[k] += freqMaster[k-1];
/* if only one region, then the table is complete */
if (!twoRegions)
return nBands0;
/* tested for all k1 = [10, 64], k2 = [k0, 64], freqScale = [1,3] */
t = (log2Tab[k2] - log2Tab[k1]) >> 3; /* log2(k1/k0), Q28 to Q25 */
t = MULSHIFT32(bands * t, invWarp) << 2; /* multiply by bands/2, divide by warp factor, keep Q25 */
nBands1 = 2 * ((t + (1 << 24)) >> 25); /* round to nearest int */
/* see comments above for calculations in first region */
t = RatioPowInv(k2, k1, nBands1);
pCurr = k1 << 24;
vLast = k1;
vDelta = freqMaster + nBands0 + 1; /* operate in-place */
for (k = 0; k < nBands1; k++) {
pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
vCurr = (pCurr + (1 << 23)) >> 24;
vDelta[k] = (vCurr - vLast);
vLast = vCurr;
}
/* sort the deltas, adjusting first and last if the second region has smaller deltas than the first */
vDk1Min = VMin(vDelta, nBands1);
if (vDk1Min < vDk0Max) {
BubbleSort(vDelta, nBands1);
change = vDk0Max - vDelta[0];
if (change > ((vDelta[nBands1 - 1] - vDelta[0]) >> 1))
change = ((vDelta[nBands1 - 1] - vDelta[0]) >> 1);
vDelta[0] += change;
vDelta[nBands1-1] -= change;
}
BubbleSort(vDelta, nBands1);
/* fill master frequency table with bands from second region
* Note: freqMaster[nBands0] = k1
*/
for (k = 1; k <= nBands1; k++)
freqMaster[k + nBands0] += freqMaster[k + nBands0 - 1];
return (nBands0 + nBands1);
}
/**************************************************************************************
* Function: CalcFreqHigh
*
* Description: calculate high resolution frequency table (4.6.18.3.2.2)
*
* Inputs: master frequency table
* number of bands in master frequency table
* crossover band from header
*
* Outputs: high resolution frequency table
*
* Return: number of bands in high resolution frequency table
**************************************************************************************/
static int CalcFreqHigh(unsigned char *freqHigh, unsigned char *freqMaster, int nMaster, int crossOverBand)
{
int k, nHigh;
nHigh = nMaster - crossOverBand;
for (k = 0; k <= nHigh; k++)
freqHigh[k] = freqMaster[k + crossOverBand];
return nHigh;
}
/**************************************************************************************
* Function: CalcFreqLow
*
* Description: calculate low resolution frequency table (4.6.18.3.2.2)
*
* Inputs: high resolution frequency table
* number of bands in high resolution frequency table
*
* Outputs: low resolution frequency table
*
* Return: number of bands in low resolution frequency table
**************************************************************************************/
static int CalcFreqLow(unsigned char *freqLow, unsigned char *freqHigh, int nHigh)
{
int k, nLow, oddFlag;
nLow = nHigh - (nHigh >> 1);
freqLow[0] = freqHigh[0];
oddFlag = nHigh & 0x01;
for (k = 1; k <= nLow; k++)
freqLow[k] = freqHigh[2*k - oddFlag];
return nLow;
}
/**************************************************************************************
* Function: CalcFreqNoise
*
* Description: calculate noise floor frequency table (4.6.18.3.2.2)
*
* Inputs: low resolution frequency table
* number of bands in low resolution frequency table
* index of starting QMF subband for SBR (kStart)
* index of last QMF subband (k2)
* number of noise bands
*
* Outputs: noise floor frequency table
*
* Return: number of bands in noise floor frequency table
**************************************************************************************/
static int CalcFreqNoise(unsigned char *freqNoise, unsigned char *freqLow, int nLow, int kStart, int k2, int noiseBands)
{
int i, iLast, k, nQ, lTop, lBottom;
lTop = log2Tab[k2];
lBottom = log2Tab[kStart];
nQ = noiseBands*((lTop - lBottom) >> 2); /* Q28 to Q26, noiseBands = [0,3] */
nQ = (nQ + (1 << 25)) >> 26;
if (nQ < 1)
nQ = 1;
ASSERT(nQ <= MAX_NUM_NOISE_FLOOR_BANDS); /* required from 4.6.18.3.6 */
iLast = 0;
freqNoise[0] = freqLow[0];
for (k = 1; k <= nQ; k++) {
i = iLast + (nLow - iLast) / (nQ + 1 - k); /* truncating division */
freqNoise[k] = freqLow[i];
iLast = i;
}
return nQ;
}
/**************************************************************************************
* Function: BuildPatches
*
* Description: build high frequency patches (4.6.18.6.3)
*
* Inputs: master frequency table
* number of bands in low resolution frequency table
* index of first QMF subband in master freq table (k0)
* index of starting QMF subband for SBR (kStart)
* number of QMF bands in high resolution frequency table
* sample rate index
*
* Outputs: starting subband for each patch
* number of subbands in each patch
*
* Return: number of patches
**************************************************************************************/
static int BuildPatches(unsigned char *patchNumSubbands, unsigned char *patchStartSubband, unsigned char *freqMaster,
int nMaster, int k0, int kStart, int numQMFBands, int sampRateIdx)
{
int i, j, k;
int msb, sb, usb, numPatches, goalSB, oddFlag;
msb = k0;
usb = kStart;
numPatches = 0;
goalSB = goalSBTab[sampRateIdx];
if (nMaster == 0) {
patchNumSubbands[0] = 0;
patchStartSubband[0] = 0;
return 0;
}
if (goalSB < kStart + numQMFBands) {
k = 0;
for (i = 0; freqMaster[i] < goalSB; i++)
k = i+1;
} else {
k = nMaster;
}
do {
j = k+1;
do {
j--;
sb = freqMaster[j];
oddFlag = (sb - 2 + k0) & 0x01;
} while (sb > k0 - 1 + msb - oddFlag);
patchNumSubbands[numPatches] = MAX(sb - usb, 0);
patchStartSubband[numPatches] = k0 - oddFlag - patchNumSubbands[numPatches];
/* from MPEG reference code - slightly different from spec */
if ((patchNumSubbands[numPatches] < 3) && (numPatches > 0))
break;
if (patchNumSubbands[numPatches] > 0) {
usb = sb;
msb = sb;
numPatches++;
} else {
msb = kStart;
}
if (freqMaster[k] - sb < 3)
k = nMaster;
} while (sb != (kStart + numQMFBands) && numPatches <= MAX_NUM_PATCHES);
return numPatches;
}
/**************************************************************************************
* Function: FindFreq
*
* Description: search buffer of unsigned chars for a specific value
*
* Inputs: buffer of elements to search
* number of elements to search
* value to search for
*
* Outputs: none
*
* Return: non-zero if the value is found anywhere in the buffer, zero otherwise
**************************************************************************************/
static int FindFreq(unsigned char *freq, int nFreq, unsigned char val)
{
int k;
for (k = 0; k < nFreq; k++) {
if (freq[k] == val)
return 1;
}
return 0;
}
/**************************************************************************************
* Function: RemoveFreq
*
* Description: remove one element from a buffer of unsigned chars
*
* Inputs: buffer of elements
* number of elements
* index of element to remove
*
* Outputs: new buffer of length nFreq-1
*
* Return: none
**************************************************************************************/
static void RemoveFreq(unsigned char *freq, int nFreq, int removeIdx)
{
int k;
if (removeIdx >= nFreq)
return;
for (k = removeIdx; k < nFreq - 1; k++)
freq[k] = freq[k+1];
}
/**************************************************************************************
* Function: CalcFreqLimiter
*
* Description: calculate limiter frequency table (4.6.18.3.2.3)
*
* Inputs: number of subbands in each patch
* low resolution frequency table
* number of bands in low resolution frequency table
* index of starting QMF subband for SBR (kStart)
* number of limiter bands
* number of patches
*
* Outputs: limiter frequency table
*
* Return: number of bands in limiter frequency table
**************************************************************************************/
static int CalcFreqLimiter(unsigned char *freqLimiter, unsigned char *patchNumSubbands, unsigned char *freqLow,
int nLow, int kStart, int limiterBands, int numPatches)
{
int k, bands, nLimiter, nOctaves;
int limBandsPerOctave[3] = {120, 200, 300}; /* [1.2, 2.0, 3.0] * 100 */
unsigned char patchBorders[MAX_NUM_PATCHES + 1];
/* simple case */
if (limiterBands == 0) {
freqLimiter[0] = freqLow[0] - kStart;
freqLimiter[1] = freqLow[nLow] - kStart;
return 1;
}
bands = limBandsPerOctave[limiterBands - 1];
patchBorders[0] = kStart;
/* from MPEG reference code - slightly different from spec (top border) */
for (k = 1; k < numPatches; k++)
patchBorders[k] = patchBorders[k-1] + patchNumSubbands[k-1];
patchBorders[k] = freqLow[nLow];
for (k = 0; k <= nLow; k++)
freqLimiter[k] = freqLow[k];
for (k = 1; k < numPatches; k++)
freqLimiter[k+nLow] = patchBorders[k];
k = 1;
nLimiter = nLow + numPatches - 1;
BubbleSort(freqLimiter, nLimiter + 1);
while (k <= nLimiter) {
nOctaves = log2Tab[freqLimiter[k]] - log2Tab[freqLimiter[k-1]]; /* Q28 */
nOctaves = (nOctaves >> 9) * bands; /* Q19, max bands = 300 < 2^9 */
if (nOctaves < (49 << 19)) { /* compare with 0.49*100, in Q19 */
if (freqLimiter[k] == freqLimiter[k-1] || FindFreq(patchBorders, numPatches + 1, freqLimiter[k]) == 0) {
RemoveFreq(freqLimiter, nLimiter + 1, k);
nLimiter--;
} else if (FindFreq(patchBorders, numPatches + 1, freqLimiter[k-1]) == 0) {
RemoveFreq(freqLimiter, nLimiter + 1, k-1);
nLimiter--;
} else {
k++;
}
} else {
k++;
}
}
/* store limiter boundaries as offsets from kStart */
for (k = 0; k <= nLimiter; k++)
freqLimiter[k] -= kStart;
return nLimiter;
}
/**************************************************************************************
* Function: CalcFreqTables
*
* Description: calulate master and derived frequency tables, and patches
*
* Inputs: initialized SBRHeader struct for this SCE/CPE block
* initialized SBRFreq struct for this SCE/CPE block
* sample rate index of output sample rate (after SBR)
*
* Outputs: master and derived frequency tables, and patches
*
* Return: non-zero if error, zero otherwise
**************************************************************************************/
int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx)
{
int k0, k2;
k0 = k0Tab[sampRateIdx][sbrHdr->startFreq];
if (sbrHdr->stopFreq == 14)
k2 = 2*k0;
else if (sbrHdr->stopFreq == 15)
k2 = 3*k0;
else
k2 = k2Tab[sampRateIdx][sbrHdr->stopFreq];
if (k2 > 64)
k2 = 64;
/* calculate master frequency table */
if (sbrHdr->freqScale == 0)
sbrFreq->nMaster = CalcFreqMasterScaleZero(sbrFreq->freqMaster, sbrHdr->alterScale, k0, k2);
else
sbrFreq->nMaster = CalcFreqMaster(sbrFreq->freqMaster, sbrHdr->freqScale, sbrHdr->alterScale, k0, k2);
/* calculate high frequency table and related parameters */
sbrFreq->nHigh = CalcFreqHigh(sbrFreq->freqHigh, sbrFreq->freqMaster, sbrFreq->nMaster, sbrHdr->crossOverBand);
sbrFreq->numQMFBands = sbrFreq->freqHigh[sbrFreq->nHigh] - sbrFreq->freqHigh[0];
sbrFreq->kStart = sbrFreq->freqHigh[0];
/* calculate low frequency table */
sbrFreq->nLow = CalcFreqLow(sbrFreq->freqLow, sbrFreq->freqHigh, sbrFreq->nHigh);
/* calculate noise floor frequency table */
sbrFreq->numNoiseFloorBands = CalcFreqNoise(sbrFreq->freqNoise, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart, k2, sbrHdr->noiseBands);
/* calculate limiter table */
sbrFreq->numPatches = BuildPatches(sbrFreq->patchNumSubbands, sbrFreq->patchStartSubband, sbrFreq->freqMaster,
sbrFreq->nMaster, k0, sbrFreq->kStart, sbrFreq->numQMFBands, sampRateIdx);
sbrFreq->nLimiter = CalcFreqLimiter(sbrFreq->freqLimiter, sbrFreq->patchNumSubbands, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart,
sbrHdr->limiterBands, sbrFreq->numPatches);
return 0;
}

View File

@@ -1,853 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrhfadj.c,v 1.3 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
*
* sbrhfadj.c - high frequency adjustment for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/* invBandTab[i] = 1.0 / (i + 1), Q31 */
static const int invBandTab[64] PROGMEM = {
0x7fffffff, 0x40000000, 0x2aaaaaab, 0x20000000, 0x1999999a, 0x15555555, 0x12492492, 0x10000000,
0x0e38e38e, 0x0ccccccd, 0x0ba2e8ba, 0x0aaaaaab, 0x09d89d8a, 0x09249249, 0x08888889, 0x08000000,
0x07878788, 0x071c71c7, 0x06bca1af, 0x06666666, 0x06186186, 0x05d1745d, 0x0590b216, 0x05555555,
0x051eb852, 0x04ec4ec5, 0x04bda12f, 0x04924925, 0x0469ee58, 0x04444444, 0x04210842, 0x04000000,
0x03e0f83e, 0x03c3c3c4, 0x03a83a84, 0x038e38e4, 0x03759f23, 0x035e50d8, 0x03483483, 0x03333333,
0x031f3832, 0x030c30c3, 0x02fa0be8, 0x02e8ba2f, 0x02d82d83, 0x02c8590b, 0x02b93105, 0x02aaaaab,
0x029cbc15, 0x028f5c29, 0x02828283, 0x02762762, 0x026a439f, 0x025ed098, 0x0253c825, 0x02492492,
0x023ee090, 0x0234f72c, 0x022b63cc, 0x02222222, 0x02192e2a, 0x02108421, 0x02082082, 0x02000000,
};
/**************************************************************************************
* Function: EstimateEnvelope
*
* Description: estimate power of generated HF QMF bands in one time-domain envelope
* (4.6.18.7.3)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* index of current envelope
*
* Outputs: power of each QMF subband, stored as integer (Q0) * 2^N, N >= 0
*
* Return: none
**************************************************************************************/
static void EstimateEnvelope(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int env)
{
int i, m, iStart, iEnd, xre, xim, nScale, expMax;
int p, n, mStart, mEnd, invFact, t;
int *XBuf;
U64 eCurr;
unsigned char *freqBandTab;
/* estimate current envelope */
iStart = sbrGrid->envTimeBorder[env] + HF_ADJ;
iEnd = sbrGrid->envTimeBorder[env+1] + HF_ADJ;
if (sbrGrid->freqRes[env]) {
n = sbrFreq->nHigh;
freqBandTab = sbrFreq->freqHigh;
} else {
n = sbrFreq->nLow;
freqBandTab = sbrFreq->freqLow;
}
/* ADS should inline MADD64 (smlal) properly, but check to make sure */
expMax = 0;
if (sbrHdr->interpFreq) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
eCurr.w64 = 0;
XBuf = psi->XBuf[iStart][sbrFreq->kStart + m];
for (i = iStart; i < iEnd; i++) {
/* scale to int before calculating power (precision not critical, and avoids overflow) */
xre = (*XBuf) >> FBITS_OUT_QMFA; XBuf += 1;
xim = (*XBuf) >> FBITS_OUT_QMFA; XBuf += (2*64 - 1);
eCurr.w64 = MADD64(eCurr.w64, xre, xre);
eCurr.w64 = MADD64(eCurr.w64, xim, xim);
}
/* eCurr.w64 is now Q(64 - 2*FBITS_OUT_QMFA) (64-bit word)
* if energy is too big to fit in 32-bit word (> 2^31) scale down by power of 2
*/
nScale = 0;
if (eCurr.r.hi32) {
nScale = (32 - CLZ(eCurr.r.hi32)) + 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
t |= eCurr.r.hi32 << (32 - nScale);
} else if (eCurr.r.lo32 >> 31) {
nScale = 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
} else {
t = (int)eCurr.r.lo32;
}
invFact = invBandTab[(iEnd - iStart)-1];
psi->eCurr[m] = MULSHIFT32(t, invFact);
psi->eCurrExp[m] = nScale + 1; /* +1 for invFact = Q31 */
if (psi->eCurrExp[m] > expMax)
expMax = psi->eCurrExp[m];
}
} else {
for (p = 0; p < n; p++) {
mStart = freqBandTab[p];
mEnd = freqBandTab[p+1];
eCurr.w64 = 0;
for (i = iStart; i < iEnd; i++) {
XBuf = psi->XBuf[i][mStart];
for (m = mStart; m < mEnd; m++) {
xre = (*XBuf++) >> FBITS_OUT_QMFA;
xim = (*XBuf++) >> FBITS_OUT_QMFA;
eCurr.w64 = MADD64(eCurr.w64, xre, xre);
eCurr.w64 = MADD64(eCurr.w64, xim, xim);
}
}
nScale = 0;
if (eCurr.r.hi32) {
nScale = (32 - CLZ(eCurr.r.hi32)) + 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
t |= eCurr.r.hi32 << (32 - nScale);
} else if (eCurr.r.lo32 >> 31) {
nScale = 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
} else {
t = (int)eCurr.r.lo32;
}
invFact = invBandTab[(iEnd - iStart)-1];
invFact = MULSHIFT32(invBandTab[(mEnd - mStart)-1], invFact) << 1;
t = MULSHIFT32(t, invFact);
for (m = mStart; m < mEnd; m++) {
psi->eCurr[m - sbrFreq->kStart] = t;
psi->eCurrExp[m - sbrFreq->kStart] = nScale + 1; /* +1 for invFact = Q31 */
}
if (psi->eCurrExp[mStart - sbrFreq->kStart] > expMax)
expMax = psi->eCurrExp[mStart - sbrFreq->kStart];
}
}
psi->eCurrExpMax = expMax;
}
/**************************************************************************************
* Function: GetSMapped
*
* Description: calculate SMapped (4.6.18.7.2)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current envelope
* index of current QMF band
* la flag for this envelope
*
* Outputs: none
*
* Return: 1 if a sinusoid is present in this band, 0 if not
**************************************************************************************/
static int GetSMapped(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int band, int la)
{
int bandStart, bandEnd, oddFlag, r;
if (sbrGrid->freqRes[env]) {
/* high resolution */
bandStart = band;
bandEnd = band+1;
} else {
/* low resolution (see CalcFreqLow() for mapping) */
oddFlag = sbrFreq->nHigh & 0x01;
bandStart = (band > 0 ? 2*band - oddFlag : 0); /* starting index for freqLow[band] */
bandEnd = 2*(band+1) - oddFlag; /* ending index for freqLow[band+1] */
}
/* sMapped = 1 if sIndexMapped == 1 for any frequency in this band */
for (band = bandStart; band < bandEnd; band++) {
if (sbrChan->addHarmonic[1][band]) {
r = ((sbrFreq->freqHigh[band+1] + sbrFreq->freqHigh[band]) >> 1);
if (env >= la || sbrChan->addHarmonic[0][r] == 1)
return 1;
}
}
return 0;
}
#define GBOOST_MAX 0x2830afd3 /* Q28, 1.584893192 squared */
#define ACC_SCALE 6
/* squared version of table in 4.6.18.7.5 */
static const int limGainTab[4] PROGMEM = {0x20138ca7, 0x40000000, 0x7fb27dce, 0x80000000}; /* Q30 (0x80000000 = sentinel for GMAX) */
/**************************************************************************************
* Function: CalcMaxGain
*
* Description: calculate max gain in one limiter band (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
* index of current limiter band
* number of fraction bits in dequantized envelope
* (max = Q(FBITS_OUT_DQ_ENV - 6) = Q23, can go negative)
*
* Outputs: updated gainMax, gainMaxFBits, and sumEOrigMapped in PSInfoSBR struct
*
* Return: none
**************************************************************************************/
static void CalcMaxGain(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int ch, int env, int lim, int fbitsDQ)
{
int m, mStart, mEnd, q, z, r;
int sumEOrigMapped, sumECurr, gainMax, eOMGainMax, envBand;
unsigned char eCurrExpMax;
unsigned char *freqBandTab;
mStart = sbrFreq->freqLimiter[lim]; /* these are offsets from kStart */
mEnd = sbrFreq->freqLimiter[lim + 1];
freqBandTab = (sbrGrid->freqRes[env] ? sbrFreq->freqHigh : sbrFreq->freqLow);
/* calculate max gain to apply to signal in this limiter band */
sumECurr = 0;
sumEOrigMapped = 0;
eCurrExpMax = psi->eCurrExpMax;
eOMGainMax = psi->eOMGainMax;
envBand = psi->envBand;
for (m = mStart; m < mEnd; m++) {
/* map current QMF band to appropriate envelope band */
if (m == freqBandTab[envBand + 1] - sbrFreq->kStart) {
envBand++;
eOMGainMax = psi->envDataDequant[ch][env][envBand] >> ACC_SCALE; /* summing max 48 bands */
}
sumEOrigMapped += eOMGainMax;
/* easy test for overflow on ARM */
sumECurr += (psi->eCurr[m] >> (eCurrExpMax - psi->eCurrExp[m]));
if (sumECurr >> 30) {
sumECurr >>= 1;
eCurrExpMax++;
}
}
psi->eOMGainMax = eOMGainMax;
psi->envBand = envBand;
psi->gainMaxFBits = 30; /* Q30 tables */
if (sumECurr == 0) {
/* any non-zero numerator * 1/EPS_0 is > G_MAX */
gainMax = (sumEOrigMapped == 0 ? (int)limGainTab[sbrHdr->limiterGains] : (int)0x80000000);
} else if (sumEOrigMapped == 0) {
/* 1/(any non-zero denominator) * EPS_0 * limGainTab[x] is appx. 0 */
gainMax = 0;
} else {
/* sumEOrigMapped = Q(fbitsDQ - ACC_SCALE), sumECurr = Q(-eCurrExpMax) */
gainMax = limGainTab[sbrHdr->limiterGains];
if (sbrHdr->limiterGains != 3) {
q = MULSHIFT32(sumEOrigMapped, gainMax); /* Q(fbitsDQ - ACC_SCALE - 2), gainMax = Q30 */
z = CLZ(sumECurr) - 1;
r = InvRNormalized(sumECurr << z); /* in = Q(z - eCurrExpMax), out = Q(29 + 31 - z + eCurrExpMax) */
gainMax = MULSHIFT32(q, r); /* Q(29 + 31 - z + eCurrExpMax + fbitsDQ - ACC_SCALE - 2 - 32) */
psi->gainMaxFBits = 26 - z + eCurrExpMax + fbitsDQ - ACC_SCALE;
}
}
psi->sumEOrigMapped = sumEOrigMapped;
psi->gainMax = gainMax;
}
/**************************************************************************************
* Function: CalcNoiseDivFactors
*
* Description: calculate 1/(1+Q) and Q/(1+Q) (4.6.18.7.4; 4.6.18.7.5)
*
* Inputs: dequantized noise floor scalefactor
*
* Outputs: 1/(1+Q) and Q/(1+Q), format = Q31
*
* Return: none
**************************************************************************************/
static void CalcNoiseDivFactors(int q, int *qp1Inv, int *qqp1Inv)
{
int z, qp1, t, s;
/* 1 + Q_orig */
qp1 = (q >> 1);
qp1 += (1 << (FBITS_OUT_DQ_NOISE - 1)); /* >> 1 to avoid overflow when adding 1.0 */
z = CLZ(qp1) - 1; /* z <= 31 - FBITS_OUT_DQ_NOISE */
qp1 <<= z; /* Q(FBITS_OUT_DQ_NOISE + z) = Q31 * 2^-(31 - (FBITS_OUT_DQ_NOISE + z)) */
t = InvRNormalized(qp1) << 1; /* Q30 * 2^(31 - (FBITS_OUT_DQ_NOISE + z)), guaranteed not to overflow */
/* normalize to Q31 */
s = (31 - (FBITS_OUT_DQ_NOISE - 1) - z - 1); /* clearly z >= 0, z <= (30 - (FBITS_OUT_DQ_NOISE - 1)) */
*qp1Inv = (t >> s); /* s = [0, 31 - FBITS_OUT_DQ_NOISE] */
*qqp1Inv = MULSHIFT32(t, q) << (32 - FBITS_OUT_DQ_NOISE - s);
}
/**************************************************************************************
* Function: CalcComponentGains
*
* Description: calculate gain of envelope, sinusoids, and noise in one limiter band
* (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
* index of current limiter band
* number of fraction bits in dequantized envelope
*
* Outputs: gains for envelope, sinusoids and noise
* number of fraction bits for envelope gain
* sum of the total gain for each component in this band
* other updated state variables
*
* Return: none
**************************************************************************************/
static void CalcComponentGains(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch, int env, int lim, int fbitsDQ)
{
int d, m, mStart, mEnd, q, qm, noiseFloor, sIndexMapped;
int shift, eCurr, maxFlag, gainMax, gainMaxFBits;
int gain, sm, z, r, fbitsGain, gainScale;
unsigned char *freqBandTab;
mStart = sbrFreq->freqLimiter[lim]; /* these are offsets from kStart */
mEnd = sbrFreq->freqLimiter[lim + 1];
gainMax = psi->gainMax;
gainMaxFBits = psi->gainMaxFBits;
d = (env == psi->la || env == sbrChan->laPrev ? 0 : 1);
freqBandTab = (sbrGrid->freqRes[env] ? sbrFreq->freqHigh : sbrFreq->freqLow);
/* figure out which noise floor this envelope is in (only 1 or 2 noise floors allowed) */
noiseFloor = 0;
if (sbrGrid->numNoiseFloors == 2 && sbrGrid->noiseTimeBorder[1] <= sbrGrid->envTimeBorder[env])
noiseFloor++;
psi->sumECurrGLim = 0;
psi->sumSM = 0;
psi->sumQM = 0;
/* calculate energy of noise to add in this limiter band */
for (m = mStart; m < mEnd; m++) {
if (m == sbrFreq->freqNoise[psi->noiseFloorBand + 1] - sbrFreq->kStart) {
/* map current QMF band to appropriate noise floor band (NOTE: freqLimiter[0] == freqLow[0] = freqHigh[0]) */
psi->noiseFloorBand++;
CalcNoiseDivFactors(psi->noiseDataDequant[ch][noiseFloor][psi->noiseFloorBand], &(psi->qp1Inv), &(psi->qqp1Inv));
}
if (m == sbrFreq->freqHigh[psi->highBand + 1] - sbrFreq->kStart)
psi->highBand++;
if (m == freqBandTab[psi->sBand + 1] - sbrFreq->kStart) {
psi->sBand++;
psi->sMapped = GetSMapped(sbrGrid, sbrFreq, sbrChan, env, psi->sBand, psi->la);
}
/* get sIndexMapped for this QMF subband */
sIndexMapped = 0;
r = ((sbrFreq->freqHigh[psi->highBand+1] + sbrFreq->freqHigh[psi->highBand]) >> 1);
if (m + sbrFreq->kStart == r) {
/* r = center frequency, deltaStep = (env >= la || sIndexMapped'(r, numEnv'-1) == 1) */
if (env >= psi->la || sbrChan->addHarmonic[0][r] == 1)
sIndexMapped = sbrChan->addHarmonic[1][psi->highBand];
}
/* save sine flags from last envelope in this frame:
* addHarmonic[0][0...63] = saved sine present flag from previous frame, for each QMF subband
* addHarmonic[1][0...nHigh-1] = addHarmonic bit from current frame, for each high-res frequency band
* from MPEG reference code - slightly different from spec
* (sIndexMapped'(m,LE'-1) can still be 0 when numEnv == psi->la)
*/
if (env == sbrGrid->numEnv - 1) {
if (m + sbrFreq->kStart == r)
sbrChan->addHarmonic[0][m + sbrFreq->kStart] = sbrChan->addHarmonic[1][psi->highBand];
else
sbrChan->addHarmonic[0][m + sbrFreq->kStart] = 0;
}
gain = psi->envDataDequant[ch][env][psi->sBand];
qm = MULSHIFT32(gain, psi->qqp1Inv) << 1;
sm = (sIndexMapped ? MULSHIFT32(gain, psi->qp1Inv) << 1 : 0);
/* three cases: (sMapped == 0 && delta == 1), (sMapped == 0 && delta == 0), (sMapped == 1) */
if (d == 1 && psi->sMapped == 0)
gain = MULSHIFT32(psi->qp1Inv, gain) << 1;
else if (psi->sMapped != 0)
gain = MULSHIFT32(psi->qqp1Inv, gain) << 1;
/* gain, qm, sm = Q(fbitsDQ), gainMax = Q(fbitsGainMax) */
eCurr = psi->eCurr[m];
if (eCurr) {
z = CLZ(eCurr) - 1;
r = InvRNormalized(eCurr << z); /* in = Q(z - eCurrExp), out = Q(29 + 31 - z + eCurrExp) */
gainScale = MULSHIFT32(gain, r); /* out = Q(29 + 31 - z + eCurrExp + fbitsDQ - 32) */
fbitsGain = 29 + 31 - z + psi->eCurrExp[m] + fbitsDQ - 32;
} else {
/* if eCurr == 0, then gain is unchanged (divide by EPS = 1) */
gainScale = gain;
fbitsGain = fbitsDQ;
}
/* see if gain for this band exceeds max gain */
maxFlag = 0;
if (gainMax != (int)0x80000000) {
if (fbitsGain >= gainMaxFBits) {
shift = MIN(fbitsGain - gainMaxFBits, 31);
maxFlag = ((gainScale >> shift) > gainMax ? 1 : 0);
} else {
shift = MIN(gainMaxFBits - fbitsGain, 31);
maxFlag = (gainScale > (gainMax >> shift) ? 1 : 0);
}
}
if (maxFlag) {
/* gainScale > gainMax, calculate ratio with 32/16 division */
q = 0;
r = gainScale; /* guaranteed > 0, else maxFlag could not have been set */
z = CLZ(r);
if (z < 16) {
q = 16 - z;
r >>= q; /* out = Q(fbitsGain - q) */
}
z = CLZ(gainMax) - 1;
r = (gainMax << z) / r; /* out = Q((fbitsGainMax + z) - (fbitsGain - q)) */
q = (gainMaxFBits + z) - (fbitsGain - q); /* r = Q(q) */
if (q > 30) {
r >>= MIN(q - 30, 31);
} else {
z = MIN(30 - q, 30);
CLIP_2N_SHIFT30(r, z); /* let r = Q30 since range = [0.0, 1.0) (clip to 0x3fffffff = 0.99999) */
}
qm = MULSHIFT32(qm, r) << 2;
gain = MULSHIFT32(gain, r) << 2;
psi->gLimBuf[m] = gainMax;
psi->gLimFbits[m] = gainMaxFBits;
} else {
psi->gLimBuf[m] = gainScale;
psi->gLimFbits[m] = fbitsGain;
}
/* sumSM, sumQM, sumECurrGLim = Q(fbitsDQ - ACC_SCALE) */
psi->smBuf[m] = sm;
psi->sumSM += (sm >> ACC_SCALE);
psi->qmLimBuf[m] = qm;
if (env != psi->la && env != sbrChan->laPrev && sm == 0)
psi->sumQM += (qm >> ACC_SCALE);
/* eCurr * gain^2 same as gain^2, before division by eCurr
* (but note that gain != 0 even if eCurr == 0, since it's divided by eps)
*/
if (eCurr)
psi->sumECurrGLim += (gain >> ACC_SCALE);
}
}
/**************************************************************************************
* Function: ApplyBoost
*
* Description: calculate and apply boost factor for envelope, sinusoids, and noise
* in this limiter band (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRFreq struct for this SCE/CPE block
* index of current limiter band
* number of fraction bits in dequantized envelope
*
* Outputs: envelope gain, sinusoids and noise after scaling by gBoost
* format = Q(FBITS_GLIM_BOOST) for envelope gain,
* = Q(FBITS_QLIM_BOOST) for noise
* = Q(FBITS_OUT_QMFA) for sinusoids
*
* Return: none
*
* Notes: after scaling, each component has at least 1 GB
**************************************************************************************/
static void ApplyBoost(PSInfoSBR *psi, SBRFreq *sbrFreq, int lim, int fbitsDQ)
{
int m, mStart, mEnd, q, z, r;
int sumEOrigMapped, gBoost;
mStart = sbrFreq->freqLimiter[lim]; /* these are offsets from kStart */
mEnd = sbrFreq->freqLimiter[lim + 1];
sumEOrigMapped = psi->sumEOrigMapped >> 1;
r = (psi->sumECurrGLim >> 1) + (psi->sumSM >> 1) + (psi->sumQM >> 1); /* 1 GB fine (sm and qm are mutually exclusive in acc) */
if (r < (1 << (31-28))) {
/* any non-zero numerator * 1/EPS_0 is > GBOOST_MAX
* round very small r to zero to avoid scaling problems
*/
gBoost = (sumEOrigMapped == 0 ? (1 << 28) : GBOOST_MAX);
z = 0;
} else if (sumEOrigMapped == 0) {
/* 1/(any non-zero denominator) * EPS_0 is appx. 0 */
gBoost = 0;
z = 0;
} else {
/* numerator (sumEOrigMapped) and denominator (r) have same Q format (before << z) */
z = CLZ(r) - 1; /* z = [0, 27] */
r = InvRNormalized(r << z);
gBoost = MULSHIFT32(sumEOrigMapped, r);
}
/* gBoost = Q(28 - z) */
if (gBoost > (GBOOST_MAX >> z)) {
gBoost = GBOOST_MAX;
z = 0;
}
gBoost <<= z; /* gBoost = Q28, minimum 1 GB */
/* convert gain, noise, sinusoids to fixed Q format, clipping if necessary
* (rare, usually only happens at very low bitrates, introduces slight
* distortion into final HF mapping, but should be inaudible)
*/
for (m = mStart; m < mEnd; m++) {
/* let gLimBoost = Q24, since in practice the max values are usually 16 to 20
* unless limiterGains == 3 (limiter off) and eCurr ~= 0 (i.e. huge gain, but only
* because the envelope has 0 power anyway)
*/
q = MULSHIFT32(psi->gLimBuf[m], gBoost) << 2; /* Q(gLimFbits) * Q(28) --> Q(gLimFbits[m]-2) */
r = SqrtFix(q, psi->gLimFbits[m] - 2, &z);
z -= FBITS_GLIM_BOOST;
if (z >= 0) {
psi->gLimBoost[m] = r >> MIN(z, 31);
} else {
z = MIN(30, -z);
CLIP_2N_SHIFT30(r, z);
psi->gLimBoost[m] = r;
}
q = MULSHIFT32(psi->qmLimBuf[m], gBoost) << 2; /* Q(fbitsDQ) * Q(28) --> Q(fbitsDQ-2) */
r = SqrtFix(q, fbitsDQ - 2, &z);
z -= FBITS_QLIM_BOOST; /* << by 14, since integer sqrt of x < 2^16, and we want to leave 1 GB */
if (z >= 0) {
psi->qmLimBoost[m] = r >> MIN(31, z);
} else {
z = MIN(30, -z);
CLIP_2N_SHIFT30(r, z);
psi->qmLimBoost[m] = r;
}
q = MULSHIFT32(psi->smBuf[m], gBoost) << 2; /* Q(fbitsDQ) * Q(28) --> Q(fbitsDQ-2) */
r = SqrtFix(q, fbitsDQ - 2, &z);
z -= FBITS_OUT_QMFA; /* justify for adding to signal (xBuf) later */
if (z >= 0) {
psi->smBoost[m] = r >> MIN(31, z);
} else {
z = MIN(30, -z);
CLIP_2N_SHIFT30(r, z);
psi->smBoost[m] = r;
}
}
}
/**************************************************************************************
* Function: CalcGain
*
* Description: calculate and apply proper gain to HF components in one envelope
* (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
*
* Outputs: envelope gain, sinusoids and noise after scaling
*
* Return: none
**************************************************************************************/
static void CalcGain(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch, int env)
{
int lim, fbitsDQ;
/* initialize to -1 so that mapping limiter bands to env/noise bands works right on first pass */
psi->envBand = -1;
psi->noiseFloorBand = -1;
psi->sBand = -1;
psi->highBand = -1;
fbitsDQ = (FBITS_OUT_DQ_ENV - psi->envDataDequantScale[ch][env]); /* Q(29 - optional scalefactor) */
for (lim = 0; lim < sbrFreq->nLimiter; lim++) {
/* the QMF bands are divided into lim regions (consecutive, non-overlapping) */
CalcMaxGain(psi, sbrHdr, sbrGrid, sbrFreq, ch, env, lim, fbitsDQ);
CalcComponentGains(psi, sbrGrid, sbrFreq, sbrChan, ch, env, lim, fbitsDQ);
ApplyBoost(psi, sbrFreq, lim, fbitsDQ);
}
}
/* hSmooth table from 4.7.18.7.6, format = Q31 */
static const int hSmoothCoef[MAX_NUM_SMOOTH_COEFS] PROGMEM = {
0x2aaaaaab, 0x2697a512, 0x1becfa68, 0x0ebdb043, 0x04130598,
};
/**************************************************************************************
* Function: MapHF
*
* Description: map HF components to proper QMF bands, with optional gain smoothing
* filter (4.6.18.7.6)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current envelope
* reset flag (can be non-zero for first envelope only)
*
* Outputs: complete reconstructed subband QMF samples for this envelope
*
* Return: none
*
* Notes: ensures that output has >= MIN_GBITS_IN_QMFS guard bits,
* so it's not necessary to check anything in the synth QMF
**************************************************************************************/
static void MapHF(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int hfReset)
{
int noiseTabIndex, sinIndex, gainNoiseIndex, hSL;
int i, iStart, iEnd, m, idx, j, s, n, smre, smim;
int gFilt, qFilt, xre, xim, gbMask, gbIdx;
int *XBuf;
noiseTabIndex = sbrChan->noiseTabIndex;
sinIndex = sbrChan->sinIndex;
gainNoiseIndex = sbrChan->gainNoiseIndex; /* oldest entries in filter delay buffer */
if (hfReset)
noiseTabIndex = 2; /* starts at 1, double since complex */
hSL = (sbrHdr->smoothMode ? 0 : 4);
if (hfReset) {
for (i = 0; i < hSL; i++) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
sbrChan->gTemp[gainNoiseIndex][m] = psi->gLimBoost[m];
sbrChan->qTemp[gainNoiseIndex][m] = psi->qmLimBoost[m];
}
gainNoiseIndex++;
if (gainNoiseIndex == MAX_NUM_SMOOTH_COEFS)
gainNoiseIndex = 0;
}
ASSERT(env == 0); /* should only be reset when env == 0 */
}
iStart = sbrGrid->envTimeBorder[env];
iEnd = sbrGrid->envTimeBorder[env+1];
for (i = iStart; i < iEnd; i++) {
/* save new values in temp buffers (delay)
* we only store MAX_NUM_SMOOTH_COEFS most recent values,
* so don't keep storing the same value over and over
*/
if (i - iStart < MAX_NUM_SMOOTH_COEFS) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
sbrChan->gTemp[gainNoiseIndex][m] = psi->gLimBoost[m];
sbrChan->qTemp[gainNoiseIndex][m] = psi->qmLimBoost[m];
}
}
/* see 4.6.18.7.6 */
XBuf = psi->XBuf[i + HF_ADJ][sbrFreq->kStart];
gbMask = 0;
for (m = 0; m < sbrFreq->numQMFBands; m++) {
if (env == psi->la || env == sbrChan->laPrev) {
/* no smoothing filter for gain, and qFilt = 0 (only need to do once) */
if (i == iStart) {
psi->gFiltLast[m] = sbrChan->gTemp[gainNoiseIndex][m];
psi->qFiltLast[m] = 0;
}
} else if (hSL == 0) {
/* no smoothing filter for gain, (only need to do once) */
if (i == iStart) {
psi->gFiltLast[m] = sbrChan->gTemp[gainNoiseIndex][m];
psi->qFiltLast[m] = sbrChan->qTemp[gainNoiseIndex][m];
}
} else {
/* apply smoothing filter to gain and noise (after MAX_NUM_SMOOTH_COEFS, it's always the same) */
if (i - iStart < MAX_NUM_SMOOTH_COEFS) {
gFilt = 0;
qFilt = 0;
idx = gainNoiseIndex;
for (j = 0; j < MAX_NUM_SMOOTH_COEFS; j++) {
/* sum(abs(hSmoothCoef[j])) for all j < 1.0 */
gFilt += MULSHIFT32(sbrChan->gTemp[idx][m], hSmoothCoef[j]);
qFilt += MULSHIFT32(sbrChan->qTemp[idx][m], hSmoothCoef[j]);
idx--;
if (idx < 0)
idx += MAX_NUM_SMOOTH_COEFS;
}
psi->gFiltLast[m] = gFilt << 1; /* restore to Q(FBITS_GLIM_BOOST) (gain of filter < 1.0, so no overflow) */
psi->qFiltLast[m] = qFilt << 1; /* restore to Q(FBITS_QLIM_BOOST) */
}
}
if (psi->smBoost[m] != 0) {
/* add scaled signal and sinusoid, don't add noise (qFilt = 0) */
smre = psi->smBoost[m];
smim = smre;
/* sinIndex: [0] xre += sm [1] xim += sm*s [2] xre -= sm [3] xim -= sm*s */
s = (sinIndex >> 1); /* if 2 or 3, flip sign to subtract sm */
s <<= 31;
smre ^= (s >> 31);
smre -= (s >> 31);
s ^= ((m + sbrFreq->kStart) << 31);
smim ^= (s >> 31);
smim -= (s >> 31);
/* if sinIndex == 0 or 2, smim = 0; if sinIndex == 1 or 3, smre = 0 */
s = sinIndex << 31;
smim &= (s >> 31);
s ^= 0x80000000;
smre &= (s >> 31);
noiseTabIndex += 2; /* noise filtered by 0, but still need to bump index */
} else {
/* add scaled signal and scaled noise */
qFilt = psi->qFiltLast[m];
n = noiseTab[noiseTabIndex++];
smre = MULSHIFT32(n, qFilt) >> (FBITS_QLIM_BOOST - 1 - FBITS_OUT_QMFA);
n = noiseTab[noiseTabIndex++];
smim = MULSHIFT32(n, qFilt) >> (FBITS_QLIM_BOOST - 1 - FBITS_OUT_QMFA);
}
noiseTabIndex &= 1023; /* 512 complex numbers */
gFilt = psi->gFiltLast[m];
xre = MULSHIFT32(gFilt, XBuf[0]);
xim = MULSHIFT32(gFilt, XBuf[1]);
CLIP_2N_SHIFT30(xre, 32 - FBITS_GLIM_BOOST);
CLIP_2N_SHIFT30(xim, 32 - FBITS_GLIM_BOOST);
xre += smre; *XBuf++ = xre;
xim += smim; *XBuf++ = xim;
gbMask |= FASTABS(xre);
gbMask |= FASTABS(xim);
}
/* update circular buffer index */
gainNoiseIndex++;
if (gainNoiseIndex == MAX_NUM_SMOOTH_COEFS)
gainNoiseIndex = 0;
sinIndex++;
sinIndex &= 3;
/* ensure MIN_GBITS_IN_QMFS guard bits in output
* almost never occurs in practice, but checking here makes synth QMF logic very simple
*/
if (gbMask >> (31 - MIN_GBITS_IN_QMFS)) {
XBuf = psi->XBuf[i + HF_ADJ][sbrFreq->kStart];
for (m = 0; m < sbrFreq->numQMFBands; m++) {
xre = XBuf[0]; xim = XBuf[1];
CLIP_2N(xre, (31 - MIN_GBITS_IN_QMFS));
CLIP_2N(xim, (31 - MIN_GBITS_IN_QMFS));
*XBuf++ = xre; *XBuf++ = xim;
}
CLIP_2N(gbMask, (31 - MIN_GBITS_IN_QMFS));
}
gbIdx = ((i + HF_ADJ) >> 5) & 0x01;
sbrChan->gbMask[gbIdx] |= gbMask;
}
sbrChan->noiseTabIndex = noiseTabIndex;
sbrChan->sinIndex = sinIndex;
sbrChan->gainNoiseIndex = gainNoiseIndex;
}
/**************************************************************************************
* Function: AdjustHighFreq
*
* Description: adjust high frequencies and add noise and sinusoids (4.6.18.7)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: complete reconstructed subband QMF samples for this channel
*
* Return: none
**************************************************************************************/
void AdjustHighFreq(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int i, env, hfReset;
unsigned char frameClass, pointer;
frameClass = sbrGrid->frameClass;
pointer = sbrGrid->pointer;
/* derive la from table 4.159 */
if ((frameClass == SBR_GRID_FIXVAR || frameClass == SBR_GRID_VARVAR) && pointer > 0)
psi->la = sbrGrid->numEnv + 1 - pointer;
else if (frameClass == SBR_GRID_VARFIX && pointer > 1)
psi->la = pointer - 1;
else
psi->la = -1;
/* for each envelope, estimate gain and adjust SBR QMF bands */
hfReset = sbrChan->reset;
for (env = 0; env < sbrGrid->numEnv; env++) {
EstimateEnvelope(psi, sbrHdr, sbrGrid, sbrFreq, env);
CalcGain(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch, env);
MapHF(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, env, hfReset);
hfReset = 0; /* only set for first envelope after header reset */
}
/* set saved sine flags to 0 for QMF bands outside of current frequency range */
for (i = 0; i < sbrFreq->freqLimiter[0] + sbrFreq->kStart; i++)
sbrChan->addHarmonic[0][i] = 0;
for (i = sbrFreq->freqLimiter[sbrFreq->nLimiter] + sbrFreq->kStart; i < 64; i++)
sbrChan->addHarmonic[0][i] = 0;
sbrChan->addHarmonicFlag[0] = sbrChan->addHarmonicFlag[1];
/* save la for next frame */
if (psi->la == sbrGrid->numEnv)
sbrChan->laPrev = 0;
else
sbrChan->laPrev = -1;
}

View File

@@ -1,616 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrhfgen.c,v 1.2 2005/05/19 20:45:20 jrecker 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
*
* sbrhfgen.c - high frequency generation for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
#define FBITS_LPCOEFS 29 /* Q29 for range of (-4, 4) */
#define MAG_16 (16 * (1 << (32 - (2*(32-FBITS_LPCOEFS))))) /* i.e. 16 in Q26 format */
#define RELAX_COEF 0x7ffff79c /* 1.0 / (1.0 + 1e-6), Q31 */
/* newBWTab[prev invfMode][curr invfMode], format = Q31 (table 4.158)
* sample file which uses all of these: al_sbr_sr_64_2_fsaac32.aac
*/
static const int newBWTab[4][4] PROGMEM = {
{0x00000000, 0x4ccccccd, 0x73333333, 0x7d70a3d7},
{0x4ccccccd, 0x60000000, 0x73333333, 0x7d70a3d7},
{0x00000000, 0x60000000, 0x73333333, 0x7d70a3d7},
{0x00000000, 0x60000000, 0x73333333, 0x7d70a3d7},
};
/**************************************************************************************
* Function: CVKernel1
*
* Description: kernel of covariance matrix calculation for p01, p11, p12, p22
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
*
* Outputs: 64-bit accumulators for p01re, p01im, p12re, p12im, p11re, p22re
* stored in accBuf
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrcov.s when building for ARM!
**************************************************************************************/
#if (defined (XXXX__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(XXXX__arm__))
#ifdef __cplusplus
extern "C"
#endif
void CVKernel1(int *XBuf, int *accBuf);
#else
void CVKernel1(int *XBuf, int *accBuf)
{
U64 p01re, p01im, p12re, p12im, p11re, p22re;
int n, x0re, x0im, x1re, x1im;
x0re = XBuf[0];
x0im = XBuf[1];
XBuf += (2*64);
x1re = XBuf[0];
x1im = XBuf[1];
XBuf += (2*64);
p01re.w64 = p01im.w64 = 0;
p12re.w64 = p12im.w64 = 0;
p11re.w64 = 0;
p22re.w64 = 0;
p12re.w64 = MADD64(p12re.w64, x1re, x0re);
p12re.w64 = MADD64(p12re.w64, x1im, x0im);
p12im.w64 = MADD64(p12im.w64, x0re, x1im);
p12im.w64 = MADD64(p12im.w64, -x0im, x1re);
p22re.w64 = MADD64(p22re.w64, x0re, x0re);
p22re.w64 = MADD64(p22re.w64, x0im, x0im);
for (n = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6); n != 0; n--) {
/* 4 input, 3*2 acc, 1 ptr, 1 loop counter = 12 registers (use same for x0im, -x0im) */
x0re = x1re;
x0im = x1im;
x1re = XBuf[0];
x1im = XBuf[1];
p01re.w64 = MADD64(p01re.w64, x1re, x0re);
p01re.w64 = MADD64(p01re.w64, x1im, x0im);
p01im.w64 = MADD64(p01im.w64, x0re, x1im);
p01im.w64 = MADD64(p01im.w64, -x0im, x1re);
p11re.w64 = MADD64(p11re.w64, x0re, x0re);
p11re.w64 = MADD64(p11re.w64, x0im, x0im);
XBuf += (2*64);
}
/* these can be derived by slight changes to account for boundary conditions */
p12re.w64 += p01re.w64;
p12re.w64 = MADD64(p12re.w64, x1re, -x0re);
p12re.w64 = MADD64(p12re.w64, x1im, -x0im);
p12im.w64 += p01im.w64;
p12im.w64 = MADD64(p12im.w64, x0re, -x1im);
p12im.w64 = MADD64(p12im.w64, x0im, x1re);
p22re.w64 += p11re.w64;
p22re.w64 = MADD64(p22re.w64, x0re, -x0re);
p22re.w64 = MADD64(p22re.w64, x0im, -x0im);
accBuf[0] = p01re.r.lo32; accBuf[1] = p01re.r.hi32;
accBuf[2] = p01im.r.lo32; accBuf[3] = p01im.r.hi32;
accBuf[4] = p11re.r.lo32; accBuf[5] = p11re.r.hi32;
accBuf[6] = p12re.r.lo32; accBuf[7] = p12re.r.hi32;
accBuf[8] = p12im.r.lo32; accBuf[9] = p12im.r.hi32;
accBuf[10] = p22re.r.lo32; accBuf[11] = p22re.r.hi32;
}
#endif
/**************************************************************************************
* Function: CalcCovariance1
*
* Description: calculate covariance matrix for p01, p12, p11, p22 (4.6.18.6.2)
*
* Inputs: buffer of low-freq samples, starting at time index 0,
* freq index = patch subband
*
* Outputs: complex covariance elements p01re, p01im, p12re, p12im, p11re, p22re
* (p11im = p22im = 0)
* format = integer (Q0) * 2^N, with scalefactor N >= 0
*
* Return: scalefactor N
*
* Notes: outputs are normalized to have 1 GB (sign in at least top 2 bits)
**************************************************************************************/
static int CalcCovariance1(int *XBuf, int *p01reN, int *p01imN, int *p12reN, int *p12imN, int *p11reN, int *p22reN)
{
int accBuf[2*6];
int n, z, s, loShift, hiShift, gbMask;
U64 p01re, p01im, p12re, p12im, p11re, p22re;
CVKernel1(XBuf, accBuf);
p01re.r.lo32 = accBuf[0]; p01re.r.hi32 = accBuf[1];
p01im.r.lo32 = accBuf[2]; p01im.r.hi32 = accBuf[3];
p11re.r.lo32 = accBuf[4]; p11re.r.hi32 = accBuf[5];
p12re.r.lo32 = accBuf[6]; p12re.r.hi32 = accBuf[7];
p12im.r.lo32 = accBuf[8]; p12im.r.hi32 = accBuf[9];
p22re.r.lo32 = accBuf[10]; p22re.r.hi32 = accBuf[11];
/* 64-bit accumulators now have 2*FBITS_OUT_QMFA fraction bits
* want to scale them down to integers (32-bit signed, Q0)
* with scale factor of 2^n, n >= 0
* leave 2 GB's for calculating determinant, so take top 30 non-zero bits
*/
gbMask = ((p01re.r.hi32) ^ (p01re.r.hi32 >> 31)) | ((p01im.r.hi32) ^ (p01im.r.hi32 >> 31));
gbMask |= ((p12re.r.hi32) ^ (p12re.r.hi32 >> 31)) | ((p12im.r.hi32) ^ (p12im.r.hi32 >> 31));
gbMask |= ((p11re.r.hi32) ^ (p11re.r.hi32 >> 31)) | ((p22re.r.hi32) ^ (p22re.r.hi32 >> 31));
if (gbMask == 0) {
s = p01re.r.hi32 >> 31; gbMask = (p01re.r.lo32 ^ s) - s;
s = p01im.r.hi32 >> 31; gbMask |= (p01im.r.lo32 ^ s) - s;
s = p12re.r.hi32 >> 31; gbMask |= (p12re.r.lo32 ^ s) - s;
s = p12im.r.hi32 >> 31; gbMask |= (p12im.r.lo32 ^ s) - s;
s = p11re.r.hi32 >> 31; gbMask |= (p11re.r.lo32 ^ s) - s;
s = p22re.r.hi32 >> 31; gbMask |= (p22re.r.lo32 ^ s) - s;
z = 32 + CLZ(gbMask);
} else {
gbMask = FASTABS(p01re.r.hi32) | FASTABS(p01im.r.hi32);
gbMask |= FASTABS(p12re.r.hi32) | FASTABS(p12im.r.hi32);
gbMask |= FASTABS(p11re.r.hi32) | FASTABS(p22re.r.hi32);
z = CLZ(gbMask);
}
n = 64 - z; /* number of non-zero bits in bottom of 64-bit word */
if (n <= 30) {
loShift = (30 - n);
*p01reN = p01re.r.lo32 << loShift; *p01imN = p01im.r.lo32 << loShift;
*p12reN = p12re.r.lo32 << loShift; *p12imN = p12im.r.lo32 << loShift;
*p11reN = p11re.r.lo32 << loShift; *p22reN = p22re.r.lo32 << loShift;
return -(loShift + 2*FBITS_OUT_QMFA);
} else if (n < 32 + 30) {
loShift = (n - 30);
hiShift = 32 - loShift;
*p01reN = (p01re.r.hi32 << hiShift) | (p01re.r.lo32 >> loShift);
*p01imN = (p01im.r.hi32 << hiShift) | (p01im.r.lo32 >> loShift);
*p12reN = (p12re.r.hi32 << hiShift) | (p12re.r.lo32 >> loShift);
*p12imN = (p12im.r.hi32 << hiShift) | (p12im.r.lo32 >> loShift);
*p11reN = (p11re.r.hi32 << hiShift) | (p11re.r.lo32 >> loShift);
*p22reN = (p22re.r.hi32 << hiShift) | (p22re.r.lo32 >> loShift);
return (loShift - 2*FBITS_OUT_QMFA);
} else {
hiShift = n - (32 + 30);
*p01reN = p01re.r.hi32 >> hiShift; *p01imN = p01im.r.hi32 >> hiShift;
*p12reN = p12re.r.hi32 >> hiShift; *p12imN = p12im.r.hi32 >> hiShift;
*p11reN = p11re.r.hi32 >> hiShift; *p22reN = p22re.r.hi32 >> hiShift;
return (32 - 2*FBITS_OUT_QMFA - hiShift);
}
return 0;
}
/**************************************************************************************
* Function: CVKernel2
*
* Description: kernel of covariance matrix calculation for p02
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
*
* Outputs: 64-bit accumulators for p02re, p02im stored in accBuf
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrcov.s when building for ARM!
**************************************************************************************/
#if (defined (XXXX__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(XXXX__arm__))
#ifdef __cplusplus
extern "C"
#endif
void CVKernel2(int *XBuf, int *accBuf);
#else
void CVKernel2(int *XBuf, int *accBuf)
{
U64 p02re, p02im;
int n, x0re, x0im, x1re, x1im, x2re, x2im;
p02re.w64 = p02im.w64 = 0;
x0re = XBuf[0];
x0im = XBuf[1];
XBuf += (2*64);
x1re = XBuf[0];
x1im = XBuf[1];
XBuf += (2*64);
for (n = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6); n != 0; n--) {
/* 6 input, 2*2 acc, 1 ptr, 1 loop counter = 12 registers (use same for x0im, -x0im) */
x2re = XBuf[0];
x2im = XBuf[1];
p02re.w64 = MADD64(p02re.w64, x2re, x0re);
p02re.w64 = MADD64(p02re.w64, x2im, x0im);
p02im.w64 = MADD64(p02im.w64, x0re, x2im);
p02im.w64 = MADD64(p02im.w64, -x0im, x2re);
x0re = x1re;
x0im = x1im;
x1re = x2re;
x1im = x2im;
XBuf += (2*64);
}
accBuf[0] = p02re.r.lo32;
accBuf[1] = p02re.r.hi32;
accBuf[2] = p02im.r.lo32;
accBuf[3] = p02im.r.hi32;
}
#endif
/**************************************************************************************
* Function: CalcCovariance2
*
* Description: calculate covariance matrix for p02 (4.6.18.6.2)
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
*
* Outputs: complex covariance element p02re, p02im
* format = integer (Q0) * 2^N, with scalefactor N >= 0
*
* Return: scalefactor N
*
* Notes: outputs are normalized to have 1 GB (sign in at least top 2 bits)
**************************************************************************************/
static int CalcCovariance2(int *XBuf, int *p02reN, int *p02imN)
{
U64 p02re, p02im;
int n, z, s, loShift, hiShift, gbMask;
int accBuf[2*2];
CVKernel2(XBuf, accBuf);
p02re.r.lo32 = accBuf[0];
p02re.r.hi32 = accBuf[1];
p02im.r.lo32 = accBuf[2];
p02im.r.hi32 = accBuf[3];
/* 64-bit accumulators now have 2*FBITS_OUT_QMFA fraction bits
* want to scale them down to integers (32-bit signed, Q0)
* with scale factor of 2^n, n >= 0
* leave 1 GB for calculating determinant, so take top 30 non-zero bits
*/
gbMask = ((p02re.r.hi32) ^ (p02re.r.hi32 >> 31)) | ((p02im.r.hi32) ^ (p02im.r.hi32 >> 31));
if (gbMask == 0) {
s = p02re.r.hi32 >> 31; gbMask = (p02re.r.lo32 ^ s) - s;
s = p02im.r.hi32 >> 31; gbMask |= (p02im.r.lo32 ^ s) - s;
z = 32 + CLZ(gbMask);
} else {
gbMask = FASTABS(p02re.r.hi32) | FASTABS(p02im.r.hi32);
z = CLZ(gbMask);
}
n = 64 - z; /* number of non-zero bits in bottom of 64-bit word */
if (n <= 30) {
loShift = (30 - n);
*p02reN = p02re.r.lo32 << loShift;
*p02imN = p02im.r.lo32 << loShift;
return -(loShift + 2*FBITS_OUT_QMFA);
} else if (n < 32 + 30) {
loShift = (n - 30);
hiShift = 32 - loShift;
*p02reN = (p02re.r.hi32 << hiShift) | (p02re.r.lo32 >> loShift);
*p02imN = (p02im.r.hi32 << hiShift) | (p02im.r.lo32 >> loShift);
return (loShift - 2*FBITS_OUT_QMFA);
} else {
hiShift = n - (32 + 30);
*p02reN = p02re.r.hi32 >> hiShift;
*p02imN = p02im.r.hi32 >> hiShift;
return (32 - 2*FBITS_OUT_QMFA - hiShift);
}
return 0;
}
/**************************************************************************************
* Function: CalcLPCoefs
*
* Description: calculate linear prediction coefficients for one subband (4.6.18.6.2)
*
* Inputs: buffer of low-freq samples, starting at time index = 0,
* freq index = patch subband
* number of guard bits in input sample buffer
*
* Outputs: complex LP coefficients a0re, a0im, a1re, a1im, format = Q29
*
* Return: none
*
* Notes: output coefficients (a0re, a0im, a1re, a1im) clipped to range (-4, 4)
* if the comples coefficients have magnitude >= 4.0, they are all
* set to 0 (see spec)
**************************************************************************************/
static void CalcLPCoefs(int *XBuf, int *a0re, int *a0im, int *a1re, int *a1im, int gb)
{
int zFlag, n1, n2, nd, d, dInv, tre, tim;
int p01re, p01im, p02re, p02im, p12re, p12im, p11re, p22re;
/* pre-scale to avoid overflow - probably never happens in practice (see QMFA)
* max bit growth per accumulator = 38*2 = 76 mul-adds (X * X)
* using 64-bit MADD, so if X has n guard bits, X*X has 2n+1 guard bits
* gain 1 extra sign bit per multiply, so ensure ceil(log2(76/2) / 2) = 3 guard bits on inputs
*/
if (gb < 3) {
nd = 3 - gb;
for (n1 = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6 + 2); n1 != 0; n1--) {
XBuf[0] >>= nd; XBuf[1] >>= nd;
XBuf += (2*64);
}
XBuf -= (2*64*(NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6 + 2));
}
/* calculate covariance elements */
n1 = CalcCovariance1(XBuf, &p01re, &p01im, &p12re, &p12im, &p11re, &p22re);
n2 = CalcCovariance2(XBuf, &p02re, &p02im);
/* normalize everything to larger power of 2 scalefactor, call it n1 */
if (n1 < n2) {
nd = MIN(n2 - n1, 31);
p01re >>= nd; p01im >>= nd;
p12re >>= nd; p12im >>= nd;
p11re >>= nd; p22re >>= nd;
n1 = n2;
} else if (n1 > n2) {
nd = MIN(n1 - n2, 31);
p02re >>= nd; p02im >>= nd;
}
/* calculate determinant of covariance matrix (at least 1 GB in pXX) */
d = MULSHIFT32(p12re, p12re) + MULSHIFT32(p12im, p12im);
d = MULSHIFT32(d, RELAX_COEF) << 1;
d = MULSHIFT32(p11re, p22re) - d;
ASSERT(d >= 0); /* should never be < 0 */
zFlag = 0;
*a0re = *a0im = 0;
*a1re = *a1im = 0;
if (d > 0) {
/* input = Q31 d = Q(-2*n1 - 32 + nd) = Q31 * 2^(31 + 2*n1 + 32 - nd)
* inverse = Q29 dInv = Q29 * 2^(-31 - 2*n1 - 32 + nd) = Q(29 + 31 + 2*n1 + 32 - nd)
*
* numerator has same Q format as d, since it's sum of normalized squares
* so num * inverse = Q(-2*n1 - 32) * Q(29 + 31 + 2*n1 + 32 - nd)
* = Q(29 + 31 - nd), drop low 32 in MULSHIFT32
* = Q(29 + 31 - 32 - nd) = Q(28 - nd)
*/
nd = CLZ(d) - 1;
d <<= nd;
dInv = InvRNormalized(d);
/* 1 GB in pXX */
tre = MULSHIFT32(p01re, p12re) - MULSHIFT32(p01im, p12im) - MULSHIFT32(p02re, p11re);
tre = MULSHIFT32(tre, dInv);
tim = MULSHIFT32(p01re, p12im) + MULSHIFT32(p01im, p12re) - MULSHIFT32(p02im, p11re);
tim = MULSHIFT32(tim, dInv);
/* if d is extremely small, just set coefs to 0 (would have poor precision anyway) */
if (nd > 28 || (FASTABS(tre) >> (28 - nd)) >= 4 || (FASTABS(tim) >> (28 - nd)) >= 4) {
zFlag = 1;
} else {
*a1re = tre << (FBITS_LPCOEFS - 28 + nd); /* i.e. convert Q(28 - nd) to Q(29) */
*a1im = tim << (FBITS_LPCOEFS - 28 + nd);
}
}
if (p11re) {
/* input = Q31 p11re = Q(-n1 + nd) = Q31 * 2^(31 + n1 - nd)
* inverse = Q29 dInv = Q29 * 2^(-31 - n1 + nd) = Q(29 + 31 + n1 - nd)
*
* numerator is Q(-n1 - 3)
* so num * inverse = Q(-n1 - 3) * Q(29 + 31 + n1 - nd)
* = Q(29 + 31 - 3 - nd), drop low 32 in MULSHIFT32
* = Q(29 + 31 - 3 - 32 - nd) = Q(25 - nd)
*/
nd = CLZ(p11re) - 1; /* assume positive */
p11re <<= nd;
dInv = InvRNormalized(p11re);
/* a1re, a1im = Q29, so scaled by (n1 + 3) */
tre = (p01re >> 3) + MULSHIFT32(p12re, *a1re) + MULSHIFT32(p12im, *a1im);
tre = -MULSHIFT32(tre, dInv);
tim = (p01im >> 3) - MULSHIFT32(p12im, *a1re) + MULSHIFT32(p12re, *a1im);
tim = -MULSHIFT32(tim, dInv);
if (nd > 25 || (FASTABS(tre) >> (25 - nd)) >= 4 || (FASTABS(tim) >> (25 - nd)) >= 4) {
zFlag = 1;
} else {
*a0re = tre << (FBITS_LPCOEFS - 25 + nd); /* i.e. convert Q(25 - nd) to Q(29) */
*a0im = tim << (FBITS_LPCOEFS - 25 + nd);
}
}
/* see 4.6.18.6.2 - if magnitude of a0 or a1 >= 4 then a0 = a1 = 0
* i.e. a0re < 4, a0im < 4, a1re < 4, a1im < 4
* Q29*Q29 = Q26
*/
if (zFlag || MULSHIFT32(*a0re, *a0re) + MULSHIFT32(*a0im, *a0im) >= MAG_16 || MULSHIFT32(*a1re, *a1re) + MULSHIFT32(*a1im, *a1im) >= MAG_16) {
*a0re = *a0im = 0;
*a1re = *a1im = 0;
}
/* no need to clip - we never changed the XBuf data, just used it to calculate a0 and a1 */
if (gb < 3) {
nd = 3 - gb;
for (n1 = (NUM_TIME_SLOTS*SAMPLES_PER_SLOT + 6 + 2); n1 != 0; n1--) {
XBuf[0] <<= nd; XBuf[1] <<= nd;
XBuf += (2*64);
}
}
}
/**************************************************************************************
* Function: GenerateHighFreq
*
* Description: generate high frequencies with SBR (4.6.18.6)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: new high frequency samples starting at frequency kStart
*
* Return: none
**************************************************************************************/
void GenerateHighFreq(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int band, newBW, c, t, gb, gbMask, gbIdx;
int currPatch, p, x, k, g, i, iStart, iEnd, bw, bwsq;
int a0re, a0im, a1re, a1im;
int x1re, x1im, x2re, x2im;
int ACCre, ACCim;
int *XBufLo, *XBufHi;
(void) ch;
/* calculate array of chirp factors */
for (band = 0; band < sbrFreq->numNoiseFloorBands; band++) {
c = sbrChan->chirpFact[band]; /* previous (bwArray') */
newBW = newBWTab[sbrChan->invfMode[0][band]][sbrChan->invfMode[1][band]];
/* weighted average of new and old (can't overflow - total gain = 1.0) */
if (newBW < c)
t = MULSHIFT32(newBW, 0x60000000) + MULSHIFT32(0x20000000, c); /* new is smaller: 0.75*new + 0.25*old */
else
t = MULSHIFT32(newBW, 0x74000000) + MULSHIFT32(0x0c000000, c); /* new is larger: 0.90625*new + 0.09375*old */
t <<= 1;
if (t < 0x02000000) /* below 0.015625, clip to 0 */
t = 0;
if (t > 0x7f800000) /* clip to 0.99609375 */
t = 0x7f800000;
/* save curr as prev for next time */
sbrChan->chirpFact[band] = t;
sbrChan->invfMode[0][band] = sbrChan->invfMode[1][band];
}
iStart = sbrGrid->envTimeBorder[0] + HF_ADJ;
iEnd = sbrGrid->envTimeBorder[sbrGrid->numEnv] + HF_ADJ;
/* generate new high freqs from low freqs, patches, and chirp factors */
k = sbrFreq->kStart;
g = 0;
bw = sbrChan->chirpFact[g];
bwsq = MULSHIFT32(bw, bw) << 1;
gbMask = (sbrChan->gbMask[0] | sbrChan->gbMask[1]); /* older 32 | newer 8 */
gb = CLZ(gbMask) - 1;
for (currPatch = 0; currPatch < sbrFreq->numPatches; currPatch++) {
for (x = 0; x < sbrFreq->patchNumSubbands[currPatch]; x++) {
/* map k to corresponding noise floor band */
if (k >= sbrFreq->freqNoise[g+1]) {
g++;
bw = sbrChan->chirpFact[g]; /* Q31 */
bwsq = MULSHIFT32(bw, bw) << 1; /* Q31 */
}
p = sbrFreq->patchStartSubband[currPatch] + x; /* low QMF band */
XBufHi = psi->XBuf[iStart][k];
if (bw) {
CalcLPCoefs(psi->XBuf[0][p], &a0re, &a0im, &a1re, &a1im, gb);
a0re = MULSHIFT32(bw, a0re); /* Q31 * Q29 = Q28 */
a0im = MULSHIFT32(bw, a0im);
a1re = MULSHIFT32(bwsq, a1re);
a1im = MULSHIFT32(bwsq, a1im);
XBufLo = psi->XBuf[iStart-2][p];
x2re = XBufLo[0]; /* RE{XBuf[n-2]} */
x2im = XBufLo[1]; /* IM{XBuf[n-2]} */
XBufLo += (64*2);
x1re = XBufLo[0]; /* RE{XBuf[n-1]} */
x1im = XBufLo[1]; /* IM{XBuf[n-1]} */
XBufLo += (64*2);
for (i = iStart; i < iEnd; i++) {
/* a0re/im, a1re/im are Q28 with at least 1 GB,
* so the summing for AACre/im is fine (1 GB in, plus 1 from MULSHIFT32)
*/
ACCre = MULSHIFT32(x2re, a1re) - MULSHIFT32(x2im, a1im);
ACCim = MULSHIFT32(x2re, a1im) + MULSHIFT32(x2im, a1re);
x2re = x1re;
x2im = x1im;
ACCre += MULSHIFT32(x1re, a0re) - MULSHIFT32(x1im, a0im);
ACCim += MULSHIFT32(x1re, a0im) + MULSHIFT32(x1im, a0re);
x1re = XBufLo[0]; /* RE{XBuf[n]} */
x1im = XBufLo[1]; /* IM{XBuf[n]} */
XBufLo += (64*2);
/* lost 4 fbits when scaling by a0re/im, a1re/im (Q28) */
CLIP_2N_SHIFT30(ACCre, 4);
ACCre += x1re;
CLIP_2N_SHIFT30(ACCim, 4);
ACCim += x1im;
XBufHi[0] = ACCre;
XBufHi[1] = ACCim;
XBufHi += (64*2);
/* update guard bit masks */
gbMask = FASTABS(ACCre);
gbMask |= FASTABS(ACCim);
gbIdx = (i >> 5) & 0x01; /* 0 if i < 32, 1 if i >= 32 */
sbrChan->gbMask[gbIdx] |= gbMask;
}
} else {
XBufLo = (int *)psi->XBuf[iStart][p];
for (i = iStart; i < iEnd; i++) {
XBufHi[0] = XBufLo[0];
XBufHi[1] = XBufLo[1];
XBufLo += (64*2);
XBufHi += (64*2);
}
}
k++; /* high QMF band */
}
}
}

View File

@@ -1,476 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrhuff.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrhuff.c - functions for unpacking Huffman-coded envelope and noise data
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/**************************************************************************************
* Function: DecodeHuffmanScalar
*
* Description: decode one Huffman symbol from bitstream
*
* Inputs: pointers to Huffman table and info struct
* left-aligned bit buffer with >= huffTabInfo->maxBits bits
*
* Outputs: decoded symbol in *val
*
* Return: number of bits in symbol
*
* Notes: assumes canonical Huffman codes:
* first CW always 0, we have "count" CW's of length "nBits" bits
* starting CW for codes of length nBits+1 =
* (startCW[nBits] + count[nBits]) << 1
* if there are no codes at nBits, then we just keep << 1 each time
* (since count[nBits] = 0)
**************************************************************************************/
static int DecodeHuffmanScalar(const signed /*short*/ int *huffTab, const HuffInfo *huffTabInfo, unsigned int bitBuf, signed int *val)
{
unsigned int count, start, shift, t;
const unsigned int /*char*/ *countPtr;
const signed int /*short*/ *map;
map = huffTab + huffTabInfo->offset;
countPtr = huffTabInfo->count;
start = 0;
count = 0;
shift = 32;
do {
start += count;
start <<= 1;
map += count;
count = *countPtr++;
shift--;
t = (bitBuf >> shift) - start;
} while (t >= count);
*val = (signed int)map[t];
return (countPtr - huffTabInfo->count);
}
/**************************************************************************************
* Function: DecodeOneSymbol
*
* Description: dequantize one Huffman symbol from bitstream,
* using table huffTabSBR[huffTabIndex]
*
* Inputs: BitStreamInfo struct pointing to start of next Huffman codeword
* index of Huffman table
*
* Outputs: bitstream advanced by number of bits in codeword
*
* Return: one decoded symbol
**************************************************************************************/
static int DecodeOneSymbol(BitStreamInfo *bsi, int huffTabIndex)
{
int nBits, val;
unsigned int bitBuf;
const HuffInfo *hi;
hi = &(huffTabSBRInfo[huffTabIndex]);
bitBuf = GetBitsNoAdvance(bsi, hi->maxBits) << (32 - hi->maxBits);
nBits = DecodeHuffmanScalar(huffTabSBR, hi, bitBuf, &val);
AdvanceBitstream(bsi, nBits);
return val;
}
/* [1.0, sqrt(2)], format = Q29 (one guard bit for decoupling) */
static const int envDQTab[2] PROGMEM = {0x20000000, 0x2d413ccc};
/**************************************************************************************
* Function: DequantizeEnvelope
*
* Description: dequantize envelope scalefactors
*
* Inputs: number of scalefactors to process
* amplitude resolution flag for this frame (0 or 1)
* quantized envelope scalefactors
*
* Outputs: dequantized envelope scalefactors
*
* Return: extra int bits in output (6 + expMax)
* in other words, output format = Q(FBITS_OUT_DQ_ENV - (6 + expMax))
*
* Notes: dequantized scalefactors have at least 2 GB
**************************************************************************************/
static int DequantizeEnvelope(int nBands, int ampRes, signed char *envQuant, int *envDequant)
{
int exp, expMax, i, scalei;
if (nBands <= 0)
return 0;
/* scan for largest dequant value (do separately from envelope decoding to keep code cleaner) */
expMax = 0;
for (i = 0; i < nBands; i++) {
if (envQuant[i] > expMax)
expMax = envQuant[i];
}
/* dequantized envelope gains
* envDequant = 64*2^(envQuant / alpha) = 2^(6 + envQuant / alpha)
* if ampRes == 0, alpha = 2 and range of envQuant = [0, 127]
* if ampRes == 1, alpha = 1 and range of envQuant = [0, 63]
* also if coupling is on, envDequant is scaled by something in range [0, 2]
* so range of envDequant = [2^6, 2^69] (no coupling), [2^6, 2^70] (with coupling)
*
* typical range (from observation) of envQuant/alpha = [0, 27] --> largest envQuant ~= 2^33
* output: Q(29 - (6 + expMax))
*
* reference: 14496-3:2001(E)/4.6.18.3.5 and 14496-4:200X/FPDAM8/5.6.5.1.2.1.5
*/
if (ampRes) {
do {
exp = *envQuant++;
scalei = MIN(expMax - exp, 31);
*envDequant++ = envDQTab[0] >> scalei;
} while (--nBands);
return (6 + expMax);
} else {
expMax >>= 1;
do {
exp = *envQuant++;
scalei = MIN(expMax - (exp >> 1), 31);
*envDequant++ = envDQTab[exp & 0x01] >> scalei;
} while (--nBands);
return (6 + expMax);
}
}
/**************************************************************************************
* Function: DequantizeNoise
*
* Description: dequantize noise scalefactors
*
* Inputs: number of scalefactors to process
* quantized noise scalefactors
*
* Outputs: dequantized noise scalefactors, format = Q(FBITS_OUT_DQ_NOISE)
*
* Return: none
*
* Notes: dequantized scalefactors have at least 2 GB
**************************************************************************************/
static void DequantizeNoise(int nBands, signed char *noiseQuant, int *noiseDequant)
{
int exp, scalei;
if (nBands <= 0)
return;
/* dequantize noise floor gains (4.6.18.3.5):
* noiseDequant = 2^(NOISE_FLOOR_OFFSET - noiseQuant)
*
* range of noiseQuant = [0, 30] (see 4.6.18.3.6), NOISE_FLOOR_OFFSET = 6
* so range of noiseDequant = [2^-24, 2^6]
*/
do {
exp = *noiseQuant++;
scalei = NOISE_FLOOR_OFFSET - exp + FBITS_OUT_DQ_NOISE; /* 6 + 24 - exp, exp = [0,30] */
if (scalei < 0)
*noiseDequant++ = 0;
else if (scalei < 30)
*noiseDequant++ = 1 << scalei;
else
*noiseDequant++ = 0x3fffffff; /* leave 2 GB */
} while (--nBands);
}
/**************************************************************************************
* Function: DecodeSBREnvelope
*
* Description: decode delta Huffman coded envelope scalefactors from bitstream
*
* Inputs: BitStreamInfo struct pointing to start of env data
* initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: dequantized env scalefactors for left channel (before decoupling)
* dequantized env scalefactors for right channel (if coupling off)
* or raw decoded env scalefactors for right channel (if coupling on)
*
* Return: none
**************************************************************************************/
void DecodeSBREnvelope(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int huffIndexTime, huffIndexFreq, env, envStartBits, band, nBands, sf, lastEnv;
int freqRes, freqResPrev, dShift, i;
if (psi->couplingFlag && ch) {
dShift = 1;
if (sbrGrid->ampResFrame) {
huffIndexTime = HuffTabSBR_tEnv30b;
huffIndexFreq = HuffTabSBR_fEnv30b;
envStartBits = 5;
} else {
huffIndexTime = HuffTabSBR_tEnv15b;
huffIndexFreq = HuffTabSBR_fEnv15b;
envStartBits = 6;
}
} else {
dShift = 0;
if (sbrGrid->ampResFrame) {
huffIndexTime = HuffTabSBR_tEnv30;
huffIndexFreq = HuffTabSBR_fEnv30;
envStartBits = 6;
} else {
huffIndexTime = HuffTabSBR_tEnv15;
huffIndexFreq = HuffTabSBR_fEnv15;
envStartBits = 7;
}
}
/* range of envDataQuant[] = [0, 127] (see comments in DequantizeEnvelope() for reference) */
for (env = 0; env < sbrGrid->numEnv; env++) {
nBands = (sbrGrid->freqRes[env] ? sbrFreq->nHigh : sbrFreq->nLow);
freqRes = (sbrGrid->freqRes[env]);
freqResPrev = (env == 0 ? sbrGrid->freqResPrev : sbrGrid->freqRes[env-1]);
lastEnv = (env == 0 ? sbrGrid->numEnvPrev-1 : env-1);
if (lastEnv < 0)
lastEnv = 0; /* first frame */
ASSERT(nBands <= MAX_QMF_BANDS);
if (sbrChan->deltaFlagEnv[env] == 0) {
/* delta coding in freq */
sf = GetBits(bsi, envStartBits) << dShift;
sbrChan->envDataQuant[env][0] = sf;
for (band = 1; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexFreq) << dShift;
sbrChan->envDataQuant[env][band] = sf + sbrChan->envDataQuant[env][band-1];
}
} else if (freqRes == freqResPrev) {
/* delta coding in time - same freq resolution for both frames */
for (band = 0; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->envDataQuant[env][band] = sf + sbrChan->envDataQuant[lastEnv][band];
}
} else if (freqRes == 0 && freqResPrev == 1) {
/* delta coding in time - low freq resolution for new frame, high freq resolution for old frame */
for (band = 0; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->envDataQuant[env][band] = sf;
for (i = 0; i < sbrFreq->nHigh; i++) {
if (sbrFreq->freqHigh[i] == sbrFreq->freqLow[band]) {
sbrChan->envDataQuant[env][band] += sbrChan->envDataQuant[lastEnv][i];
break;
}
}
}
} else if (freqRes == 1 && freqResPrev == 0) {
/* delta coding in time - high freq resolution for new frame, low freq resolution for old frame */
for (band = 0; band < nBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->envDataQuant[env][band] = sf;
for (i = 0; i < sbrFreq->nLow; i++) {
if (sbrFreq->freqLow[i] <= sbrFreq->freqHigh[band] && sbrFreq->freqHigh[band] < sbrFreq->freqLow[i+1] ) {
sbrChan->envDataQuant[env][band] += sbrChan->envDataQuant[lastEnv][i];
break;
}
}
}
}
/* skip coupling channel */
if (ch != 1 || psi->couplingFlag != 1)
psi->envDataDequantScale[ch][env] = DequantizeEnvelope(nBands, sbrGrid->ampResFrame, sbrChan->envDataQuant[env], psi->envDataDequant[ch][env]);
}
sbrGrid->numEnvPrev = sbrGrid->numEnv;
sbrGrid->freqResPrev = sbrGrid->freqRes[sbrGrid->numEnv-1];
}
/**************************************************************************************
* Function: DecodeSBRNoise
*
* Description: decode delta Huffman coded noise scalefactors from bitstream
*
* Inputs: BitStreamInfo struct pointing to start of noise data
* initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: dequantized noise scalefactors for left channel (before decoupling)
* dequantized noise scalefactors for right channel (if coupling off)
* or raw decoded noise scalefactors for right channel (if coupling on)
*
* Return: none
**************************************************************************************/
void DecodeSBRNoise(BitStreamInfo *bsi, PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int huffIndexTime, huffIndexFreq, noiseFloor, band, dShift, sf, lastNoiseFloor;
if (psi->couplingFlag && ch) {
dShift = 1;
huffIndexTime = HuffTabSBR_tNoise30b;
huffIndexFreq = HuffTabSBR_fNoise30b;
} else {
dShift = 0;
huffIndexTime = HuffTabSBR_tNoise30;
huffIndexFreq = HuffTabSBR_fNoise30;
}
for (noiseFloor = 0; noiseFloor < sbrGrid->numNoiseFloors; noiseFloor++) {
lastNoiseFloor = (noiseFloor == 0 ? sbrGrid->numNoiseFloorsPrev-1 : noiseFloor-1);
if (lastNoiseFloor < 0)
lastNoiseFloor = 0; /* first frame */
ASSERT(sbrFreq->numNoiseFloorBands <= MAX_QMF_BANDS);
if (sbrChan->deltaFlagNoise[noiseFloor] == 0) {
/* delta coding in freq */
sbrChan->noiseDataQuant[noiseFloor][0] = GetBits(bsi, 5) << dShift;
for (band = 1; band < sbrFreq->numNoiseFloorBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexFreq) << dShift;
sbrChan->noiseDataQuant[noiseFloor][band] = sf + sbrChan->noiseDataQuant[noiseFloor][band-1];
}
} else {
/* delta coding in time */
for (band = 0; band < sbrFreq->numNoiseFloorBands; band++) {
sf = DecodeOneSymbol(bsi, huffIndexTime) << dShift;
sbrChan->noiseDataQuant[noiseFloor][band] = sf + sbrChan->noiseDataQuant[lastNoiseFloor][band];
}
}
/* skip coupling channel */
if (ch != 1 || psi->couplingFlag != 1)
DequantizeNoise(sbrFreq->numNoiseFloorBands, sbrChan->noiseDataQuant[noiseFloor], psi->noiseDataDequant[ch][noiseFloor]);
}
sbrGrid->numNoiseFloorsPrev = sbrGrid->numNoiseFloors;
}
/* dqTabCouple[i] = 2 / (1 + 2^(12 - i)), format = Q30 */
static const int dqTabCouple[25] PROGMEM = {
0x0007ff80, 0x000ffe00, 0x001ff802, 0x003fe010, 0x007f8080, 0x00fe03f8, 0x01f81f82, 0x03e0f83e,
0x07878788, 0x0e38e38e, 0x1999999a, 0x2aaaaaab, 0x40000000, 0x55555555, 0x66666666, 0x71c71c72,
0x78787878, 0x7c1f07c2, 0x7e07e07e, 0x7f01fc08, 0x7f807f80, 0x7fc01ff0, 0x7fe007fe, 0x7ff00200,
0x7ff80080,
};
/**************************************************************************************
* Function: UncoupleSBREnvelope
*
* Description: scale dequantized envelope scalefactors according to channel
* coupling rules
*
* Inputs: initialized PSInfoSBR struct including
* dequantized envelope data for left channel
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for right channel including
* quantized envelope scalefactors
*
* Outputs: dequantized envelope data for left channel (after decoupling)
* dequantized envelope data for right channel (after decoupling)
*
* Return: none
**************************************************************************************/
void UncoupleSBREnvelope(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR)
{
int env, band, nBands, scalei, E_1;
scalei = (sbrGrid->ampResFrame ? 0 : 1);
for (env = 0; env < sbrGrid->numEnv; env++) {
nBands = (sbrGrid->freqRes[env] ? sbrFreq->nHigh : sbrFreq->nLow);
psi->envDataDequantScale[1][env] = psi->envDataDequantScale[0][env]; /* same scalefactor for L and R */
for (band = 0; band < nBands; band++) {
/* clip E_1 to [0, 24] (scalefactors approach 0 or 2) */
E_1 = sbrChanR->envDataQuant[env][band] >> scalei;
if (E_1 < 0) E_1 = 0;
if (E_1 > 24) E_1 = 24;
/* envDataDequant[0] has 1 GB, so << by 2 is okay */
psi->envDataDequant[1][env][band] = MULSHIFT32(psi->envDataDequant[0][env][band], dqTabCouple[24 - E_1]) << 2;
psi->envDataDequant[0][env][band] = MULSHIFT32(psi->envDataDequant[0][env][band], dqTabCouple[E_1]) << 2;
}
}
}
/**************************************************************************************
* Function: UncoupleSBRNoise
*
* Description: scale dequantized noise floor scalefactors according to channel
* coupling rules
*
* Inputs: initialized PSInfoSBR struct including
* dequantized noise data for left channel
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel including
* quantized noise scalefactors
*
* Outputs: dequantized noise data for left channel (after decoupling)
* dequantized noise data for right channel (after decoupling)
*
* Return: none
**************************************************************************************/
void UncoupleSBRNoise(PSInfoSBR *psi, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR)
{
int noiseFloor, band, Q_1;
for (noiseFloor = 0; noiseFloor < sbrGrid->numNoiseFloors; noiseFloor++) {
for (band = 0; band < sbrFreq->numNoiseFloorBands; band++) {
/* Q_1 should be in range [0, 24] according to 4.6.18.3.6, but check to make sure */
Q_1 = sbrChanR->noiseDataQuant[noiseFloor][band];
if (Q_1 < 0) Q_1 = 0;
if (Q_1 > 24) Q_1 = 24;
/* noiseDataDequant[0] has 1 GB, so << by 2 is okay */
psi->noiseDataDequant[1][noiseFloor][band] = MULSHIFT32(psi->noiseDataDequant[0][noiseFloor][band], dqTabCouple[24 - Q_1]) << 2;
psi->noiseDataDequant[0][noiseFloor][band] = MULSHIFT32(psi->noiseDataDequant[0][noiseFloor][band], dqTabCouple[Q_1]) << 2;
}
}
}

View File

@@ -1,447 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrimdct.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrimdct.c - inverse MDCT without clipping or interleaving, for input to SBR
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/**************************************************************************************
* Function: DecWindowOverlapNoClip
*
* Description: apply synthesis window, do overlap-add without clipping,
* for winSequence LONG-LONG
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
out1 = out0 + 1024 - 1;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
if (winTypeCurr == winTypePrev) {
/* cut window loads in half since current and overlap sections use same symmetric window */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
} else {
/* different windows for current and overlap parts - should still fit in registers on ARM w/o stack spill */
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
}
/**************************************************************************************
* Function: DecWindowOverlapLongStart
*
* Description: apply synthesis window, do overlap-add, without clipping
* for winSequence LONG-START
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapLongStartNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
out1 = out0 + 1024 - 1;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
in = *buf1--;
*over1-- = 0; /* Wn = 0 for n = (2047, 2046, ... 1600) */
*over0++ = in >> 1; /* Wn = 1 for n = (1024, 1025, ... 1471) */
} while (--i);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++;
w1 = *wndPrev++;
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++; /* W[0], W[1], ... --> W[255], W[254], ... */
w1 = *wndCurr++; /* W[127], W[126], ... --> W[128], W[129], ... */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* Wn = short window for n = (1599, 1598, ... , 1536) */
*over0++ = MULSHIFT32(w1, in); /* Wn = short window for n = (1472, 1473, ... , 1535) */
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapLongStop
*
* Description: apply synthesis window, do overlap-add, without clipping
* for winSequence LONG-STOP
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapLongStopNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
buf0 += (1024 >> 1);
buf1 = buf0 - 1;
out1 = out0 + 1024 - 1;
over1 = over0 + 1024 - 1;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[1] : sinWindow + sinWindowOffset[1]);
i = 448; /* 2 outputs, 2 overlaps per loop */
do {
/* Wn = 0 for n = (0, 1, ... 447) */
/* Wn = 1 for n = (576, 577, ... 1023) */
in = *buf0++;
f1 = in >> 1; /* scale since skipping multiply by Q31 */
in = *over0;
*out0++ = in;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (--i);
/* do 64 more loops - 2 outputs, 2 overlaps per loop */
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/**************************************************************************************
* Function: DecWindowOverlapShort
*
* Description: apply synthesis window, do overlap-add, without clipping
* for winSequence EIGHT-SHORT (does all 8 short blocks)
*
* Inputs: input buffer (output of type-IV DCT)
* overlap buffer (saved from last time)
* window type (sin or KBD) for input buffer
* window type (sin or KBD) for overlap buffer
*
* Outputs: one channel, one frame of 32-bit PCM, non-interleaved
*
* Return: none
*
* Notes: use this function when the decoded PCM is going to the SBR decoder
**************************************************************************************/
void DecWindowOverlapShortNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev)
{
int i, in, w0, w1, f0, f1;
int *buf1, *over1, *out1;
const int *wndPrev, *wndCurr;
wndPrev = (winTypePrev == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
wndCurr = (winTypeCurr == 1 ? kbdWindow + kbdWindowOffset[0] : sinWindow + sinWindowOffset[0]);
/* pcm[0-447] = 0 + overlap[0-447] */
i = 448;
do {
f0 = *over0++;
f1 = *over0++;
*out0++ = f0;
*out0++ = f1;
i -= 2;
} while (i);
/* pcm[448-575] = Wp[0-127] * block0[0-127] + overlap[448-575] */
out1 = out0 + (128 - 1);
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
do {
w0 = *wndPrev++; /* W[0], W[1], ...W[63] */
w1 = *wndPrev++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *over0;
*out0++ = in - f0;
in = *over1;
*out1-- = in + f1;
w0 = *wndCurr++;
w1 = *wndCurr++;
in = *buf1--;
/* save over0/over1 for next short block, in the slots just vacated */
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
/* pcm[576-703] = Wc[128-255] * block0[128-255] + Wc[0-127] * block1[0-127] + overlap[576-703]
* pcm[704-831] = Wc[128-255] * block1[128-255] + Wc[0-127] * block2[0-127] + overlap[704-831]
* pcm[832-959] = Wc[128-255] * block2[128-255] + Wc[0-127] * block3[0-127] + overlap[832-959]
*/
for (i = 0; i < 3; i++) {
out0 += 64;
out1 = out0 + 128 - 1;
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 - 128); /* from last short block */
in += *(over0 + 0); /* from last full frame */
*out0++ = in - f0;
in = *(over1 - 128); /* from last short block */
in += *(over1 + 0); /* from last full frame */
*out1-- = in + f1;
/* save over0/over1 for next short block, in the slots just vacated */
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* pcm[960-1023] = Wc[128-191] * block3[128-191] + Wc[0-63] * block4[0-63] + overlap[960-1023]
* over[0-63] = Wc[192-255] * block3[192-255] + Wc[64-127] * block4[64-127]
*/
out0 += 64;
over0 -= 832; /* points at overlap[64] */
over1 = over0 + 128 - 1; /* points at overlap[191] */
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
in = *(over0 + 768); /* from last short block */
in += *(over0 + 896); /* from last full frame */
*out0++ = in - f0;
in = *(over1 + 768); /* from last short block */
*(over1 - 128) = in + f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in); /* save in overlap[128-191] */
*over0++ = MULSHIFT32(w1, in); /* save in overlap[64-127] */
} while (over0 < over1);
/* over0 now points at overlap[128] */
/* over[64-191] = Wc[128-255] * block4[128-255] + Wc[0-127] * block5[0-127]
* over[192-319] = Wc[128-255] * block5[128-255] + Wc[0-127] * block6[0-127]
* over[320-447] = Wc[128-255] * block6[128-255] + Wc[0-127] * block7[0-127]
* over[448-576] = Wc[128-255] * block7[128-255]
*/
for (i = 0; i < 3; i++) {
over0 += 64;
over1 = over0 + 128 - 1;
buf0 += 64;
buf1 = buf0 - 1;
wndCurr -= 128;
do {
w0 = *wndCurr++; /* W[0], W[1], ...W[63] */
w1 = *wndCurr++; /* W[127], W[126], ... W[64] */
in = *buf0++;
f0 = MULSHIFT32(w0, in);
f1 = MULSHIFT32(w1, in);
/* from last short block */
*(over0 - 128) -= f0;
*(over1 - 128)+= f1;
in = *buf1--;
*over1-- = MULSHIFT32(w0, in);
*over0++ = MULSHIFT32(w1, in);
} while (over0 < over1);
}
/* over[576-1024] = 0 */
i = 448;
over0 += 64;
do {
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
*over0++ = 0;
i -= 4;
} while (i);
}

View File

@@ -1,195 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrmath.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrmath.c - fixed-point math functions for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
#define Q28_2 0x20000000 /* Q28: 2.0 */
#define Q28_15 0x30000000 /* Q28: 1.5 */
#define NUM_ITER_IRN 5
/**************************************************************************************
* Function: InvRNormalized
*
* Description: use Newton's method to solve for x = 1/r
*
* Inputs: r = Q31, range = [0.5, 1) (normalize your inputs to this range)
*
* Outputs: none
*
* Return: x = Q29, range ~= [1.0, 2.0]
*
* Notes: guaranteed to converge and not overflow for any r in [0.5, 1)
*
* xn+1 = xn - f(xn)/f'(xn)
* f(x) = 1/r - x = 0 (find root)
* = 1/x - r
* f'(x) = -1/x^2
*
* so xn+1 = xn - (1/xn - r) / (-1/xn^2)
* = xn * (2 - r*xn)
*
* NUM_ITER_IRN = 2, maxDiff = 6.2500e-02 (precision of about 4 bits)
* NUM_ITER_IRN = 3, maxDiff = 3.9063e-03 (precision of about 8 bits)
* NUM_ITER_IRN = 4, maxDiff = 1.5288e-05 (precision of about 16 bits)
* NUM_ITER_IRN = 5, maxDiff = 3.0034e-08 (precision of about 24 bits)
**************************************************************************************/
int InvRNormalized(int r)
{
int i, xn, t;
/* r = [0.5, 1.0)
* 1/r = (1.0, 2.0]
* so use 1.5 as initial guess
*/
xn = Q28_15;
/* xn = xn*(2.0 - r*xn) */
for (i = NUM_ITER_IRN; i != 0; i--) {
t = MULSHIFT32(r, xn); /* Q31*Q29 = Q28 */
t = Q28_2 - t; /* Q28 */
xn = MULSHIFT32(xn, t) << 4; /* Q29*Q28 << 4 = Q29 */
}
return xn;
}
#define NUM_TERMS_RPI 5
#define LOG2_EXP_INV 0x58b90bfc /* 1/log2(e), Q31 */
/* invTab[x] = 1/(x+1), format = Q30 */
static const int invTab[NUM_TERMS_RPI] PROGMEM = {0x40000000, 0x20000000, 0x15555555, 0x10000000, 0x0ccccccd};
/**************************************************************************************
* Function: RatioPowInv
*
* Description: use Taylor (MacLaurin) series expansion to calculate (a/b) ^ (1/c)
*
* Inputs: a = [1, 64], b = [1, 64], c = [1, 64], a >= b
*
* Outputs: none
*
* Return: y = Q24, range ~= [0.015625, 64]
**************************************************************************************/
int RatioPowInv(int a, int b, int c)
{
int lna, lnb, i, p, t, y;
if (a < 1 || b < 1 || c < 1 || a > 64 || b > 64 || c > 64 || a < b)
return 0;
lna = MULSHIFT32(log2Tab[a], LOG2_EXP_INV) << 1; /* ln(a), Q28 */
lnb = MULSHIFT32(log2Tab[b], LOG2_EXP_INV) << 1; /* ln(b), Q28 */
p = (lna - lnb) / c; /* Q28 */
/* sum in Q24 */
y = (1 << 24);
t = p >> 4; /* t = p^1 * 1/1! (Q24)*/
y += t;
for (i = 2; i <= NUM_TERMS_RPI; i++) {
t = MULSHIFT32(invTab[i-1], t) << 2;
t = MULSHIFT32(p, t) << 4; /* t = p^i * 1/i! (Q24) */
y += t;
}
return y;
}
/**************************************************************************************
* Function: SqrtFix
*
* Description: use binary search to calculate sqrt(q)
*
* Inputs: q = Q30
* number of fraction bits in input
*
* Outputs: number of fraction bits in output
*
* Return: lo = Q(fBitsOut)
*
* Notes: absolute precision varies depending on fBitsIn
* normalizes input to range [0x200000000, 0x7fffffff] and takes
* floor(sqrt(input)), and sets fBitsOut appropriately
**************************************************************************************/
int SqrtFix(int q, int fBitsIn, int *fBitsOut)
{
int z, lo, hi, mid;
if (q <= 0) {
*fBitsOut = fBitsIn;
return 0;
}
/* force even fBitsIn */
z = fBitsIn & 0x01;
q >>= z;
fBitsIn -= z;
/* for max precision, normalize to [0x20000000, 0x7fffffff] */
z = (CLZ(q) - 1);
z >>= 1;
q <<= (2*z);
/* choose initial bounds */
lo = 1;
if (q >= 0x10000000)
lo = 16384; /* (int)sqrt(0x10000000) */
hi = 46340; /* (int)sqrt(0x7fffffff) */
/* do binary search with 32x32->32 multiply test */
do {
mid = (lo + hi) >> 1;
if (mid*mid > q)
hi = mid - 1;
else
lo = mid + 1;
} while (hi >= lo);
lo--;
*fBitsOut = ((fBitsIn + 2*z) >> 1);
return lo;
}

View File

@@ -1,527 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrqmf.c,v 1.2 2005/05/19 20:45:20 jrecker 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
*
* sbrqmf.c - analysis and synthesis QMF filters for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/* PreMultiply64() table
* format = Q30
* reordered for sequential access
*
* for (i = 0; i < 64/4; i++) {
* angle = (i + 0.25) * M_PI / nmdct;
* x = (cos(angle) + sin(angle));
* x = sin(angle);
*
* angle = (nmdct/2 - 1 - i + 0.25) * M_PI / nmdct;
* x = (cos(angle) + sin(angle));
* x = sin(angle);
* }
*/
static const int cos4sin4tab64[64] PROGMEM = {
0x40c7d2bd, 0x00c90e90, 0x424ff28f, 0x3ff4e5e0, 0x43cdd89a, 0x03ecadcf, 0x454149fc, 0x3fc395f9,
0x46aa0d6d, 0x070de172, 0x4807eb4b, 0x3f6af2e3, 0x495aada2, 0x0a2abb59, 0x4aa22036, 0x3eeb3347,
0x4bde1089, 0x0d415013, 0x4d0e4de2, 0x3e44a5ef, 0x4e32a956, 0x104fb80e, 0x4f4af5d1, 0x3d77b192,
0x50570819, 0x135410c3, 0x5156b6d9, 0x3c84d496, 0x5249daa2, 0x164c7ddd, 0x53304df6, 0x3b6ca4c4,
0x5409ed4b, 0x19372a64, 0x54d69714, 0x3a2fcee8, 0x55962bc0, 0x1c1249d8, 0x56488dc5, 0x38cf1669,
0x56eda1a0, 0x1edc1953, 0x57854ddd, 0x374b54ce, 0x580f7b19, 0x2192e09b, 0x588c1404, 0x35a5793c,
0x58fb0568, 0x2434f332, 0x595c3e2a, 0x33de87de, 0x59afaf4c, 0x26c0b162, 0x59f54bee, 0x31f79948,
0x5a2d0957, 0x29348937, 0x5a56deec, 0x2ff1d9c7, 0x5a72c63b, 0x2b8ef77d, 0x5a80baf6, 0x2dce88aa,
};
/* PostMultiply64() table
* format = Q30
* reordered for sequential access
*
* for (i = 0; i <= (32/2); i++) {
* angle = i * M_PI / 64;
* x = (cos(angle) + sin(angle));
* x = sin(angle);
* }
*/
static const int cos1sin1tab64[34] PROGMEM = {
0x40000000, 0x00000000, 0x43103085, 0x0323ecbe, 0x45f704f7, 0x0645e9af, 0x48b2b335, 0x09640837,
0x4b418bbe, 0x0c7c5c1e, 0x4da1fab5, 0x0f8cfcbe, 0x4fd288dc, 0x1294062f, 0x51d1dc80, 0x158f9a76,
0x539eba45, 0x187de2a7, 0x553805f2, 0x1b5d100a, 0x569cc31b, 0x1e2b5d38, 0x57cc15bc, 0x20e70f32,
0x58c542c5, 0x238e7673, 0x5987b08a, 0x261feffa, 0x5a12e720, 0x2899e64a, 0x5a6690ae, 0x2afad269,
0x5a82799a, 0x2d413ccd,
};
/**************************************************************************************
* Function: PreMultiply64
*
* Description: pre-twiddle stage of 64-point DCT-IV
*
* Inputs: buffer of 64 samples
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out, gains 2 int bits
* gbOut = gbIn + 1
* output is limited to sqrt(2)/2 plus GB in full GB
* uses 3-mul, 3-add butterflies instead of 4-mul, 2-add
**************************************************************************************/
static void PreMultiply64(int *zbuf1)
{
int i, ar1, ai1, ar2, ai2, z1, z2;
int t, cms2, cps2a, sin2a, cps2b, sin2b;
int *zbuf2;
const int *csptr;
zbuf2 = zbuf1 + 64 - 1;
csptr = cos4sin4tab64;
/* whole thing should fit in registers - verify that compiler does this */
for (i = 64 >> 2; i != 0; i--) {
/* cps2 = (cos+sin), sin2 = sin, cms2 = (cos-sin) */
cps2a = *csptr++;
sin2a = *csptr++;
cps2b = *csptr++;
sin2b = *csptr++;
ar1 = *(zbuf1 + 0);
ai2 = *(zbuf1 + 1);
ai1 = *(zbuf2 + 0);
ar2 = *(zbuf2 - 1);
/* gain 2 ints bit from MULSHIFT32 by Q30
* max per-sample gain (ignoring implicit scaling) = MAX(sin(angle)+cos(angle)) = 1.414
* i.e. gain 1 GB since worst case is sin(angle) = cos(angle) = 0.707 (Q30), gain 2 from
* extra sign bits, and eat one in adding
*/
t = MULSHIFT32(sin2a, ar1 + ai1);
z2 = MULSHIFT32(cps2a, ai1) - t;
cms2 = cps2a - 2*sin2a;
z1 = MULSHIFT32(cms2, ar1) + t;
*zbuf1++ = z1; /* cos*ar1 + sin*ai1 */
*zbuf1++ = z2; /* cos*ai1 - sin*ar1 */
t = MULSHIFT32(sin2b, ar2 + ai2);
z2 = MULSHIFT32(cps2b, ai2) - t;
cms2 = cps2b - 2*sin2b;
z1 = MULSHIFT32(cms2, ar2) + t;
*zbuf2-- = z2; /* cos*ai2 - sin*ar2 */
*zbuf2-- = z1; /* cos*ar2 + sin*ai2 */
}
}
/**************************************************************************************
* Function: PostMultiply64
*
* Description: post-twiddle stage of 64-point type-IV DCT
*
* Inputs: buffer of 64 samples
* number of output samples to calculate
*
* Outputs: processed samples in same buffer
*
* Return: none
*
* Notes: minimum 1 GB in, 2 GB out, gains 2 int bits
* gbOut = gbIn + 1
* output is limited to sqrt(2)/2 plus GB in full GB
* nSampsOut is rounded up to next multiple of 4, since we calculate
* 4 samples per loop
**************************************************************************************/
static void PostMultiply64(int *fft1, int nSampsOut)
{
int i, ar1, ai1, ar2, ai2;
int t, cms2, cps2, sin2;
int *fft2;
const int *csptr;
csptr = cos1sin1tab64;
fft2 = fft1 + 64 - 1;
/* load coeffs for first pass
* cps2 = (cos+sin)/2, sin2 = sin/2, cms2 = (cos-sin)/2
*/
cps2 = *csptr++;
sin2 = *csptr++;
cms2 = cps2 - 2*sin2;
for (i = (nSampsOut + 3) >> 2; i != 0; i--) {
ar1 = *(fft1 + 0);
ai1 = *(fft1 + 1);
ar2 = *(fft2 - 1);
ai2 = *(fft2 + 0);
/* gain 2 int bits (multiplying by Q30), max gain = sqrt(2) */
t = MULSHIFT32(sin2, ar1 + ai1);
*fft2-- = t - MULSHIFT32(cps2, ai1);
*fft1++ = t + MULSHIFT32(cms2, ar1);
cps2 = *csptr++;
sin2 = *csptr++;
ai2 = -ai2;
t = MULSHIFT32(sin2, ar2 + ai2);
*fft2-- = t - MULSHIFT32(cps2, ai2);
cms2 = cps2 - 2*sin2;
*fft1++ = t + MULSHIFT32(cms2, ar2);
}
}
/**************************************************************************************
* Function: QMFAnalysisConv
*
* Description: convolution kernel for analysis QMF
*
* Inputs: pointer to coefficient table, reordered for sequential access
* delay buffer of size 32*10 = 320 real-valued PCM samples
* index for delay ring buffer (range = [0, 9])
*
* Outputs: 64 consecutive 32-bit samples
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrqmfak.s when building for ARM!
**************************************************************************************/
#if (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM))
#ifdef __cplusplus
extern "C"
#endif
void QMFAnalysisConv(int *cTab, int *delay, int dIdx, int *uBuf);
#else
void QMFAnalysisConv(int *cTab, int *delay, int dIdx, int *uBuf)
{
int k, dOff;
int *cPtr0, *cPtr1;
U64 u64lo, u64hi;
dOff = dIdx*32 + 31;
cPtr0 = cTab;
cPtr1 = cTab + 33*5 - 1;
/* special first pass since we need to flip sign to create cTab[384], cTab[512] */
u64lo.w64 = 0;
u64hi.w64 = 0;
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, -(*cPtr1--), delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, -(*cPtr1--), delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
uBuf[0] = u64lo.r.hi32;
uBuf[32] = u64hi.r.hi32;
uBuf++;
dOff--;
/* max gain for any sample in uBuf, after scaling by cTab, ~= 0.99
* so we can just sum the uBuf values with no overflow problems
*/
for (k = 1; k <= 31; k++) {
u64lo.w64 = 0;
u64hi.w64 = 0;
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr0++, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64lo.w64 = MADD64(u64lo.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
u64hi.w64 = MADD64(u64hi.w64, *cPtr1--, delay[dOff]); dOff -= 32; if (dOff < 0) {dOff += 320;}
uBuf[0] = u64lo.r.hi32;
uBuf[32] = u64hi.r.hi32;
uBuf++;
dOff--;
}
}
#endif
/**************************************************************************************
* Function: QMFAnalysis
*
* Description: 32-subband analysis QMF (4.6.18.4.1)
*
* Inputs: 32 consecutive samples of decoded 32-bit PCM, format = Q(fBitsIn)
* delay buffer of size 32*10 = 320 PCM samples
* number of fraction bits in input PCM
* index for delay ring buffer (range = [0, 9])
* number of subbands to calculate (range = [0, 32])
*
* Outputs: qmfaBands complex subband samples, format = Q(FBITS_OUT_QMFA)
* updated delay buffer
* updated delay index
*
* Return: guard bit mask
*
* Notes: output stored as RE{X0}, IM{X0}, RE{X1}, IM{X1}, ... RE{X31}, IM{X31}
* output stored in int buffer of size 64*2 = 128
* (zero-filled from XBuf[2*qmfaBands] to XBuf[127])
**************************************************************************************/
int QMFAnalysis(int *inbuf, int *delay, int *XBuf, int fBitsIn, int *delayIdx, int qmfaBands)
{
int n, y, shift, gbMask;
int *delayPtr, *uBuf, *tBuf;
/* use XBuf[128] as temp buffer for reordering */
uBuf = XBuf; /* first 64 samples */
tBuf = XBuf + 64; /* second 64 samples */
/* overwrite oldest PCM with new PCM
* delay[n] has 1 GB after shifting (either << or >>)
*/
delayPtr = delay + (*delayIdx * 32);
if (fBitsIn > FBITS_IN_QMFA) {
shift = MIN(fBitsIn - FBITS_IN_QMFA, 31);
for (n = 32; n != 0; n--) {
y = (*inbuf) >> shift;
inbuf++;
*delayPtr++ = y;
}
} else {
shift = MIN(FBITS_IN_QMFA - fBitsIn, 30);
for (n = 32; n != 0; n--) {
y = *inbuf++;
CLIP_2N_SHIFT30(y, shift);
*delayPtr++ = y;
}
}
QMFAnalysisConv((int *)cTabA, delay, *delayIdx, uBuf);
/* uBuf has at least 2 GB right now (1 from clipping to Q(FBITS_IN_QMFA), one from
* the scaling by cTab (MULSHIFT32(*delayPtr--, *cPtr++), with net gain of < 1.0)
* TODO - fuse with QMFAnalysisConv to avoid separate reordering
*/
tBuf[2*0 + 0] = uBuf[0];
tBuf[2*0 + 1] = uBuf[1];
for (n = 1; n < 31; n++) {
tBuf[2*n + 0] = -uBuf[64-n];
tBuf[2*n + 1] = uBuf[n+1];
}
tBuf[2*31 + 1] = uBuf[32];
tBuf[2*31 + 0] = -uBuf[33];
/* fast in-place DCT-IV - only need 2*qmfaBands output samples */
PreMultiply64(tBuf); /* 2 GB in, 3 GB out */
FFT32C(tBuf); /* 3 GB in, 1 GB out */
PostMultiply64(tBuf, qmfaBands*2); /* 1 GB in, 2 GB out */
/* TODO - roll into PostMultiply (if enough registers) */
gbMask = 0;
for (n = 0; n < qmfaBands; n++) {
XBuf[2*n+0] = tBuf[ n + 0]; /* implicit scaling of 2 in our output Q format */
gbMask |= FASTABS(XBuf[2*n+0]);
XBuf[2*n+1] = -tBuf[63 - n];
gbMask |= FASTABS(XBuf[2*n+1]);
}
/* fill top section with zeros for HF generation */
for ( ; n < 64; n++) {
XBuf[2*n+0] = 0;
XBuf[2*n+1] = 0;
}
*delayIdx = (*delayIdx == NUM_QMF_DELAY_BUFS - 1 ? 0 : *delayIdx + 1);
/* minimum of 2 GB in output */
return gbMask;
}
/* lose FBITS_LOST_DCT4_64 in DCT4, gain 6 for implicit scaling by 1/64, lose 1 for cTab multiply (Q31) */
#define FBITS_OUT_QMFS (FBITS_IN_QMFS - FBITS_LOST_DCT4_64 + 6 - 1)
#define RND_VAL (1 << (FBITS_OUT_QMFS-1))
/**************************************************************************************
* Function: QMFSynthesisConv
*
* Description: final convolution kernel for synthesis QMF
*
* Inputs: pointer to coefficient table, reordered for sequential access
* delay buffer of size 64*10 = 640 complex samples (1280 ints)
* index for delay ring buffer (range = [0, 9])
* number of QMF subbands to process (range = [0, 64])
* number of channels
*
* Outputs: 64 consecutive 16-bit PCM samples, interleaved by factor of nChans
*
* Return: none
*
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrqmfsk.s when building for ARM!
**************************************************************************************/
#if (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM))
#ifdef __cplusplus
extern "C"
#endif
void QMFSynthesisConv(int *cPtr, int *delay, int dIdx, short *outbuf, int nChans);
#else
void QMFSynthesisConv(int *cPtr, int *delay, int dIdx, short *outbuf, int nChans)
{
int k, dOff0, dOff1;
U64 sum64;
dOff0 = (dIdx)*128;
dOff1 = dOff0 - 1;
if (dOff1 < 0)
dOff1 += 1280;
/* scaling note: total gain of coefs (cPtr[0]-cPtr[9] for any k) is < 2.0, so 1 GB in delay values is adequate */
for (k = 0; k <= 63; k++) {
sum64.w64 = 0;
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff0]); dOff0 -= 256; if (dOff0 < 0) {dOff0 += 1280;}
sum64.w64 = MADD64(sum64.w64, *cPtr++, delay[dOff1]); dOff1 -= 256; if (dOff1 < 0) {dOff1 += 1280;}
dOff0++;
dOff1--;
*outbuf = CLIPTOSHORT((sum64.r.hi32 + RND_VAL) >> FBITS_OUT_QMFS);
outbuf += nChans;
}
}
#endif
/**************************************************************************************
* Function: QMFSynthesis
*
* Description: 64-subband synthesis QMF (4.6.18.4.2)
*
* Inputs: 64 consecutive complex subband QMF samples, format = Q(FBITS_IN_QMFS)
* delay buffer of size 64*10 = 640 complex samples (1280 ints)
* index for delay ring buffer (range = [0, 9])
* number of QMF subbands to process (range = [0, 64])
* number of channels
*
* Outputs: 64 consecutive 16-bit PCM samples, interleaved by factor of nChans
* updated delay buffer
* updated delay index
*
* Return: none
*
* Notes: assumes MIN_GBITS_IN_QMFS guard bits in input, either from
* QMFAnalysis (if upsampling only) or from MapHF (if SBR on)
**************************************************************************************/
void QMFSynthesis(int *inbuf, int *delay, int *delayIdx, int qmfsBands, short *outbuf, int nChans)
{
int n, a0, a1, b0, b1, dOff0, dOff1, dIdx;
int *tBufLo, *tBufHi;
dIdx = *delayIdx;
tBufLo = delay + dIdx*128 + 0;
tBufHi = delay + dIdx*128 + 127;
/* reorder inputs to DCT-IV, only use first qmfsBands (complex) samples
* TODO - fuse with PreMultiply64 to avoid separate reordering steps
*/
for (n = 0; n < qmfsBands >> 1; n++) {
a0 = *inbuf++;
b0 = *inbuf++;
a1 = *inbuf++;
b1 = *inbuf++;
*tBufLo++ = a0;
*tBufLo++ = a1;
*tBufHi-- = b0;
*tBufHi-- = b1;
}
if (qmfsBands & 0x01) {
a0 = *inbuf++;
b0 = *inbuf++;
*tBufLo++ = a0;
*tBufHi-- = b0;
*tBufLo++ = 0;
*tBufHi-- = 0;
n++;
}
for ( ; n < 32; n++) {
*tBufLo++ = 0;
*tBufHi-- = 0;
*tBufLo++ = 0;
*tBufHi-- = 0;
}
tBufLo = delay + dIdx*128 + 0;
tBufHi = delay + dIdx*128 + 64;
/* 2 GB in, 3 GB out */
PreMultiply64(tBufLo);
PreMultiply64(tBufHi);
/* 3 GB in, 1 GB out */
FFT32C(tBufLo);
FFT32C(tBufHi);
/* 1 GB in, 2 GB out */
PostMultiply64(tBufLo, 64);
PostMultiply64(tBufHi, 64);
/* could fuse with PostMultiply64 to avoid separate pass */
dOff0 = dIdx*128;
dOff1 = dIdx*128 + 64;
for (n = 32; n != 0; n--) {
a0 = (*tBufLo++);
a1 = (*tBufLo++);
b0 = (*tBufHi++);
b1 = -(*tBufHi++);
delay[dOff0++] = (b0 - a0);
delay[dOff0++] = (b1 - a1);
delay[dOff1++] = (b0 + a0);
delay[dOff1++] = (b1 + a1);
}
QMFSynthesisConv((int *)cTabS, delay, dIdx, outbuf, nChans);
*delayIdx = (*delayIdx == NUM_QMF_DELAY_BUFS - 1 ? 0 : *delayIdx + 1);
}

View File

@@ -1,575 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrside.c,v 1.2 2005/05/24 16:01:55 albertofloyd Exp $
*
* Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file,
* are subject to the current version of the RealNetworks Public
* Source License (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the current version of the RealNetworks Community
* Source License (the "RCSL") available at
* http://www.helixcommunity.org/content/rcsl, in which case the RCSL
* will apply. You may also obtain the license terms directly from
* RealNetworks. You may not use this file except in compliance with
* the RPSL or, if you have a valid RCSL with RealNetworks applicable
* to this file, the RCSL. Please see the applicable RPSL or RCSL for
* the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the
* portions it created.
*
* This file, and the files included with this file, is distributed
* and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
* ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/**************************************************************************************
* Fixed-point HE-AAC decoder
* Jon Recker (jrecker@real.com)
* February 2005
*
* sbrside.c - functions for unpacking side info from SBR bitstream
**************************************************************************************/
#include "sbr.h"
/**************************************************************************************
* Function: GetSampRateIdx
*
* Description: get index of given sample rate
*
* Inputs: sample rate (in Hz)
*
* Outputs: none
*
* Return: index of sample rate (table 1.15 in 14496-3:2001(E))
* -1 if sample rate not found in table
**************************************************************************************/
int GetSampRateIdx(int sampRate)
{
int idx;
for (idx = 0; idx < NUM_SAMPLE_RATES; idx++) {
if (sampRate == sampRateTab[idx])
return idx;
}
return -1;
}
/**************************************************************************************
* Function: UnpackSBRHeader
*
* Description: unpack SBR header (table 4.56)
*
* Inputs: BitStreamInfo struct pointing to start of SBR header
*
* Outputs: initialized SBRHeader struct for this SCE/CPE block
*
* Return: non-zero if frame reset is triggered, zero otherwise
**************************************************************************************/
int UnpackSBRHeader(BitStreamInfo *bsi, SBRHeader *sbrHdr)
{
SBRHeader sbrHdrPrev;
/* save previous values so we know whether to reset decoder */
sbrHdrPrev.startFreq = sbrHdr->startFreq;
sbrHdrPrev.stopFreq = sbrHdr->stopFreq;
sbrHdrPrev.freqScale = sbrHdr->freqScale;
sbrHdrPrev.alterScale = sbrHdr->alterScale;
sbrHdrPrev.crossOverBand = sbrHdr->crossOverBand;
sbrHdrPrev.noiseBands = sbrHdr->noiseBands;
sbrHdr->ampRes = GetBits(bsi, 1);
sbrHdr->startFreq = GetBits(bsi, 4);
sbrHdr->stopFreq = GetBits(bsi, 4);
sbrHdr->crossOverBand = GetBits(bsi, 3);
sbrHdr->resBitsHdr = GetBits(bsi, 2);
sbrHdr->hdrExtra1 = GetBits(bsi, 1);
sbrHdr->hdrExtra2 = GetBits(bsi, 1);
if (sbrHdr->hdrExtra1) {
sbrHdr->freqScale = GetBits(bsi, 2);
sbrHdr->alterScale = GetBits(bsi, 1);
sbrHdr->noiseBands = GetBits(bsi, 2);
} else {
/* defaults */
sbrHdr->freqScale = 2;
sbrHdr->alterScale = 1;
sbrHdr->noiseBands = 2;
}
if (sbrHdr->hdrExtra2) {
sbrHdr->limiterBands = GetBits(bsi, 2);
sbrHdr->limiterGains = GetBits(bsi, 2);
sbrHdr->interpFreq = GetBits(bsi, 1);
sbrHdr->smoothMode = GetBits(bsi, 1);
} else {
/* defaults */
sbrHdr->limiterBands = 2;
sbrHdr->limiterGains = 2;
sbrHdr->interpFreq = 1;
sbrHdr->smoothMode = 1;
}
sbrHdr->count++;
/* if any of these have changed from previous frame, reset the SBR module */
if (sbrHdr->startFreq != sbrHdrPrev.startFreq || sbrHdr->stopFreq != sbrHdrPrev.stopFreq ||
sbrHdr->freqScale != sbrHdrPrev.freqScale || sbrHdr->alterScale != sbrHdrPrev.alterScale ||
sbrHdr->crossOverBand != sbrHdrPrev.crossOverBand || sbrHdr->noiseBands != sbrHdrPrev.noiseBands
)
return -1;
else
return 0;
}
/* cLog2[i] = ceil(log2(i)) (disregard i == 0) */
static const unsigned char cLog2[9] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
/**************************************************************************************
* Function: UnpackSBRGrid
*
* Description: unpack SBR grid (table 4.62)
*
* Inputs: BitStreamInfo struct pointing to start of SBR grid
* initialized SBRHeader struct for this SCE/CPE block
*
* Outputs: initialized SBRGrid struct for this channel
*
* Return: none
**************************************************************************************/
static void UnpackSBRGrid(BitStreamInfo *bsi, SBRHeader *sbrHdr, SBRGrid *sbrGrid)
{
int numEnvRaw, env, rel, pBits, border, middleBorder=0;
unsigned char relBordLead[MAX_NUM_ENV], relBordTrail[MAX_NUM_ENV];
unsigned char relBorder0[3], relBorder1[3], relBorder[3];
unsigned char numRelBorder0, numRelBorder1, numRelBorder, numRelLead=0, numRelTrail;
unsigned char absBordLead=0, absBordTrail=0, absBorder;
sbrGrid->ampResFrame = sbrHdr->ampRes;
sbrGrid->frameClass = GetBits(bsi, 2);
switch (sbrGrid->frameClass) {
case SBR_GRID_FIXFIX:
numEnvRaw = GetBits(bsi, 2);
sbrGrid->numEnv = (1 << numEnvRaw);
if (sbrGrid->numEnv == 1)
sbrGrid->ampResFrame = 0;
ASSERT(sbrGrid->numEnv == 1 || sbrGrid->numEnv == 2 || sbrGrid->numEnv == 4);
sbrGrid->freqRes[0] = GetBits(bsi, 1);
for (env = 1; env < sbrGrid->numEnv; env++)
sbrGrid->freqRes[env] = sbrGrid->freqRes[0];
absBordLead = 0;
absBordTrail = NUM_TIME_SLOTS;
numRelLead = sbrGrid->numEnv - 1;
numRelTrail = 0;
/* numEnv = 1, 2, or 4 */
if (sbrGrid->numEnv == 1) border = NUM_TIME_SLOTS / 1;
else if (sbrGrid->numEnv == 2) border = NUM_TIME_SLOTS / 2;
else border = NUM_TIME_SLOTS / 4;
for (rel = 0; rel < numRelLead; rel++)
relBordLead[rel] = border;
middleBorder = (sbrGrid->numEnv >> 1);
break;
case SBR_GRID_FIXVAR:
absBorder = GetBits(bsi, 2) + NUM_TIME_SLOTS;
numRelBorder = GetBits(bsi, 2);
sbrGrid->numEnv = numRelBorder + 1;
for (rel = 0; rel < numRelBorder; rel++)
relBorder[rel] = 2*GetBits(bsi, 2) + 2;
pBits = cLog2[sbrGrid->numEnv + 1];
sbrGrid->pointer = GetBits(bsi, pBits);
for (env = sbrGrid->numEnv - 1; env >= 0; env--)
sbrGrid->freqRes[env] = GetBits(bsi, 1);
absBordLead = 0;
absBordTrail = absBorder;
numRelLead = 0;
numRelTrail = numRelBorder;
for (rel = 0; rel < numRelTrail; rel++)
relBordTrail[rel] = relBorder[rel];
if (sbrGrid->pointer > 1) middleBorder = sbrGrid->numEnv + 1 - sbrGrid->pointer;
else middleBorder = sbrGrid->numEnv - 1;
break;
case SBR_GRID_VARFIX:
absBorder = GetBits(bsi, 2);
numRelBorder = GetBits(bsi, 2);
sbrGrid->numEnv = numRelBorder + 1;
for (rel = 0; rel < numRelBorder; rel++)
relBorder[rel] = 2*GetBits(bsi, 2) + 2;
pBits = cLog2[sbrGrid->numEnv + 1];
sbrGrid->pointer = GetBits(bsi, pBits);
for (env = 0; env < sbrGrid->numEnv; env++)
sbrGrid->freqRes[env] = GetBits(bsi, 1);
absBordLead = absBorder;
absBordTrail = NUM_TIME_SLOTS;
numRelLead = numRelBorder;
numRelTrail = 0;
for (rel = 0; rel < numRelLead; rel++)
relBordLead[rel] = relBorder[rel];
if (sbrGrid->pointer == 0) middleBorder = 1;
else if (sbrGrid->pointer == 1) middleBorder = sbrGrid->numEnv - 1;
else middleBorder = sbrGrid->pointer - 1;
break;
case SBR_GRID_VARVAR:
absBordLead = GetBits(bsi, 2); /* absBorder0 */
absBordTrail = GetBits(bsi, 2) + NUM_TIME_SLOTS; /* absBorder1 */
numRelBorder0 = GetBits(bsi, 2);
numRelBorder1 = GetBits(bsi, 2);
sbrGrid->numEnv = numRelBorder0 + numRelBorder1 + 1;
ASSERT(sbrGrid->numEnv <= 5);
for (rel = 0; rel < numRelBorder0; rel++)
relBorder0[rel] = 2*GetBits(bsi, 2) + 2;
for (rel = 0; rel < numRelBorder1; rel++)
relBorder1[rel] = 2*GetBits(bsi, 2) + 2;
pBits = cLog2[numRelBorder0 + numRelBorder1 + 2];
sbrGrid->pointer = GetBits(bsi, pBits);
for (env = 0; env < sbrGrid->numEnv; env++)
sbrGrid->freqRes[env] = GetBits(bsi, 1);
numRelLead = numRelBorder0;
numRelTrail = numRelBorder1;
for (rel = 0; rel < numRelLead; rel++)
relBordLead[rel] = relBorder0[rel];
for (rel = 0; rel < numRelTrail; rel++)
relBordTrail[rel] = relBorder1[rel];
if (sbrGrid->pointer > 1) middleBorder = sbrGrid->numEnv + 1 - sbrGrid->pointer;
else middleBorder = sbrGrid->numEnv - 1;
break;
}
/* build time border vector */
sbrGrid->envTimeBorder[0] = absBordLead * SAMPLES_PER_SLOT;
rel = 0;
border = absBordLead;
for (env = 1; env <= numRelLead; env++) {
border += relBordLead[rel++];
sbrGrid->envTimeBorder[env] = border * SAMPLES_PER_SLOT;
}
rel = 0;
border = absBordTrail;
for (env = sbrGrid->numEnv - 1; env > numRelLead; env--) {
border -= relBordTrail[rel++];
sbrGrid->envTimeBorder[env] = border * SAMPLES_PER_SLOT;
}
sbrGrid->envTimeBorder[sbrGrid->numEnv] = absBordTrail * SAMPLES_PER_SLOT;
if (sbrGrid->numEnv > 1) {
sbrGrid->numNoiseFloors = 2;
sbrGrid->noiseTimeBorder[0] = sbrGrid->envTimeBorder[0];
sbrGrid->noiseTimeBorder[1] = sbrGrid->envTimeBorder[middleBorder];
sbrGrid->noiseTimeBorder[2] = sbrGrid->envTimeBorder[sbrGrid->numEnv];
} else {
sbrGrid->numNoiseFloors = 1;
sbrGrid->noiseTimeBorder[0] = sbrGrid->envTimeBorder[0];
sbrGrid->noiseTimeBorder[1] = sbrGrid->envTimeBorder[1];
}
}
/**************************************************************************************
* Function: UnpackDeltaTimeFreq
*
* Description: unpack time/freq flags for delta coding of SBR envelopes (table 4.63)
*
* Inputs: BitStreamInfo struct pointing to start of dt/df flags
* number of envelopes
* number of noise floors
*
* Outputs: delta flags for envelope and noise floors
*
* Return: none
**************************************************************************************/
static void UnpackDeltaTimeFreq(BitStreamInfo *bsi, int numEnv, unsigned char *deltaFlagEnv,
int numNoiseFloors, unsigned char *deltaFlagNoise)
{
int env, noiseFloor;
for (env = 0; env < numEnv; env++)
deltaFlagEnv[env] = GetBits(bsi, 1);
for (noiseFloor = 0; noiseFloor < numNoiseFloors; noiseFloor++)
deltaFlagNoise[noiseFloor] = GetBits(bsi, 1);
}
/**************************************************************************************
* Function: UnpackInverseFilterMode
*
* Description: unpack invf flags for chirp factor calculation (table 4.64)
*
* Inputs: BitStreamInfo struct pointing to start of invf flags
* number of noise floor bands
*
* Outputs: invf flags for noise floor bands
*
* Return: none
**************************************************************************************/
static void UnpackInverseFilterMode(BitStreamInfo *bsi, int numNoiseFloorBands, unsigned char *mode)
{
int n;
for (n = 0; n < numNoiseFloorBands; n++)
mode[n] = GetBits(bsi, 2);
}
/**************************************************************************************
* Function: UnpackSinusoids
*
* Description: unpack sinusoid (harmonic) flags for each SBR subband (table 4.67)
*
* Inputs: BitStreamInfo struct pointing to start of sinusoid flags
* number of high resolution SBR subbands (nHigh)
*
* Outputs: sinusoid flags for each SBR subband, zero-filled above nHigh
*
* Return: none
**************************************************************************************/
static void UnpackSinusoids(BitStreamInfo *bsi, int nHigh, int addHarmonicFlag, unsigned char *addHarmonic)
{
int n;
n = 0;
if (addHarmonicFlag) {
for ( ; n < nHigh; n++)
addHarmonic[n] = GetBits(bsi, 1);
}
/* zero out unused bands */
for ( ; n < MAX_QMF_BANDS; n++)
addHarmonic[n] = 0;
}
/**************************************************************************************
* Function: CopyCouplingGrid
*
* Description: copy grid parameters from left to right for channel coupling
*
* Inputs: initialized SBRGrid struct for left channel
*
* Outputs: initialized SBRGrid struct for right channel
*
* Return: none
**************************************************************************************/
static void CopyCouplingGrid(SBRGrid *sbrGridLeft, SBRGrid *sbrGridRight)
{
int env, noiseFloor;
sbrGridRight->frameClass = sbrGridLeft->frameClass;
sbrGridRight->ampResFrame = sbrGridLeft->ampResFrame;
sbrGridRight->pointer = sbrGridLeft->pointer;
sbrGridRight->numEnv = sbrGridLeft->numEnv;
for (env = 0; env < sbrGridLeft->numEnv; env++) {
sbrGridRight->envTimeBorder[env] = sbrGridLeft->envTimeBorder[env];
sbrGridRight->freqRes[env] = sbrGridLeft->freqRes[env];
}
sbrGridRight->envTimeBorder[env] = sbrGridLeft->envTimeBorder[env]; /* borders are [0, numEnv] inclusive */
sbrGridRight->numNoiseFloors = sbrGridLeft->numNoiseFloors;
for (noiseFloor = 0; noiseFloor <= sbrGridLeft->numNoiseFloors; noiseFloor++)
sbrGridRight->noiseTimeBorder[noiseFloor] = sbrGridLeft->noiseTimeBorder[noiseFloor];
/* numEnvPrev, numNoiseFloorsPrev, freqResPrev are updated in DecodeSBREnvelope() and DecodeSBRNoise() */
}
/**************************************************************************************
* Function: CopyCouplingInverseFilterMode
*
* Description: copy invf flags from left to right for channel coupling
*
* Inputs: invf flags for left channel
* number of noise floor bands
*
* Outputs: invf flags for right channel
*
* Return: none
**************************************************************************************/
static void CopyCouplingInverseFilterMode(int numNoiseFloorBands, unsigned char *modeLeft, unsigned char *modeRight)
{
int band;
for (band = 0; band < numNoiseFloorBands; band++)
modeRight[band] = modeLeft[band];
}
/**************************************************************************************
* Function: UnpackSBRSingleChannel
*
* Description: unpack sideband info (grid, delta flags, invf flags, envelope and
* noise floor configuration, sinusoids) for a single channel
*
* Inputs: BitStreamInfo struct pointing to start of sideband info
* initialized PSInfoSBR struct (after parsing SBR header and building
* frequency tables)
* base output channel (range = [0, nChans-1])
*
* Outputs: updated PSInfoSBR struct (SBRGrid and SBRChan)
*
* Return: none
**************************************************************************************/
void UnpackSBRSingleChannel(BitStreamInfo *bsi, PSInfoSBR *psi, int chBase)
{
int bitsLeft;
SBRHeader *sbrHdr = &(psi->sbrHdr[chBase]);
SBRGrid *sbrGridL = &(psi->sbrGrid[chBase+0]);
SBRFreq *sbrFreq = &(psi->sbrFreq[chBase]);
SBRChan *sbrChanL = &(psi->sbrChan[chBase+0]);
psi->dataExtra = GetBits(bsi, 1);
if (psi->dataExtra)
psi->resBitsData = GetBits(bsi, 4);
UnpackSBRGrid(bsi, sbrHdr, sbrGridL);
UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);
DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
sbrChanL->addHarmonicFlag[1] = GetBits(bsi, 1);
UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanL->addHarmonicFlag[1], sbrChanL->addHarmonic[1]);
psi->extendedDataPresent = GetBits(bsi, 1);
if (psi->extendedDataPresent) {
psi->extendedDataSize = GetBits(bsi, 4);
if (psi->extendedDataSize == 15)
psi->extendedDataSize += GetBits(bsi, 8);
bitsLeft = 8 * psi->extendedDataSize;
/* get ID, unpack extension info, do whatever is necessary with it... */
while (bitsLeft > 0) {
GetBits(bsi, 8);
bitsLeft -= 8;
}
}
}
/**************************************************************************************
* Function: UnpackSBRChannelPair
*
* Description: unpack sideband info (grid, delta flags, invf flags, envelope and
* noise floor configuration, sinusoids) for a channel pair
*
* Inputs: BitStreamInfo struct pointing to start of sideband info
* initialized PSInfoSBR struct (after parsing SBR header and building
* frequency tables)
* base output channel (range = [0, nChans-1])
*
* Outputs: updated PSInfoSBR struct (SBRGrid and SBRChan for both channels)
*
* Return: none
**************************************************************************************/
void UnpackSBRChannelPair(BitStreamInfo *bsi, PSInfoSBR *psi, int chBase)
{
int bitsLeft;
SBRHeader *sbrHdr = &(psi->sbrHdr[chBase]);
SBRGrid *sbrGridL = &(psi->sbrGrid[chBase+0]), *sbrGridR = &(psi->sbrGrid[chBase+1]);
SBRFreq *sbrFreq = &(psi->sbrFreq[chBase]);
SBRChan *sbrChanL = &(psi->sbrChan[chBase+0]), *sbrChanR = &(psi->sbrChan[chBase+1]);
psi->dataExtra = GetBits(bsi, 1);
if (psi->dataExtra) {
psi->resBitsData = GetBits(bsi, 4);
psi->resBitsData = GetBits(bsi, 4);
}
psi->couplingFlag = GetBits(bsi, 1);
if (psi->couplingFlag) {
UnpackSBRGrid(bsi, sbrHdr, sbrGridL);
CopyCouplingGrid(sbrGridL, sbrGridR);
UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);
UnpackDeltaTimeFreq(bsi, sbrGridR->numEnv, sbrChanR->deltaFlagEnv, sbrGridR->numNoiseFloors, sbrChanR->deltaFlagNoise);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);
CopyCouplingInverseFilterMode(sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1], sbrChanR->invfMode[1]);
DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBREnvelope(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
DecodeSBRNoise(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
/* pass RIGHT sbrChan struct */
UncoupleSBREnvelope(psi, sbrGridL, sbrFreq, sbrChanR);
UncoupleSBRNoise(psi, sbrGridL, sbrFreq, sbrChanR);
} else {
UnpackSBRGrid(bsi, sbrHdr, sbrGridL);
UnpackSBRGrid(bsi, sbrHdr, sbrGridR);
UnpackDeltaTimeFreq(bsi, sbrGridL->numEnv, sbrChanL->deltaFlagEnv, sbrGridL->numNoiseFloors, sbrChanL->deltaFlagNoise);
UnpackDeltaTimeFreq(bsi, sbrGridR->numEnv, sbrChanR->deltaFlagEnv, sbrGridR->numNoiseFloors, sbrChanR->deltaFlagNoise);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanL->invfMode[1]);
UnpackInverseFilterMode(bsi, sbrFreq->numNoiseFloorBands, sbrChanR->invfMode[1]);
DecodeSBREnvelope(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBREnvelope(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
DecodeSBRNoise(bsi, psi, sbrGridL, sbrFreq, sbrChanL, 0);
DecodeSBRNoise(bsi, psi, sbrGridR, sbrFreq, sbrChanR, 1);
}
sbrChanL->addHarmonicFlag[1] = GetBits(bsi, 1);
UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanL->addHarmonicFlag[1], sbrChanL->addHarmonic[1]);
sbrChanR->addHarmonicFlag[1] = GetBits(bsi, 1);
UnpackSinusoids(bsi, sbrFreq->nHigh, sbrChanR->addHarmonicFlag[1], sbrChanR->addHarmonic[1]);
psi->extendedDataPresent = GetBits(bsi, 1);
if (psi->extendedDataPresent) {
psi->extendedDataSize = GetBits(bsi, 4);
if (psi->extendedDataSize == 15)
psi->extendedDataSize += GetBits(bsi, 8);
bitsLeft = 8 * psi->extendedDataSize;
/* get ID, unpack extension info, do whatever is necessary with it... */
while (bitsLeft > 0) {
GetBits(bsi, 8);
bitsLeft -= 8;
}
}
}

View File

@@ -1,400 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: sbrtabs.c,v 1.1 2005/02/26 01:47:35 jrecker 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
*
* sbrtabs.c - platform-independent tables for SBR (global, read-only)
**************************************************************************************/
#include "sbr.h"
/* k0Tab[sampRateIdx][k] = k0 = startMin + offset(bs_start_freq) for given sample rate (4.6.18.3.2.1)
* downsampled (single-rate) SBR not currently supported
*/
const unsigned char k0Tab[NUM_SAMPLE_RATES_SBR][16] = {
{ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31 }, /* 96 kHz */
{ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31 }, /* 88 kHz */
{ 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 26, 30 }, /* 64 kHz */
{ 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 27, 31 }, /* 48 kHz */
{ 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 28, 32 }, /* 44 kHz */
{ 10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32 }, /* 32 kHz */
{ 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32 }, /* 24 kHz */
{ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30 }, /* 22 kHz */
{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }, /* 16 kHz */
};
/* k2Tab[sampRateIdx][k] = stopVector(bs_stop_freq) for given sample rate, bs_stop_freq = [0, 13] (4.6.18.3.2.1)
* generated with Matlab script calc_stopvec.m
* downsampled (single-rate) SBR not currently supported
*/
const unsigned char k2Tab[NUM_SAMPLE_RATES_SBR][14] = {
{ 13, 15, 17, 19, 21, 24, 27, 31, 35, 39, 44, 50, 57, 64 }, /* 96 kHz */
{ 15, 17, 19, 21, 23, 26, 29, 33, 37, 41, 46, 51, 57, 64 }, /* 88 kHz */
{ 20, 22, 24, 26, 28, 31, 34, 37, 41, 45, 49, 54, 59, 64 }, /* 64 kHz */
{ 21, 23, 25, 27, 29, 32, 35, 38, 41, 45, 49, 54, 59, 64 }, /* 48 kHz */
{ 23, 25, 27, 29, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64 }, /* 44 kHz */
{ 32, 34, 36, 38, 40, 42, 44, 46, 49, 52, 55, 58, 61, 64 }, /* 32 kHz */
{ 32, 34, 36, 38, 40, 42, 44, 46, 49, 52, 55, 58, 61, 64 }, /* 24 kHz */
{ 35, 36, 38, 40, 42, 44, 46, 48, 50, 52, 55, 58, 61, 64 }, /* 22 kHz */
{ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62, 64 }, /* 16 kHz */
};
/* NINT(2.048E6 / Fs) (figure 4.47)
* downsampled (single-rate) SBR not currently supported
*/
const unsigned char goalSBTab[NUM_SAMPLE_RATES_SBR] = {
21, 23, 32, 43, 46, 64, 85, 93, 128
};
const HuffInfo huffTabSBRInfo[10] PROGMEM = {
{19, { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 2, 7, 4, 8, 72, 0}, 0},
{20, { 0, 2, 2, 2, 2, 2, 1, 3, 3, 2, 4, 4, 4, 3, 2, 5, 6, 13, 15, 46}, 121},
{17, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 0, 0, 1, 25, 10, 0, 0, 0}, 242},
{19, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 1, 0, 1, 1, 2, 1, 29, 2, 0}, 291},
{19, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 2, 5, 1, 4, 2, 3, 34, 0}, 340},
{20, { 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 1, 2, 3, 4, 4, 7, 10, 16}, 403},
{14, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 13, 2, 0, 0, 0, 0, 0, 0}, 466},
{14, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 6, 8, 0, 0, 0, 0, 0, 0}, 491},
{14, { 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 1, 0, 51, 2, 0, 0, 0, 0, 0, 0}, 516},
{ 8, { 1, 1, 1, 0, 1, 1, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 579},
};
/* Huffman tables from appendix 4.A.6.1, includes offset of -LAV[i] for table i */
const signed int /*short*/ huffTabSBR[604] PROGMEM = {
/* SBR table sbr_tenv15 [121] (signed) */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8,
-9, 8, -10, 9, -11, 10, -12, -13, 11, -14, 12, -15, -16, 13, -19, -18,
-17, 14, -24, -20, 16, -26, -21, 15, -23, -25, -22, -60, -59, -58, -57, -56,
-55, -54, -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40,
-39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60,
/* SBR table sbr_fenv15 [121] (signed) */
0, -1, 1, -2, -3, 2, -4, 3, -5, 4, -6, 5, -7, 6, -8, 7,
-9, 8, -10, 9, -11, 10, 11, -12, 12, -13, 13, 14, -14, -15, 15, 16,
17, -16, -17, -18, -19, 18, 19, -20, -21, 20, 21, -24, -23, -22, -26, -28,
22, 23, 25, -41, -25, 26, 27, -30, -27, 24, 28, 44, -51, -46, -44, -43,
-37, -33, -31, -29, 30, 37, 42, 47, 48, -60, -59, -58, -57, -56, -55, -54,
-53, -52, -50, -49, -48, -47, -45, -42, -40, -39, -38, -36, -35, -34, -32, 29,
31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 43, 45, 46, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60,
/* SBR table sbr_tenv15b [49] (signed) */
0, 1, -1, 2, -2, 3, -3, 4, -4, -5, 5, -6, 6, 7, -7, 8,
-24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9,
-8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24,
/* SBR table sbr_fenv15b [49] (signed) */
0, -1, 1, -2, 2, 3, -3, -4, 4, -5, 5, -6, 6, -7, 7, 8,
-9, -8, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11,
-10, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24,
/* SBR table sbr_tenv30 [63] (signed) */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, -7, 6, -8, 7,
-9, -10, 8, 9, 10, -13, -11, -12, -14, 11, 12, -31, -30, -29, -28, -27,
-26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
/* SBR table sbr_fenv30 [63] (signed) */
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8,
8, 9, -9, -10, 10, 11, -11, -12, 12, 13, -13, -15, 14, 15, -14, 18,
-18, -24, -19, 16, 17, -22, -21, -16, 20, 21, 22, 25, -23, -20, 24, -31,
-30, -29, -28, -27, -26, -25, -17, 19, 23, 26, 27, 28, 29, 30, 31,
/* SBR table sbr_tenv30b [25] (signed) */
0, 1, -1, -2, 2, 3, -3, -4, 4, -5, -12, -11, -10, -9, -8, -7,
-6, 5, 6, 7, 8, 9, 10, 11, 12,
/* SBR table sbr_fenv30b [25] (signed) */
0, -1, 1, -2, 2, 3, -3, -4, 4, -5, 5, 6, -12, -11, -10, -9,
-8, -7, -6, 7, 8, 9, 10, 11, 12,
/* SBR table sbr_tnoise30 [63] (signed) */
0, 1, -1, -2, 2, -3, 3, -4, 4, -5, 5, 11, -31, -30, -29, -28,
-27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12,
-11, -10, -9, -8, -7, -6, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
/* SBR table sbr_tnoise30b [25] (signed) */
0, -1, 1, -2, 2, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12,
};
/* log2Tab[x] = floor(log2(x)), format = Q28 */
const int log2Tab[65] PROGMEM = {
0x00000000, 0x00000000, 0x10000000, 0x195c01a3, 0x20000000, 0x25269e12, 0x295c01a3, 0x2ceaecfe,
0x30000000, 0x32b80347, 0x35269e12, 0x3759d4f8, 0x395c01a3, 0x3b350047, 0x3ceaecfe, 0x3e829fb6,
0x40000000, 0x41663f6f, 0x42b80347, 0x43f782d7, 0x45269e12, 0x4646eea2, 0x4759d4f8, 0x48608280,
0x495c01a3, 0x4a4d3c25, 0x4b350047, 0x4c1404ea, 0x4ceaecfe, 0x4dba4a47, 0x4e829fb6, 0x4f446359,
0x50000000, 0x50b5d69b, 0x51663f6f, 0x52118b11, 0x52b80347, 0x5359ebc5, 0x53f782d7, 0x549101ea,
0x55269e12, 0x55b88873, 0x5646eea2, 0x56d1fafd, 0x5759d4f8, 0x57dea15a, 0x58608280, 0x58df988f,
0x595c01a3, 0x59d5d9fd, 0x5a4d3c25, 0x5ac24113, 0x5b350047, 0x5ba58feb, 0x5c1404ea, 0x5c80730b,
0x5ceaecfe, 0x5d53847a, 0x5dba4a47, 0x5e1f4e51, 0x5e829fb6, 0x5ee44cd5, 0x5f446359, 0x5fa2f045,
0x60000000
};
/* coefficient table 4.A.87, format = Q31
* reordered as:
* cTab[0], cTab[64], cTab[128], cTab[192], cTab[256],
* cTab[2], cTab[66], cTab[130], cTab[194], cTab[258],
* ...
* cTab[64], cTab[128], cTab[192], cTab[256], cTab[320]
*
* NOTE: cTab[1, 2, ... , 318, 319] = cTab[639, 638, ... 322, 321]
* except cTab[384] = -cTab[256], cTab[512] = -cTab[128]
*/
const int cTabA[165] PROGMEM = {
0x00000000, 0x0055dba1, 0x01b2e41d, 0x09015651, 0x2e3a7532, 0xffed978a, 0x006090c4, 0x01fd3ba0, 0x08a24899, 0x311af3a4,
0xfff0065d, 0x006b47fa, 0x024bf7a1, 0x082f552e, 0x33ff670e, 0xffef7b8b, 0x0075fded, 0x029e35b4, 0x07a8127d, 0x36e69691,
0xffee1650, 0x00807994, 0x02f3e48d, 0x070bbf58, 0x39ce0477, 0xffecc31b, 0x008a7dd7, 0x034d01f0, 0x06593912, 0x3cb41219,
0xffeb50b2, 0x009424c6, 0x03a966bb, 0x0590a67d, 0x3f962fb8, 0xffe9ca76, 0x009d10bf, 0x04083fec, 0x04b0adcb, 0x4272a385,
0xffe88ba8, 0x00a520bb, 0x04694101, 0x03b8f8dc, 0x4547daea, 0xffe79e16, 0x00abe79e, 0x04cc2fcf, 0x02a99097, 0x4812f848,
0xffe6d466, 0x00b1978d, 0x05303f87, 0x01816e06, 0x4ad237a2, 0xffe65416, 0x00b5c867, 0x05950122, 0x0040c496, 0x4d83976c,
0xffe66dd0, 0x00b8394b, 0x05f9c051, 0xfee723c6, 0x5024d70e, 0xffe69423, 0x00b8c6b0, 0x065dd56a, 0xfd7475d8, 0x52b449de,
0xffe75361, 0x00b73ab0, 0x06c0f0c0, 0xfbe8f5bd, 0x552f8ff7, 0xffe85b4b, 0x00b36acd, 0x0721bf22, 0xfa44a069, 0x579505f5,
0xffea353a, 0x00acbd2f, 0x077fedb3, 0xf887507c, 0x59e2f69e, 0xffec8409, 0x00a3508f, 0x07da2b7f, 0xf6b1f3c3, 0x5c16d0ae,
0xffef2395, 0x0096dcc2, 0x08303897, 0xf4c473c6, 0x5e2f6367, 0xfff294c3, 0x00872c63, 0x0880ffdd, 0xf2bf6ea4, 0x602b0c7f,
0xfff681d6, 0x007400b8, 0x08cb4e23, 0xf0a3959f, 0x6207f220, 0xfffb42b0, 0x005d36df, 0x090ec1fc, 0xee71b2fe, 0x63c45243,
0x00007134, 0x00426f36, 0x0949eaac, 0xec2a3f5f, 0x655f63f2, 0x0006b1cf, 0x0023b989, 0x097c1ee8, 0xe9cea84a, 0x66d76725,
0x000d31b5, 0x0000e790, 0x09a3e163, 0xe75f8bb8, 0x682b39a4, 0x001471f8, 0xffda17f2, 0x09c0e59f, 0xe4de0cb0, 0x6959709d,
0x001c3549, 0xffaea5d6, 0x09d19ca9, 0xe24b8f66, 0x6a619c5e, 0x0024dd50, 0xff7ee3f1, 0x09d5560b, 0xdfa93ab5, 0x6b42a864,
0x002d8e42, 0xff4aabc8, 0x09caeb0f, 0xdcf898fb, 0x6bfbdd98, 0x003745f9, 0xff120d70, 0x09b18a1d, 0xda3b176a, 0x6c8c4c7a,
0x004103f4, 0xfed4bec3, 0x09881dc5, 0xd7722f04, 0x6cf4073e, 0x004b6c46, 0xfe933dc0, 0x094d7ec2, 0xd49fd55f, 0x6d32730f,
0x0055dba1, 0x01b2e41d, 0x09015651, 0x2e3a7532, 0x6d474e1d,
};
/* coefficient table 4.A.87, format = Q31
* reordered as cTab[0], cTab[64], cTab[128], ... cTab[576], cTab[1], cTab[65], cTab[129], ... cTab[639]
* keeping full table (not using symmetry) to allow sequential access in synth filter inner loop
* format = Q31
*/
const int cTabS[640] PROGMEM = {
0x00000000, 0x0055dba1, 0x01b2e41d, 0x09015651, 0x2e3a7532, 0x6d474e1d, 0xd1c58ace, 0x09015651, 0xfe4d1be3, 0x0055dba1,
0xffede50e, 0x005b5371, 0x01d78bfc, 0x08d3e41b, 0x2faa221c, 0x6d41d963, 0xd3337b3d, 0x09299ead, 0xfe70b8d1, 0x0050b177,
0xffed978a, 0x006090c4, 0x01fd3ba0, 0x08a24899, 0x311af3a4, 0x6d32730f, 0xd49fd55f, 0x094d7ec2, 0xfe933dc0, 0x004b6c46,
0xffefc9b9, 0x0065fde5, 0x02244a24, 0x086b1eeb, 0x328cc6f0, 0x6d18520e, 0xd60a46e5, 0x096d0e21, 0xfeb48d0d, 0x00465348,
0xfff0065d, 0x006b47fa, 0x024bf7a1, 0x082f552e, 0x33ff670e, 0x6cf4073e, 0xd7722f04, 0x09881dc5, 0xfed4bec3, 0x004103f4,
0xffeff6ca, 0x0070c8a5, 0x0274ba43, 0x07ee507c, 0x3572ec70, 0x6cc59bab, 0xd8d7f21f, 0x099ec3dc, 0xfef3f6ab, 0x003c1fa4,
0xffef7b8b, 0x0075fded, 0x029e35b4, 0x07a8127d, 0x36e69691, 0x6c8c4c7a, 0xda3b176a, 0x09b18a1d, 0xff120d70, 0x003745f9,
0xffeedfa4, 0x007b3875, 0x02c89901, 0x075ca90c, 0x385a49c4, 0x6c492217, 0xdb9b5b12, 0x09c018ce, 0xff2ef725, 0x00329ab6,
0xffee1650, 0x00807994, 0x02f3e48d, 0x070bbf58, 0x39ce0477, 0x6bfbdd98, 0xdcf898fb, 0x09caeb0f, 0xff4aabc8, 0x002d8e42,
0xffed651d, 0x0085c217, 0x03201116, 0x06b559c3, 0x3b415115, 0x6ba4629f, 0xde529086, 0x09d1fa23, 0xff6542d1, 0x00293718,
0xffecc31b, 0x008a7dd7, 0x034d01f0, 0x06593912, 0x3cb41219, 0x6b42a864, 0xdfa93ab5, 0x09d5560b, 0xff7ee3f1, 0x0024dd50,
0xffebe77b, 0x008f4bfc, 0x037ad438, 0x05f7fb90, 0x3e25b17e, 0x6ad73e8d, 0xe0fc421e, 0x09d52709, 0xff975c01, 0x002064f8,
0xffeb50b2, 0x009424c6, 0x03a966bb, 0x0590a67d, 0x3f962fb8, 0x6a619c5e, 0xe24b8f66, 0x09d19ca9, 0xffaea5d6, 0x001c3549,
0xffea9192, 0x0098b855, 0x03d8afe6, 0x05237f9d, 0x41058bc6, 0x69e29784, 0xe396a45d, 0x09cab9f2, 0xffc4e365, 0x0018703f,
0xffe9ca76, 0x009d10bf, 0x04083fec, 0x04b0adcb, 0x4272a385, 0x6959709d, 0xe4de0cb0, 0x09c0e59f, 0xffda17f2, 0x001471f8,
0xffe940f4, 0x00a1039c, 0x043889c6, 0x0437fb0a, 0x43de620a, 0x68c7269b, 0xe620c476, 0x09b3d77f, 0xffee183b, 0x0010bc63,
0xffe88ba8, 0x00a520bb, 0x04694101, 0x03b8f8dc, 0x4547daea, 0x682b39a4, 0xe75f8bb8, 0x09a3e163, 0x0000e790, 0x000d31b5,
0xffe83a07, 0x00a8739d, 0x049aa82f, 0x03343533, 0x46aea856, 0x6785c24d, 0xe89971b7, 0x099140a7, 0x00131c75, 0x0009aa3f,
0xffe79e16, 0x00abe79e, 0x04cc2fcf, 0x02a99097, 0x4812f848, 0x66d76725, 0xe9cea84a, 0x097c1ee8, 0x0023b989, 0x0006b1cf,
0xffe7746e, 0x00af374c, 0x04fe20be, 0x02186a91, 0x4973fef1, 0x661fd6b8, 0xeafee7f1, 0x0963ed46, 0x0033b927, 0x00039609,
0xffe6d466, 0x00b1978d, 0x05303f87, 0x01816e06, 0x4ad237a2, 0x655f63f2, 0xec2a3f5f, 0x0949eaac, 0x00426f36, 0x00007134,
0xffe6afee, 0x00b3d15c, 0x05626209, 0x00e42fa2, 0x4c2ca3df, 0x64964063, 0xed50a31d, 0x092d7970, 0x00504f41, 0xfffdfa25,
0xffe65416, 0x00b5c867, 0x05950122, 0x0040c496, 0x4d83976c, 0x63c45243, 0xee71b2fe, 0x090ec1fc, 0x005d36df, 0xfffb42b0,
0xffe681c6, 0x00b74c37, 0x05c76fed, 0xff96db90, 0x4ed62be3, 0x62ea6474, 0xef8d4d7b, 0x08edfeaa, 0x006928a0, 0xfff91fca,
0xffe66dd0, 0x00b8394b, 0x05f9c051, 0xfee723c6, 0x5024d70e, 0x6207f220, 0xf0a3959f, 0x08cb4e23, 0x007400b8, 0xfff681d6,
0xffe66fac, 0x00b8fe0d, 0x062bf5ec, 0xfe310657, 0x516eefb9, 0x611d58a3, 0xf1b461ab, 0x08a75da4, 0x007e0393, 0xfff48700,
0xffe69423, 0x00b8c6b0, 0x065dd56a, 0xfd7475d8, 0x52b449de, 0x602b0c7f, 0xf2bf6ea4, 0x0880ffdd, 0x00872c63, 0xfff294c3,
0xffe6fed4, 0x00b85f70, 0x068f8b44, 0xfcb1d740, 0x53f495aa, 0x5f30ff5f, 0xf3c4e887, 0x08594887, 0x008f87aa, 0xfff0e7ef,
0xffe75361, 0x00b73ab0, 0x06c0f0c0, 0xfbe8f5bd, 0x552f8ff7, 0x5e2f6367, 0xf4c473c6, 0x08303897, 0x0096dcc2, 0xffef2395,
0xffe80414, 0x00b58c8c, 0x06f1825d, 0xfb19b7bd, 0x56654bdd, 0x5d26be9b, 0xf5be0fa9, 0x08061671, 0x009da526, 0xffedc418,
0xffe85b4b, 0x00b36acd, 0x0721bf22, 0xfa44a069, 0x579505f5, 0x5c16d0ae, 0xf6b1f3c3, 0x07da2b7f, 0x00a3508f, 0xffec8409,
0xffe954d0, 0x00b06b68, 0x075112a2, 0xf96916f5, 0x58befacd, 0x5b001db8, 0xf79fa13a, 0x07ad8c26, 0x00a85e94, 0xffeb3849,
0xffea353a, 0x00acbd2f, 0x077fedb3, 0xf887507c, 0x59e2f69e, 0x59e2f69e, 0xf887507c, 0x077fedb3, 0x00acbd2f, 0xffea353a,
0xffeb3849, 0x00a85e94, 0x07ad8c26, 0xf79fa13a, 0x5b001db8, 0x58befacd, 0xf96916f5, 0x075112a2, 0x00b06b68, 0xffe954d0,
0xffec8409, 0x00a3508f, 0x07da2b7f, 0xf6b1f3c3, 0x5c16d0ae, 0x579505f5, 0xfa44a069, 0x0721bf22, 0x00b36acd, 0xffe85b4b,
0xffedc418, 0x009da526, 0x08061671, 0xf5be0fa9, 0x5d26be9b, 0x56654bdd, 0xfb19b7bd, 0x06f1825d, 0x00b58c8c, 0xffe80414,
0xffef2395, 0x0096dcc2, 0x08303897, 0xf4c473c6, 0x5e2f6367, 0x552f8ff7, 0xfbe8f5bd, 0x06c0f0c0, 0x00b73ab0, 0xffe75361,
0xfff0e7ef, 0x008f87aa, 0x08594887, 0xf3c4e887, 0x5f30ff5f, 0x53f495aa, 0xfcb1d740, 0x068f8b44, 0x00b85f70, 0xffe6fed4,
0xfff294c3, 0x00872c63, 0x0880ffdd, 0xf2bf6ea4, 0x602b0c7f, 0x52b449de, 0xfd7475d8, 0x065dd56a, 0x00b8c6b0, 0xffe69423,
0xfff48700, 0x007e0393, 0x08a75da4, 0xf1b461ab, 0x611d58a3, 0x516eefb9, 0xfe310657, 0x062bf5ec, 0x00b8fe0d, 0xffe66fac,
0xfff681d6, 0x007400b8, 0x08cb4e23, 0xf0a3959f, 0x6207f220, 0x5024d70e, 0xfee723c6, 0x05f9c051, 0x00b8394b, 0xffe66dd0,
0xfff91fca, 0x006928a0, 0x08edfeaa, 0xef8d4d7b, 0x62ea6474, 0x4ed62be3, 0xff96db90, 0x05c76fed, 0x00b74c37, 0xffe681c6,
0xfffb42b0, 0x005d36df, 0x090ec1fc, 0xee71b2fe, 0x63c45243, 0x4d83976c, 0x0040c496, 0x05950122, 0x00b5c867, 0xffe65416,
0xfffdfa25, 0x00504f41, 0x092d7970, 0xed50a31d, 0x64964063, 0x4c2ca3df, 0x00e42fa2, 0x05626209, 0x00b3d15c, 0xffe6afee,
0x00007134, 0x00426f36, 0x0949eaac, 0xec2a3f5f, 0x655f63f2, 0x4ad237a2, 0x01816e06, 0x05303f87, 0x00b1978d, 0xffe6d466,
0x00039609, 0x0033b927, 0x0963ed46, 0xeafee7f1, 0x661fd6b8, 0x4973fef1, 0x02186a91, 0x04fe20be, 0x00af374c, 0xffe7746e,
0x0006b1cf, 0x0023b989, 0x097c1ee8, 0xe9cea84a, 0x66d76725, 0x4812f848, 0x02a99097, 0x04cc2fcf, 0x00abe79e, 0xffe79e16,
0x0009aa3f, 0x00131c75, 0x099140a7, 0xe89971b7, 0x6785c24d, 0x46aea856, 0x03343533, 0x049aa82f, 0x00a8739d, 0xffe83a07,
0x000d31b5, 0x0000e790, 0x09a3e163, 0xe75f8bb8, 0x682b39a4, 0x4547daea, 0x03b8f8dc, 0x04694101, 0x00a520bb, 0xffe88ba8,
0x0010bc63, 0xffee183b, 0x09b3d77f, 0xe620c476, 0x68c7269b, 0x43de620a, 0x0437fb0a, 0x043889c6, 0x00a1039c, 0xffe940f4,
0x001471f8, 0xffda17f2, 0x09c0e59f, 0xe4de0cb0, 0x6959709d, 0x4272a385, 0x04b0adcb, 0x04083fec, 0x009d10bf, 0xffe9ca76,
0x0018703f, 0xffc4e365, 0x09cab9f2, 0xe396a45d, 0x69e29784, 0x41058bc6, 0x05237f9d, 0x03d8afe6, 0x0098b855, 0xffea9192,
0x001c3549, 0xffaea5d6, 0x09d19ca9, 0xe24b8f66, 0x6a619c5e, 0x3f962fb8, 0x0590a67d, 0x03a966bb, 0x009424c6, 0xffeb50b2,
0x002064f8, 0xff975c01, 0x09d52709, 0xe0fc421e, 0x6ad73e8d, 0x3e25b17e, 0x05f7fb90, 0x037ad438, 0x008f4bfc, 0xffebe77b,
0x0024dd50, 0xff7ee3f1, 0x09d5560b, 0xdfa93ab5, 0x6b42a864, 0x3cb41219, 0x06593912, 0x034d01f0, 0x008a7dd7, 0xffecc31b,
0x00293718, 0xff6542d1, 0x09d1fa23, 0xde529086, 0x6ba4629f, 0x3b415115, 0x06b559c3, 0x03201116, 0x0085c217, 0xffed651d,
0x002d8e42, 0xff4aabc8, 0x09caeb0f, 0xdcf898fb, 0x6bfbdd98, 0x39ce0477, 0x070bbf58, 0x02f3e48d, 0x00807994, 0xffee1650,
0x00329ab6, 0xff2ef725, 0x09c018ce, 0xdb9b5b12, 0x6c492217, 0x385a49c4, 0x075ca90c, 0x02c89901, 0x007b3875, 0xffeedfa4,
0x003745f9, 0xff120d70, 0x09b18a1d, 0xda3b176a, 0x6c8c4c7a, 0x36e69691, 0x07a8127d, 0x029e35b4, 0x0075fded, 0xffef7b8b,
0x003c1fa4, 0xfef3f6ab, 0x099ec3dc, 0xd8d7f21f, 0x6cc59bab, 0x3572ec70, 0x07ee507c, 0x0274ba43, 0x0070c8a5, 0xffeff6ca,
0x004103f4, 0xfed4bec3, 0x09881dc5, 0xd7722f04, 0x6cf4073e, 0x33ff670e, 0x082f552e, 0x024bf7a1, 0x006b47fa, 0xfff0065d,
0x00465348, 0xfeb48d0d, 0x096d0e21, 0xd60a46e5, 0x6d18520e, 0x328cc6f0, 0x086b1eeb, 0x02244a24, 0x0065fde5, 0xffefc9b9,
0x004b6c46, 0xfe933dc0, 0x094d7ec2, 0xd49fd55f, 0x6d32730f, 0x311af3a4, 0x08a24899, 0x01fd3ba0, 0x006090c4, 0xffed978a,
0x0050b177, 0xfe70b8d1, 0x09299ead, 0xd3337b3d, 0x6d41d963, 0x2faa221c, 0x08d3e41b, 0x01d78bfc, 0x005b5371, 0xffede50f,
};
/* noise table 4.A.88, format = Q31 */
const int noiseTab[512*2] PROGMEM = {
0x8010fd38, 0xb3dc7948, 0x7c4e2301, 0xa9904192, 0x121622a7, 0x86489625, 0xc3d53d25, 0xd0343fa9,
0x674d6f70, 0x25f4e9fd, 0xce1a8c8b, 0x72a726c5, 0xfea6efc6, 0xaa4adb1a, 0x8b2dd628, 0xf14029e4,
0x46321c1a, 0x604889a0, 0x33363b63, 0x815ed069, 0x802b4315, 0x8f2bf7f3, 0x85b86073, 0x745cfb46,
0xc57886b3, 0xb76731f0, 0xa2a66772, 0x828ca631, 0x60cc145e, 0x1ad1010f, 0x090c83d4, 0x9bd7ba87,
0x5f5aeea2, 0x8b4dbd99, 0x848e7b1e, 0x86bb9fa2, 0x26f18ae5, 0xc0b81194, 0x553407bf, 0x52c17953,
0x755f468d, 0x166b04f8, 0xa5687981, 0x4343248b, 0xa6558d5e, 0xc5f6fab7, 0x80a4fb8c, 0x8cb53cb7,
0x7da68a54, 0x9cd8df8a, 0xba05376c, 0xfcb58ee2, 0xfdd657a4, 0x005e35ca, 0x91c75c55, 0x367651e6,
0x816abf85, 0x8f831c4f, 0x423f9c9c, 0x55aa919e, 0x80779834, 0xb59f4244, 0x800a095c, 0x7de9e0cc,
0x46bda5cb, 0x4c184464, 0x2c438f71, 0x797216b5, 0x5035cee6, 0xa0c3a26e, 0x9d3f95fa, 0xd4a100c0,
0x8ac30dac, 0x04b87397, 0x9e5ac516, 0x8b0b442e, 0x66210ad6, 0x88ba7598, 0x45b9bd33, 0xf0be5087,
0x9261b85e, 0x364f6a31, 0x891c4b50, 0x23ad08ce, 0xf10366a6, 0x80414276, 0x1b562e06, 0x8be21591,
0x9e798195, 0x7fb4045c, 0x7d9506cf, 0x854e691f, 0x9207f092, 0x7a94c9d5, 0x88911536, 0x3f45cc61,
0x27059279, 0xa5b57109, 0x6d2bb67b, 0x3bdc5379, 0x74e662d8, 0x80348f8c, 0xf875e638, 0x5a8caea1,
0x2459ae75, 0x2c54b939, 0x79ee3203, 0xb9bc8683, 0x9b6f630c, 0x9f45b351, 0x8563b2b9, 0xe5dbba41,
0x697c7d0d, 0x7bb7c90e, 0xac900866, 0x8e6b5177, 0x8822dd37, 0x7fd5a91e, 0x7506da05, 0x82302aca,
0xa5e4be04, 0x4b4288eb, 0x00b8bc9f, 0x4f1033e4, 0x7200d612, 0x43900c8c, 0xa815b900, 0x676ed1d4,
0x5c5f23b2, 0xa758ee11, 0xaf73abfa, 0x11714ec0, 0x265239e0, 0xc50de679, 0x8a84e341, 0xa1438354,
0x7f1a341f, 0x343ec96b, 0x696e71b0, 0xa13bde39, 0x81e75094, 0x80091111, 0x853a73bf, 0x80f9c1ee,
0xe4980086, 0x886a8e28, 0xa7e89426, 0xdd93edd7, 0x7592100d, 0x0bfa8123, 0x850a26d4, 0x2e34f395,
0x421b6c00, 0xa4a462e4, 0x4e3f5090, 0x3c189f4c, 0x3c971a56, 0xdd0376d2, 0x747a5367, 0x7bcbc9d7,
0x3966be6a, 0x7efda616, 0x55445e15, 0x7ba2ab3f, 0x5fe684f2, 0x8cf42af9, 0x808c61c3, 0x4390c27b,
0x7cac62ff, 0xea6cab22, 0x5d0902ad, 0xc27b7208, 0x7a27389d, 0x5820a357, 0xa29bbe59, 0x9df0f1fd,
0x92bd67e5, 0x7195b587, 0x97cac65b, 0x8339807e, 0x8f72d832, 0x5fad8685, 0xa462d9d3, 0x81d46214,
0x6ae93e1d, 0x6b23a5b9, 0xc2732874, 0x81795268, 0x7c568cb6, 0x668513ea, 0x428d024e, 0x66b78b3a,
0xfee9ef03, 0x9ddcbb82, 0xa605f07e, 0x46dc55e0, 0x85415054, 0xc89ec271, 0x7c42edfb, 0x0befe59b,
0x89b8f607, 0x6d732a1a, 0xa7081ebd, 0x7e403258, 0x21feeb7b, 0x5dd7a1e7, 0x23e3a31a, 0x129bc896,
0xa11a6b54, 0x7f1e031c, 0xfdc1a4d1, 0x96402e53, 0xb9700f1a, 0x8168ecd6, 0x7d63d3cc, 0x87a70d65,
0x81075a7a, 0x55c8caa7, 0xa95d00b5, 0x102b1652, 0x0bb30215, 0xe5b63237, 0xa446ca44, 0x82d4c333,
0x67b2e094, 0x44c3d661, 0x33fd6036, 0xde1ea2a1, 0xa95e8e47, 0x78f66eb9, 0x6f2aef1e, 0xe8887247,
0x80a3b70e, 0xfca0d9d3, 0x6bf0fd20, 0x0d5226de, 0xf4341c87, 0x5902df05, 0x7ff1a38d, 0xf02e5a5b,
0x99f129af, 0x8ac63d01, 0x7b53f599, 0x7bb32532, 0x99ac59b0, 0x5255a80f, 0xf1320a41, 0x2497aa5c,
0xcce60bd8, 0x787c634b, 0x7ed58c5b, 0x8a28eb3a, 0x24a5e647, 0x8b79a2c1, 0x955f5ce5, 0xa9d12bc4,
0x7a1e20c6, 0x3eeda7ac, 0xf7be823a, 0x042924ce, 0x808b3f03, 0x364248da, 0xac2895e5, 0x69a8b5fa,
0x97fe8b63, 0xbdeac9aa, 0x8073e0ad, 0x6c25dba7, 0x005e51d2, 0x52e74389, 0x59d3988c, 0xe5d1f39c,
0x7b57dc91, 0x341adbe7, 0xa7d42b8d, 0x74e9f335, 0xd35bf7d8, 0x5b7c0a4b, 0x75bc0874, 0x552129bf,
0x8144b70d, 0x6de93bbb, 0x5825f14b, 0x473ec5ca, 0x80a8f37c, 0xe6552d69, 0x7898360b, 0x806379b0,
0xa9b59339, 0x3f6bf60c, 0xc367d731, 0x920ade99, 0x125592f7, 0x877e5ed1, 0xda895d95, 0x075f2ece,
0x380e5f5e, 0x9b006b62, 0xd17a6dd2, 0x530a0e13, 0xf4cc9a14, 0x7d0a0ed4, 0x847c6e3f, 0xbaee4975,
0x47131163, 0x64fb2cac, 0x5e2100a6, 0x7b756a42, 0xd87609f4, 0x98bfe48c, 0x0493745e, 0x836c5784,
0x7e5ccb40, 0x3df6b476, 0x97700d28, 0x8bbd93fd, 0x56de9cdb, 0x680b4e65, 0xebc3d90e, 0x6d286793,
0x6753712e, 0xe05c98a7, 0x3d2b6b85, 0xc4b18ddb, 0x7b59b869, 0x31435688, 0x811888e9, 0xe011ee7a,
0x6a5844f9, 0x86ae35ea, 0xb4cbc10b, 0x01a6f5d6, 0x7a49ed64, 0x927caa49, 0x847ddaed, 0xae0d9bb6,
0x836bdb04, 0x0fd810a6, 0x74fe126b, 0x4a346b5f, 0x80184d36, 0x5afd153c, 0x90cc8102, 0xe606d0e6,
0xde69aa58, 0xa89f1222, 0xe06df715, 0x8fd16144, 0x0317c3e8, 0x22ce92fc, 0x690c3eca, 0x93166f02,
0x71573414, 0x8d43cffb, 0xe8bd0bb6, 0xde86770f, 0x0bf99a41, 0x4633a661, 0xba064108, 0x7adafae3,
0x2f6cde5d, 0xb350a52c, 0xa5ebfb0b, 0x74c57b46, 0xd3b603b5, 0x80b70892, 0xa7f7fa53, 0xd94b566c,
0xdda3fd86, 0x6a635793, 0x3ed005ca, 0xc5f087d8, 0x31e3a746, 0x7a4278f9, 0x82def1f9, 0x06caa2b2,
0xe9d2c349, 0x8940e7f7, 0x7feef8dd, 0x4a9b01f0, 0xacde69f8, 0x57ddc280, 0xf09e4ba4, 0xb6d9f729,
0xb48c18f2, 0xd3654aa9, 0xca7a03c8, 0x14d57545, 0x7fda87a5, 0x0e411366, 0xb77d0df0, 0x8c2aa467,
0x787f2590, 0x2d292db1, 0x9f12682c, 0x44ac364d, 0x1a4b31a6, 0x871f7ded, 0x7ff99167, 0x6630a1d5,
0x25385eb9, 0x2d4dd549, 0xaf8a7004, 0x319ebe0f, 0x379ab730, 0x81dc56a4, 0x822d8523, 0x1ae8554c,
0x18fa0786, 0x875f7de4, 0x85ca350f, 0x7de818dc, 0x7786a38f, 0xa5456355, 0x92e60f88, 0xf5526122,
0x916039bc, 0xc561e2de, 0x31c42042, 0x7c82e290, 0x75d158b2, 0xb015bda1, 0x7220c750, 0x46565441,
0xd0da1fdd, 0x7b777481, 0x782e73c6, 0x8cd72b7b, 0x7f1006aa, 0xfb30e51e, 0x87994818, 0x34e7c7db,
0x7faae06b, 0xea74fbc0, 0xd20c7af4, 0xc44f396b, 0x06b4234e, 0xdf2e2a93, 0x2efb07c8, 0xce861911,
0x7550ea05, 0xd8d90bbb, 0x58522eec, 0x746b3520, 0xce844ce9, 0x7f5cacc3, 0xda8f17e0, 0x2fedf9cb,
0xb2f77ec4, 0x6f13f4c0, 0x834de085, 0x7b7ace4b, 0x713b16ac, 0x499c5ab0, 0x06a7961d, 0x1b39a48a,
0xbb853e6e, 0x7c781cc1, 0xc0baebf5, 0x7dace394, 0x815ceebc, 0xcc7b27d4, 0x8274b181, 0xa2be40a2,
0xdd01d5dc, 0x7fefeb14, 0x0813ec78, 0xba3077cc, 0xe5cf1e1c, 0xedcfacae, 0x54c43a9b, 0x5cd62a42,
0x93806b55, 0x03095c5b, 0x8e076ae3, 0x71bfcd2a, 0x7ac1989b, 0x623bc71a, 0x5e15d4d2, 0xfb341dd1,
0xd75dfbca, 0xd0da32be, 0xd4569063, 0x337869da, 0x3d30606a, 0xcd89cca2, 0x7dd2ae36, 0x028c03cd,
0xd85e052c, 0xe8dc9ec5, 0x7ffd9241, 0xde5bf4c6, 0x88c4b235, 0x8228be2e, 0x7fe6ec64, 0x996abe6a,
0xdeb0666d, 0x9eb86611, 0xd249b922, 0x18b3e26b, 0x80211168, 0x5f8bb99c, 0x6ecb0dd2, 0x4728ff8d,
0x2ac325b8, 0x6e5169d2, 0x7ebbd68d, 0x05e41d17, 0xaaa19f28, 0x8ab238a6, 0x51f105be, 0x140809cc,
0x7f7345d9, 0x3aae5a9d, 0xaecec6e4, 0x1afb3473, 0xf6229ed1, 0x8d55f467, 0x7e32003a, 0x70f30c14,
0x6686f33f, 0xd0d45ed8, 0x644fab57, 0x3a3fbbd3, 0x0b255fc4, 0x679a1701, 0x90e17b6e, 0x325d537b,
0xcd7b9b87, 0xaa7be2a2, 0x7d47c966, 0xa33dbce5, 0x8659c3bb, 0x72a41367, 0x15c446e0, 0x45fe8b0a,
0x9d8ddf26, 0x84d47643, 0x7fabe0da, 0x36a70122, 0x7a28ebfe, 0x7c29b8b8, 0x7f760406, 0xbabe4672,
0x23ea216e, 0x92bcc50a, 0x6d20dba2, 0xad5a7c7e, 0xbf3897f5, 0xabb793e1, 0x8391fc7e, 0xe270291c,
0x7a248d58, 0x80f8fd15, 0x83ef19f3, 0x5e6ece7d, 0x278430c1, 0x35239f4d, 0xe09c073b, 0x50e78cb5,
0xd4b811bd, 0xce834ee0, 0xf88aaa34, 0xf71da5a9, 0xe2b0a1d5, 0x7c3aef31, 0xe84eabca, 0x3ce25964,
0xf29336d3, 0x8fa78b2c, 0xa3fc3415, 0x63e1313d, 0x7fbc74e0, 0x7340bc93, 0x49ae583b, 0x8b79de4b,
0x25011ce9, 0x7b462279, 0x36007db0, 0x3da1599c, 0x77780772, 0xc845c9bb, 0x83ba68be, 0x6ee507d1,
0x2f0159b8, 0x5392c4ed, 0x98336ff6, 0x0b3c7f11, 0xde697aac, 0x893fc8d0, 0x6b83f8f3, 0x47799a0d,
0x801d9dfc, 0x8516a83e, 0x5f8d22ec, 0x0f8ba384, 0xa049dc4b, 0xdd920b05, 0x7a99bc9f, 0x9ad19344,
0x7a345dba, 0xf501a13f, 0x3e58bf19, 0x7fffaf9a, 0x3b4e1511, 0x0e08b991, 0x9e157620, 0x7230a326,
0x4977f9ff, 0x2d2bbae1, 0x607aa7fc, 0x7bc85d5f, 0xb441bbbe, 0x8d8fa5f2, 0x601cce26, 0xda1884f2,
0x81c82d64, 0x200b709c, 0xcbd36abe, 0x8cbdddd3, 0x55ab61d3, 0x7e3ee993, 0x833f18aa, 0xffc1aaea,
0x7362e16a, 0x7fb85db2, 0x904ee04c, 0x7f04dca6, 0x8ad7a046, 0xebe7d8f7, 0xfbc4c687, 0xd0609458,
0x093ed977, 0x8e546085, 0x7f5b8236, 0x7c47e118, 0xa01f2641, 0x7ffb3e48, 0x05de7cda, 0x7fc281b9,
0x8e0278fc, 0xd74e6d07, 0x94c24450, 0x7cf9e641, 0x2ad27871, 0x919fa815, 0x805fd205, 0x7758397f,
0xe2c7e02c, 0x1828e194, 0x5613d6fe, 0xfb55359f, 0xf9699516, 0x8978ee26, 0x7feebad9, 0x77d71d82,
0x55b28b60, 0x7e997600, 0x80821a6b, 0xc6d78af1, 0x691822ab, 0x7f6982a0, 0x7ef56f99, 0x5c307f40,
0xac6f8b76, 0x42cc8ba4, 0x782c61d9, 0xa0224dd0, 0x7bd234d1, 0x74576e3b, 0xe38cfe9a, 0x491e66ef,
0xc78291c5, 0x895bb87f, 0x924f7889, 0x71b89394, 0x757b779d, 0xc4a9c604, 0x5cdf7829, 0x8020e9df,
0x805e8245, 0x4a82c398, 0x6360bd62, 0x78bb60fc, 0x09e0d014, 0x4b0ea180, 0xb841978b, 0x69a0e864,
0x7df35977, 0x3284b0dd, 0x3cdc2efd, 0x57d31f5e, 0x541069cc, 0x1776e92e, 0x04309ea3, 0xa015eb2d,
0xce7bfabc, 0x41b638f8, 0x8365932e, 0x846ab44c, 0xbbcc80cb, 0x8afa6cac, 0x7fc422ea, 0x4e403fc0,
0xbfac9aee, 0x8e4c6709, 0x028e01fb, 0x6d160a9b, 0x7fe93004, 0x790f9cdc, 0x6a1f37a0, 0xf7e7ef30,
0xb4ea0f04, 0x7bf4c8e6, 0xe981701f, 0xc258a9d3, 0x6acbbfba, 0xef5479c7, 0x079c8bd8, 0x1a410f56,
0x6853b799, 0x86cd4f01, 0xc66e23b6, 0x34585565, 0x8d1fe00d, 0x7fcdba1a, 0x32c9717b, 0xa02f9f48,
0xf64940db, 0x5ed7d8f1, 0x61b823b2, 0x356f8918, 0xa0a7151e, 0x793fc969, 0x530beaeb, 0x34e93270,
0x4fc4ddb5, 0x88d58b6c, 0x36094774, 0xf620ac80, 0x03763a72, 0xf910c9a6, 0x6666fb2d, 0x752c8be8,
0x9a6dfdd8, 0xd1a7117d, 0x51c1b1d4, 0x0a67773d, 0x43b32a79, 0x4cdcd085, 0x5f067d30, 0x05bfe92a,
0x7ed7d203, 0xe71a3c85, 0x99127ce2, 0x8eb3cac4, 0xad4bbcea, 0x5c6a0fd0, 0x0eec04af, 0x94e95cd4,
0x8654f921, 0x83eabb5d, 0xb058d7ca, 0x69f12d3c, 0x03d881b2, 0x80558ef7, 0x82938cb3, 0x2ec0e1d6,
0x80044422, 0xd1e47051, 0x720fc6ff, 0x82b20316, 0x0d527b02, 0x63049a15, 0x7ad5b9ad, 0xd2a4641d,
0x41144f86, 0x7b04917a, 0x15c4a2c0, 0x9da07916, 0x211df54a, 0x7fdd09af, 0xfe924f3f, 0x7e132cfe,
0x9a1d18d6, 0x7c56508b, 0x80f0f0af, 0x8095ced6, 0x8037d0d7, 0x026719d1, 0xa55fec43, 0x2b1c7cb7,
0xa5cd5ac1, 0x77639fad, 0x7fcd8b62, 0x81a18c27, 0xaee4912e, 0xeae9eebe, 0xeb3081de, 0x8532aada,
0xc822362e, 0x86a649a9, 0x8031a71d, 0x7b319dc6, 0xea8022e6, 0x814bc5a9, 0x8f62f7a1, 0xa430ea17,
0x388deafb, 0x883b5185, 0x776fe13c, 0x801c683f, 0x87c11b98, 0xb7cbc644, 0x8e9ad3e8, 0x3cf5a10c,
0x7ff6a634, 0x949ef096, 0x9f84aa7c, 0x010af13f, 0x782d1de8, 0xf18e492a, 0x6cf63b01, 0x4301cd81,
0x32d15c9e, 0x68ad8cef, 0xd09bd2d6, 0x908c5c15, 0xd1e36260, 0x2c5bfdd0, 0x88765a99, 0x93deba1e,
0xac6ae342, 0xe865b84c, 0x0f4f2847, 0x7fdf0499, 0x78b1c9b3, 0x6a73261e, 0x601a96f6, 0xd2847933,
0x489aa888, 0xe12e8093, 0x3bfa5a5f, 0xd96ba5f7, 0x7c8f4c8d, 0x80940c6f, 0xcef9dd1a, 0x7e1a055f,
0x3483558b, 0x02b59cc4, 0x0c56333e, 0x05a5b813, 0x92d66287, 0x7516b679, 0x71bfe03f, 0x8056bf68,
0xc24d0724, 0x8416bcf3, 0x234afbdb, 0x4b0d6f9c, 0xaba97333, 0x4b4f42b6, 0x7e8343ab, 0x7ffe2603,
0xe590f73c, 0x45e10c76, 0xb07a6a78, 0xb35609d3, 0x1a027dfd, 0x90cb6e20, 0x82d3fe38, 0x7b409257,
0x0e395afa, 0x1b802093, 0xcb0c6c59, 0x241e17e7, 0x1ee3ea0a, 0x41a82302, 0xab04350a, 0xf570beb7,
0xbb444b9b, 0x83021459, 0x838d65dc, 0x1c439c84, 0x6fdcc454, 0xef9ef325, 0x18626c1c, 0x020d251f,
0xc4aae786, 0x8614cb48, 0xf6f53ca6, 0x8710dbab, 0x89abec0d, 0xf29d41c1, 0x94b50336, 0xfdd49178,
0x604658d1, 0x800e85be, 0xca1bb079, 0x7fa48eeb, 0xa3b7fafe, 0xd330436b, 0x64eb604c, 0x43a658ae,
0x7caa1337, 0xddd445e6, 0x7efbf955, 0xb706ec71, 0x624a6b53, 0x9e0e231f, 0x97097248, 0xa1e1a17a,
0x68dd2e44, 0x7f9d2e14, 0xddcc7074, 0x58324197, 0xc88fc426, 0x6d3640ae, 0x7ef83600, 0x759a0270,
0x98b6d854, 0xd63c9b84, 0x372474a2, 0xe3f18cfd, 0x56ab0bdb, 0x85c9be7e, 0x47dfcfeb, 0xa5830d41,
0x0ddd6283, 0xf4f480ad, 0x74c60e38, 0xab8943c3, 0xc1508fe7, 0x480cdc39, 0x8e097362, 0xa44793be,
0x538b7e18, 0x545f5b41, 0x56529175, 0x9771a97e, 0xc2da7421, 0xea8265f2, 0x805d1163, 0x883c5d28,
0x8ba94c48, 0x4f676e65, 0xf78735b3, 0xe1853671, 0x7f454f53, 0x18147f85, 0x7d09e15d, 0xdb4f3494,
0x795c8973, 0x83310632, 0x85d8061c, 0x9a1a0ebf, 0xc125583c, 0x2a1b1a95, 0x7fd9103f, 0x71e98c72,
0x40932ed7, 0x91ed227a, 0x3c5e560e, 0xe816dee9, 0xb0891b80, 0x600038ba, 0xc7d9a80d, 0x7fff5e09,
0x7e3f4351, 0xbb6b4424, 0xb14448d4, 0x8d6bb7e1, 0xfb153626, 0xa68ad537, 0xd9782006, 0xf62f6991,
0x359ba8c1, 0x02ccff0b, 0x91bf2256, 0x7ea71c4d, 0x560ce5df, 0xeeba289b, 0xa574c4e7, 0x9e04f6ee,
0x7860a5ec, 0x0b8db4a2, 0x968ba3d7, 0x0b6c77df, 0xd6f3157d, 0x402eff1a, 0x49b820b3, 0x8152aebb,
0xd180b0b6, 0x098604d4, 0x7ff92224, 0xede9c996, 0x89c58061, 0x829624c4, 0xc6e71ea7, 0xba94d915,
0x389c3cf6, 0x5b4c5a06, 0x04b335e6, 0x516a8aab, 0x42c8d7d9, 0x92b12af6, 0x86c8549f, 0xfda98acf,
0x819673b6, 0x69545dac, 0x6feaa230, 0x726e6d3f, 0x886ebdfe, 0x34f5730a, 0x7af63ba2, 0x77307bbf,
0x7cd80630, 0x6e45efe0, 0x7f8ad7eb, 0x59d7df99, 0x86c70946, 0xda233629, 0x753f6cbf, 0x825eeb40,
};

View File

@@ -1,115 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: statname.h,v 1.1 2005/02/26 01:47:34 jrecker 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
*
* statname.h - name mangling macros for static linking
**************************************************************************************/
#ifndef _STATNAME_H
#define _STATNAME_H
/* define STAT_PREFIX to a unique name for static linking
* all the C functions and global variables will be mangled by the preprocessor
* e.g. void DCT4(...) becomes void raac_DCT4(...)
*/
#define STAT_PREFIX raac
#define STATCC1(x,y,z) STATCC2(x,y,z)
#define STATCC2(x,y,z) x##y##z
#ifdef STAT_PREFIX
#define STATNAME(func) STATCC1(STAT_PREFIX, _, func)
#else
#define STATNAME(func) func
#endif
/* these symbols are common to all implementations */
#define AllocateBuffers STATNAME(AllocateBuffers)
#define FreeBuffers STATNAME(FreeBuffers)
#define ClearBuffer STATNAME(ClearBuffer)
#define SetRawBlockParams STATNAME(SetRawBlockParams)
#define PrepareRawBlock STATNAME(PrepareRawBlock)
#define FlushCodec STATNAME(FlushCodec)
#define UnpackADTSHeader STATNAME(UnpackADTSHeader)
#define GetADTSChannelMapping STATNAME(GetADTSChannelMapping)
#define UnpackADIFHeader STATNAME(UnpackADIFHeader)
#define DecodeNextElement STATNAME(DecodeNextElement)
#define DecodeNoiselessData STATNAME(DecodeNoiselessData)
#define Dequantize STATNAME(Dequantize)
#define StereoProcess STATNAME(StereoProcess)
#define DeinterleaveShortBlocks STATNAME(DeinterleaveShortBlocks)
#define PNS STATNAME(PNS)
#define TNSFilter STATNAME(TNSFilter)
#define IMDCT STATNAME(IMDCT)
#define InitSBR STATNAME(InitSBR)
#define DecodeSBRBitstream STATNAME(DecodeSBRBitstream)
#define DecodeSBRData STATNAME(DecodeSBRData)
#define FreeSBR STATNAME(FreeSBR)
#define FlushCodecSBR STATNAME(FlushCodecSBR)
/* global ROM tables */
#define sampRateTab STATNAME(sampRateTab)
#define predSFBMax STATNAME(predSFBMax)
#define channelMapTab STATNAME(channelMapTab)
#define elementNumChans STATNAME(elementNumChans)
#define sfBandTotalShort STATNAME(sfBandTotalShort)
#define sfBandTotalLong STATNAME(sfBandTotalLong)
#define sfBandTabShortOffset STATNAME(sfBandTabShortOffset)
#define sfBandTabShort STATNAME(sfBandTabShort)
#define sfBandTabLongOffset STATNAME(sfBandTabLongOffset)
#define sfBandTabLong STATNAME(sfBandTabLong)
#define tnsMaxBandsShortOffset STATNAME(tnsMaxBandsShortOffset)
#define tnsMaxBandsShort STATNAME(tnsMaxBandsShort)
#define tnsMaxOrderShort STATNAME(tnsMaxOrderShort)
#define tnsMaxBandsLongOffset STATNAME(tnsMaxBandsLongOffset)
#define tnsMaxBandsLong STATNAME(tnsMaxBandsLong)
#define tnsMaxOrderLong STATNAME(tnsMaxOrderLong)
/* in your implementation's top-level include file (e.g. real\coder.h) you should
* add new #define sym STATNAME(sym) lines for all the
* additional global functions or variables which your
* implementation uses
*/
#endif /* _STATNAME_H */

View File

@@ -1,246 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: stproc.c,v 1.3 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
*
* stproc.c - mid-side and intensity stereo processing
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
/* pow14[0][i] = -pow(2, i/4.0)
* pow14[1][i] = +pow(2, i/4.0)
*
* i = [0,1,2,3]
* format = Q30
*/
/**************************************************************************************
* Function: StereoProcessGroup
*
* Description: apply mid-side and intensity stereo to group of transform coefficients
*
* Inputs: dequantized transform coefficients for both channels
* pointer to appropriate scalefactor band table
* mid-side mask enabled flag
* buffer with mid-side mask (one bit for each scalefactor band)
* bit offset into mid-side mask buffer
* max coded scalefactor band
* buffer of codebook indices for right channel
* buffer of scalefactors for right channel, range = [0, 256]
*
* Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF)
* updated minimum guard bit count for both channels
*
* Return: none
*
* Notes: assume no guard bits in input
* gains 0 int bits
**************************************************************************************/
static void StereoProcessGroup(int *coefL, int *coefR, const /*short*/ int *sfbTab,
int msMaskPres, unsigned char *msMaskPtr, int msMaskOffset, int maxSFB,
unsigned char *cbRight, short *sfRight, int *gbCurrent)
{
//fb
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
static const int pow14[2][4] PROGMEM = {
{ 0xc0000000, 0xb3e407d7, 0xa57d8666, 0x945d819b },
{ 0x40000000, 0x4c1bf829, 0x5a82799a, 0x6ba27e65 }
};
#pragma GCC diagnostic pop
int sfb, width, cbIdx, sf, cl, cr, scalef, scalei;
int gbMaskL, gbMaskR;
unsigned char msMask;
msMask = (*msMaskPtr++) >> msMaskOffset;
gbMaskL = 0;
gbMaskR = 0;
for (sfb = 0; sfb < maxSFB; sfb++) {
width = sfbTab[sfb+1] - sfbTab[sfb]; /* assume >= 0 (see sfBandTabLong/sfBandTabShort) */
cbIdx = cbRight[sfb];
if (cbIdx == 14 || cbIdx == 15) {
/* intensity stereo */
if (msMaskPres == 1 && (msMask & 0x01))
cbIdx ^= 0x01; /* invert_intensity(): 14 becomes 15, or 15 becomes 14 */
sf = -sfRight[sfb]; /* negative since we use identity 0.5^(x) = 2^(-x) (see spec) */
cbIdx &= 0x01; /* choose - or + scale factor */
scalef = pow14[cbIdx][sf & 0x03];
scalei = (sf >> 2) + 2; /* +2 to compensate for scalef = Q30 */
if (scalei > 0) {
if (scalei > 30)
scalei = 30;
do {
cr = MULSHIFT32(*coefL++, scalef);
CLIP_2N(cr, 31-scalei);
cr <<= scalei;
gbMaskR |= FASTABS(cr);
*coefR++ = cr;
} while (--width);
} else {
scalei = -scalei;
if (scalei > 31)
scalei = 31;
do {
cr = MULSHIFT32(*coefL++, scalef) >> scalei;
gbMaskR |= FASTABS(cr);
*coefR++ = cr;
} while (--width);
}
} else if ( cbIdx != 13 && ((msMaskPres == 1 && (msMask & 0x01)) || msMaskPres == 2) ) {
/* mid-side stereo (assumes no GB in inputs) */
do {
cl = *coefL;
cr = *coefR;
if ( (FASTABS(cl) | FASTABS(cr)) >> 30 ) {
/* avoid overflow (rare) */
cl >>= 1;
sf = cl + (cr >> 1); CLIP_2N(sf, 30); sf <<= 1;
cl = cl - (cr >> 1); CLIP_2N(cl, 30); cl <<= 1;
} else {
/* usual case */
sf = cl + cr;
cl -= cr;
}
*coefL++ = sf;
gbMaskL |= FASTABS(sf);
*coefR++ = cl;
gbMaskR |= FASTABS(cl);
} while (--width);
} else {
/* nothing to do */
coefL += width;
coefR += width;
}
/* get next mask bit (should be branchless on ARM) */
msMask >>= 1;
if (++msMaskOffset == 8) {
msMask = *msMaskPtr++;
msMaskOffset = 0;
}
}
cl = CLZ(gbMaskL) - 1;
if (gbCurrent[0] > cl)
gbCurrent[0] = cl;
cr = CLZ(gbMaskR) - 1;
if (gbCurrent[1] > cr)
gbCurrent[1] = cr;
return;
}
/**************************************************************************************
* Function: StereoProcess
*
* Description: apply mid-side and intensity stereo, if enabled
*
* Inputs: valid AACDecInfo struct (including dequantized transform coefficients)
*
* Outputs: updated transform coefficients in Q(FBITS_OUT_DQ_OFF)
* updated minimum guard bit count for both channels
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
int StereoProcess(AACDecInfo *aacDecInfo)
{
PSInfoBase *psi;
ICSInfo *icsInfo;
int gp, win, nSamps, msMaskOffset;
int *coefL, *coefR;
unsigned char *msMaskPtr;
const /*short*/ int *sfbTab;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
/* mid-side and intensity stereo require common_window == 1 (see MPEG4 spec, Correction 2, 2004) */
if (psi->commonWin != 1 || aacDecInfo->currBlockID != AAC_ID_CPE)
return 0;
/* nothing to do */
if (!psi->msMaskPresent && !psi->intensityUsed[1])
return 0;
icsInfo = &(psi->icsInfo[0]);
if (icsInfo->winSequence == 2) {
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
nSamps = NSAMPS_SHORT;
} else {
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
nSamps = NSAMPS_LONG;
}
coefL = psi->coef[0];
coefR = psi->coef[1];
/* do fused mid-side/intensity processing for each block (one long or eight short) */
msMaskOffset = 0;
msMaskPtr = psi->msMaskBits;
for (gp = 0; gp < icsInfo->numWinGroup; gp++) {
for (win = 0; win < icsInfo->winGroupLen[gp]; win++) {
StereoProcessGroup(coefL, coefR, sfbTab, psi->msMaskPresent,
msMaskPtr, msMaskOffset, icsInfo->maxSFB, psi->sfbCodeBook[1] + gp*icsInfo->maxSFB,
psi->scaleFactors[1] + gp*icsInfo->maxSFB, psi->gbCurrent);
coefL += nSamps;
coefR += nSamps;
}
/* we use one bit per sfb, so there are maxSFB bits for each window group */
msMaskPtr += (msMaskOffset + icsInfo->maxSFB) >> 3;
msMaskOffset = (msMaskOffset + icsInfo->maxSFB) & 0x07;
}
ASSERT(coefL == psi->coef[0] + 1024);
ASSERT(coefR == psi->coef[1] + 1024);
return 0;
}

View File

@@ -1,300 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: tns.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
*
* tns.c - apply TNS to spectrum
**************************************************************************************/
#include "coder.h"
#include "assembly.h"
#define FBITS_LPC_COEFS 20
//fb
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
/* inverse quantization tables for TNS filter coefficients, format = Q31
* see bottom of file for table generation
* negative (vs. spec) since we use MADD for filter kernel
*/
static const int invQuant3[16] PROGMEM = {
0x00000000, 0xc8767f65, 0x9becf22c, 0x83358feb, 0x83358feb, 0x9becf22c, 0xc8767f65, 0x00000000,
0x2bc750e9, 0x5246dd49, 0x6ed9eba1, 0x7e0e2e32, 0x7e0e2e32, 0x6ed9eba1, 0x5246dd49, 0x2bc750e9,
};
static const int invQuant4[16] PROGMEM = {
0x00000000, 0xe5632654, 0xcbf00dbe, 0xb4c373ee, 0xa0e0a15f, 0x9126145f, 0x8643c7b3, 0x80b381ac,
0x7f7437ad, 0x7b1d1a49, 0x7294b5f2, 0x66256db2, 0x563ba8aa, 0x4362210e, 0x2e3d2abb, 0x17851aad,
};
#pragma GCC diagnostic pop
/**************************************************************************************
* Function: DecodeLPCCoefs
*
* Description: decode LPC coefficients for TNS
*
* Inputs: order of TNS filter
* resolution of coefficients (3 or 4 bits)
* coefficients unpacked from bitstream
* scratch buffer (b) of size >= order
*
* Outputs: LPC coefficients in Q(FBITS_LPC_COEFS), in 'a'
*
* Return: none
*
* Notes: assumes no guard bits in input transform coefficients
* a[i] = Q(FBITS_LPC_COEFS), don't store a0 = 1.0
* (so a[0] = first delay tap, etc.)
* max abs(a[i]) < log2(order), so for max order = 20 a[i] < 4.4
* (up to 3 bits of gain) so a[i] has at least 31 - FBITS_LPC_COEFS - 3
* guard bits
* to ensure no intermediate overflow in all-pole filter, set
* FBITS_LPC_COEFS such that number of guard bits >= log2(max order)
**************************************************************************************/
static void DecodeLPCCoefs(int order, int res, signed char *filtCoef, int *a, int *b)
{
int i, m, t;
const int *invQuantTab;
if (res == 3) invQuantTab = invQuant3;
else if (res == 4) invQuantTab = invQuant4;
else return;
for (m = 0; m < order; m++) {
t = invQuantTab[filtCoef[m] & 0x0f]; /* t = Q31 */
for (i = 0; i < m; i++)
b[i] = a[i] - (MULSHIFT32(t, a[m-i-1]) << 1);
for (i = 0; i < m; i++)
a[i] = b[i];
a[m] = t >> (31 - FBITS_LPC_COEFS);
}
}
/**************************************************************************************
* Function: FilterRegion
*
* Description: apply LPC filter to one region of coefficients
*
* Inputs: number of transform coefficients in this region
* direction flag (forward = 1, backward = -1)
* order of filter
* 'size' transform coefficients
* 'order' LPC coefficients in Q(FBITS_LPC_COEFS)
* scratch buffer for history (must be >= order samples long)
*
* Outputs: filtered transform coefficients
*
* Return: guard bit mask (OR of abs value of all filtered transform coefs)
*
* Notes: assumes no guard bits in input transform coefficients
* gains 0 int bits
* history buffer does not need to be preserved between regions
**************************************************************************************/
static int FilterRegion(int size, int dir, int order, int *audioCoef, int *a, int *hist)
{
int i, j, y, hi32, inc, gbMask;
U64 sum64;
/* init history to 0 every time */
for (i = 0; i < order; i++)
hist[i] = 0;
sum64.w64 = 0; /* avoid warning */
gbMask = 0;
inc = (dir ? -1 : 1);
do {
/* sum64 = a0*y[n] = 1.0*y[n] */
y = *audioCoef;
sum64.r.hi32 = y >> (32 - FBITS_LPC_COEFS);
sum64.r.lo32 = y << FBITS_LPC_COEFS;
/* sum64 += (a1*y[n-1] + a2*y[n-2] + ... + a[order-1]*y[n-(order-1)]) */
for (j = order - 1; j > 0; j--) {
sum64.w64 = MADD64(sum64.w64, hist[j], a[j]);
hist[j] = hist[j-1];
}
sum64.w64 = MADD64(sum64.w64, hist[0], a[0]);
y = (sum64.r.hi32 << (32 - FBITS_LPC_COEFS)) | (sum64.r.lo32 >> FBITS_LPC_COEFS);
/* clip output (rare) */
hi32 = sum64.r.hi32;
if ((hi32 >> 31) != (hi32 >> (FBITS_LPC_COEFS-1)))
y = (hi32 >> 31) ^ 0x7fffffff;
hist[0] = y;
*audioCoef = y;
audioCoef += inc;
gbMask |= FASTABS(y);
} while (--size);
return gbMask;
}
/**************************************************************************************
* Function: TNSFilter
*
* Description: apply temporal noise shaping, if enabled
*
* Inputs: valid AACDecInfo struct
* index of current channel
*
* Outputs: updated transform coefficients
* updated minimum guard bit count for this channel
*
* Return: 0 if successful, -1 if error
**************************************************************************************/
int TNSFilter(AACDecInfo *aacDecInfo, int ch)
{
int win, winLen, nWindows, nSFB, filt, bottom, top, order, maxOrder, dir;
int start, end, size, tnsMaxBand, numFilt, gbMask;
int *audioCoef;
unsigned char *filtLength, *filtOrder, *filtRes, *filtDir;
signed char *filtCoef;
const unsigned /*char*/ int *tnsMaxBandTab;
const /*short*/ int *sfbTab;
ICSInfo *icsInfo;
TNSInfo *ti;
PSInfoBase *psi;
/* validate pointers */
if (!aacDecInfo || !aacDecInfo->psInfoBase)
return -1;
psi = (PSInfoBase *)(aacDecInfo->psInfoBase);
icsInfo = (ch == 1 && psi->commonWin == 1) ? &(psi->icsInfo[0]) : &(psi->icsInfo[ch]);
ti = &psi->tnsInfo[ch];
if (!ti->tnsDataPresent)
return 0;
if (icsInfo->winSequence == 2) {
nWindows = NWINDOWS_SHORT;
winLen = NSAMPS_SHORT;
nSFB = sfBandTotalShort[psi->sampRateIdx];
maxOrder = tnsMaxOrderShort[aacDecInfo->profile];
sfbTab = sfBandTabShort + sfBandTabShortOffset[psi->sampRateIdx];
tnsMaxBandTab = tnsMaxBandsShort + tnsMaxBandsShortOffset[aacDecInfo->profile];
tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
} else {
nWindows = NWINDOWS_LONG;
winLen = NSAMPS_LONG;
nSFB = sfBandTotalLong[psi->sampRateIdx];
maxOrder = tnsMaxOrderLong[aacDecInfo->profile];
sfbTab = sfBandTabLong + sfBandTabLongOffset[psi->sampRateIdx];
tnsMaxBandTab = tnsMaxBandsLong + tnsMaxBandsLongOffset[aacDecInfo->profile];
tnsMaxBand = tnsMaxBandTab[psi->sampRateIdx];
}
if (tnsMaxBand > icsInfo->maxSFB)
tnsMaxBand = icsInfo->maxSFB;
filtRes = ti->coefRes;
filtLength = ti->length;
filtOrder = ti->order;
filtDir = ti->dir;
filtCoef = ti->coef;
gbMask = 0;
audioCoef = psi->coef[ch];
for (win = 0; win < nWindows; win++) {
bottom = nSFB;
numFilt = ti->numFilt[win];
for (filt = 0; filt < numFilt; filt++) {
top = bottom;
bottom = top - *filtLength++;
bottom = MAX(bottom, 0);
order = *filtOrder++;
order = MIN(order, maxOrder);
if (order) {
start = sfbTab[MIN(bottom, tnsMaxBand)];
end = sfbTab[MIN(top, tnsMaxBand)];
size = end - start;
if (size > 0) {
dir = *filtDir++;
if (dir)
start = end - 1;
DecodeLPCCoefs(order, filtRes[win], filtCoef, psi->tnsLPCBuf, psi->tnsWorkBuf);
gbMask |= FilterRegion(size, dir, order, audioCoef + start, psi->tnsLPCBuf, psi->tnsWorkBuf);
}
filtCoef += order;
}
}
audioCoef += winLen;
}
/* update guard bit count if necessary */
size = CLZ(gbMask) - 1;
if (psi->gbCurrent[ch] > size)
psi->gbCurrent[ch] = size;
return 0;
}
/* Code to generate invQuantXXX[] tables
* {
* int res, i, t;
* double powScale, iqfac, iqfac_m, d;
*
* powScale = pow(2.0, 31) * -1.0; / ** make coefficients negative for using MADD in kernel ** /
* for (res = 3; res <= 4; res++) {
* iqfac = ( ((1 << (res-1)) - 0.5) * (2.0 / M_PI) );
* iqfac_m = ( ((1 << (res-1)) + 0.5) * (2.0 / M_PI) );
* printf("static const int invQuant%d[16] = {\n", res);
* for (i = 0; i < 16; i++) {
* / ** extend bottom 4 bits into signed, 2's complement number ** /
* t = (i << 28) >> 28;
*
* if (t >= 0) d = sin(t / iqfac);
* else d = sin(t / iqfac_m);
*
* d *= powScale;
* printf("0x%08x, ", (int)(d > 0 ? d + 0.5 : d - 0.5));
* if ((i & 0x07) == 0x07)
* printf("\n");
* }
* printf("};\n\n");
* }
* }
*/

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More