mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-02-01 15:21:09 +03:00
big merge
This commit is contained in:
213
components/spotify/cspot/bell/libhelix-aac/aaccommon.h
Normal file
213
components/spotify/cspot/bell/libhelix-aac/aaccommon.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* ***** 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 */
|
||||
476
components/spotify/cspot/bell/libhelix-aac/aacdec.c
Normal file
476
components/spotify/cspot/bell/libhelix-aac/aacdec.c
Normal file
@@ -0,0 +1,476 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
|
||||
175
components/spotify/cspot/bell/libhelix-aac/aacdec.h
Normal file
175
components/spotify/cspot/bell/libhelix-aac/aacdec.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/* ***** 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 */
|
||||
157
components/spotify/cspot/bell/libhelix-aac/aactabs.c
Normal file
157
components/spotify/cspot/bell/libhelix-aac/aactabs.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/* ***** 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};
|
||||
638
components/spotify/cspot/bell/libhelix-aac/assembly.h
Normal file
638
components/spotify/cspot/bell/libhelix-aac/assembly.h
Normal file
@@ -0,0 +1,638 @@
|
||||
/* ***** 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(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 */
|
||||
261
components/spotify/cspot/bell/libhelix-aac/bitstream.c
Normal file
261
components/spotify/cspot/bell/libhelix-aac/bitstream.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
74
components/spotify/cspot/bell/libhelix-aac/bitstream.h
Normal file
74
components/spotify/cspot/bell/libhelix-aac/bitstream.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ***** 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 */
|
||||
165
components/spotify/cspot/bell/libhelix-aac/buffers.c
Normal file
165
components/spotify/cspot/bell/libhelix-aac/buffers.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
373
components/spotify/cspot/bell/libhelix-aac/coder.h
Normal file
373
components/spotify/cspot/bell/libhelix-aac/coder.h
Normal file
@@ -0,0 +1,373 @@
|
||||
/* ***** 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 */
|
||||
|
||||
337
components/spotify/cspot/bell/libhelix-aac/dct4.c
Normal file
337
components/spotify/cspot/bell/libhelix-aac/dct4.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
425
components/spotify/cspot/bell/libhelix-aac/decelmnt.c
Normal file
425
components/spotify/cspot/bell/libhelix-aac/decelmnt.c
Normal file
@@ -0,0 +1,425 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
|
||||
373
components/spotify/cspot/bell/libhelix-aac/dequant.c
Normal file
373
components/spotify/cspot/bell/libhelix-aac/dequant.c
Normal file
@@ -0,0 +1,373 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
393
components/spotify/cspot/bell/libhelix-aac/fft.c
Normal file
393
components/spotify/cspot/bell/libhelix-aac/fft.c
Normal file
@@ -0,0 +1,393 @@
|
||||
/* ***** 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 */
|
||||
}
|
||||
}
|
||||
496
components/spotify/cspot/bell/libhelix-aac/filefmt.c
Normal file
496
components/spotify/cspot/bell/libhelix-aac/filefmt.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
415
components/spotify/cspot/bell/libhelix-aac/huffman.c
Normal file
415
components/spotify/cspot/bell/libhelix-aac/huffman.c
Normal file
@@ -0,0 +1,415 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
177
components/spotify/cspot/bell/libhelix-aac/hufftabs.c
Normal file
177
components/spotify/cspot/bell/libhelix-aac/hufftabs.c
Normal file
@@ -0,0 +1,177 @@
|
||||
/* ***** 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,
|
||||
};
|
||||
|
||||
589
components/spotify/cspot/bell/libhelix-aac/imdct.c
Normal file
589
components/spotify/cspot/bell/libhelix-aac/imdct.c
Normal file
@@ -0,0 +1,589 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
484
components/spotify/cspot/bell/libhelix-aac/noiseless.c
Normal file
484
components/spotify/cspot/bell/libhelix-aac/noiseless.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
357
components/spotify/cspot/bell/libhelix-aac/pns.c
Normal file
357
components/spotify/cspot/bell/libhelix-aac/pns.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
127
components/spotify/cspot/bell/libhelix-aac/readme.txt
Normal file
127
components/spotify/cspot/bell/libhelix-aac/readme.txt
Normal file
@@ -0,0 +1,127 @@
|
||||
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
|
||||
431
components/spotify/cspot/bell/libhelix-aac/sbr.c
Normal file
431
components/spotify/cspot/bell/libhelix-aac/sbr.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
383
components/spotify/cspot/bell/libhelix-aac/sbr.h
Normal file
383
components/spotify/cspot/bell/libhelix-aac/sbr.h
Normal file
@@ -0,0 +1,383 @@
|
||||
/* ***** 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 */
|
||||
368
components/spotify/cspot/bell/libhelix-aac/sbrfft.c
Normal file
368
components/spotify/cspot/bell/libhelix-aac/sbrfft.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/* ***** 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) */
|
||||
}
|
||||
641
components/spotify/cspot/bell/libhelix-aac/sbrfreq.c
Normal file
641
components/spotify/cspot/bell/libhelix-aac/sbrfreq.c
Normal file
@@ -0,0 +1,641 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
853
components/spotify/cspot/bell/libhelix-aac/sbrhfadj.c
Normal file
853
components/spotify/cspot/bell/libhelix-aac/sbrhfadj.c
Normal file
@@ -0,0 +1,853 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
616
components/spotify/cspot/bell/libhelix-aac/sbrhfgen.c
Normal file
616
components/spotify/cspot/bell/libhelix-aac/sbrhfgen.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/* ***** 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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
476
components/spotify/cspot/bell/libhelix-aac/sbrhuff.c
Normal file
476
components/spotify/cspot/bell/libhelix-aac/sbrhuff.c
Normal file
@@ -0,0 +1,476 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
447
components/spotify/cspot/bell/libhelix-aac/sbrimdct.c
Normal file
447
components/spotify/cspot/bell/libhelix-aac/sbrimdct.c
Normal file
@@ -0,0 +1,447 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
195
components/spotify/cspot/bell/libhelix-aac/sbrmath.c
Normal file
195
components/spotify/cspot/bell/libhelix-aac/sbrmath.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
527
components/spotify/cspot/bell/libhelix-aac/sbrqmf.c
Normal file
527
components/spotify/cspot/bell/libhelix-aac/sbrqmf.c
Normal file
@@ -0,0 +1,527 @@
|
||||
/* ***** 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 (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && 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 (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && 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);
|
||||
}
|
||||
575
components/spotify/cspot/bell/libhelix-aac/sbrside.c
Normal file
575
components/spotify/cspot/bell/libhelix-aac/sbrside.c
Normal file
@@ -0,0 +1,575 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
400
components/spotify/cspot/bell/libhelix-aac/sbrtabs.c
Normal file
400
components/spotify/cspot/bell/libhelix-aac/sbrtabs.c
Normal file
@@ -0,0 +1,400 @@
|
||||
/* ***** 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,
|
||||
};
|
||||
115
components/spotify/cspot/bell/libhelix-aac/statname.h
Normal file
115
components/spotify/cspot/bell/libhelix-aac/statname.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* ***** 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 */
|
||||
246
components/spotify/cspot/bell/libhelix-aac/stproc.c
Normal file
246
components/spotify/cspot/bell/libhelix-aac/stproc.c
Normal file
@@ -0,0 +1,246 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
300
components/spotify/cspot/bell/libhelix-aac/tns.c
Normal file
300
components/spotify/cspot/bell/libhelix-aac/tns.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/* ***** 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");
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
1004
components/spotify/cspot/bell/libhelix-aac/trigtabs.c
Normal file
1004
components/spotify/cspot/bell/libhelix-aac/trigtabs.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user