summaryrefslogtreecommitdiffstats
path: root/libAACdec
diff options
context:
space:
mode:
authorDave Burke <daveburke@google.com>2012-04-17 09:51:45 -0700
committerDave Burke <daveburke@google.com>2012-04-17 23:04:43 -0700
commit9bf37cc9712506b2483650c82d3c41152337ef7e (patch)
tree77db44e2bae06e3d144b255628be2b7a55c581d3 /libAACdec
parenta37315fe10ee143d6d0b28c19d41a476a23e63ea (diff)
downloadfdk-aac-dabplus-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.gz
fdk-aac-dabplus-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.bz2
fdk-aac-dabplus-9bf37cc9712506b2483650c82d3c41152337ef7e.zip
Fraunhofer AAC codec.
License boilerplate update to follow. Change-Id: I2810460c11a58b6d148d84673cc031f3685e79b5
Diffstat (limited to 'libAACdec')
-rw-r--r--libAACdec/Android.mk1
-rw-r--r--libAACdec/include/aacdecoder_lib.h626
-rw-r--r--libAACdec/src/Android.mk39
-rw-r--r--libAACdec/src/aac_ram.cpp81
-rw-r--r--libAACdec/src/aac_ram.h58
-rw-r--r--libAACdec/src/aac_rom.cpp1780
-rw-r--r--libAACdec/src/aac_rom.h125
-rw-r--r--libAACdec/src/aacdec_drc.cpp997
-rw-r--r--libAACdec/src/aacdec_drc.h105
-rw-r--r--libAACdec/src/aacdec_drc_types.h104
-rw-r--r--libAACdec/src/aacdec_hcr.cpp1529
-rw-r--r--libAACdec/src/aacdec_hcr.h64
-rw-r--r--libAACdec/src/aacdec_hcr_bit.cpp103
-rw-r--r--libAACdec/src/aacdec_hcr_bit.h44
-rw-r--r--libAACdec/src/aacdec_hcr_types.h304
-rw-r--r--libAACdec/src/aacdec_hcrs.cpp1344
-rw-r--r--libAACdec/src/aacdec_hcrs.h91
-rw-r--r--libAACdec/src/aacdec_pns.cpp320
-rw-r--r--libAACdec/src/aacdec_pns.h58
-rw-r--r--libAACdec/src/aacdec_tns.cpp350
-rw-r--r--libAACdec/src/aacdec_tns.h64
-rw-r--r--libAACdec/src/aacdecoder.cpp1667
-rw-r--r--libAACdec/src/aacdecoder.h250
-rw-r--r--libAACdec/src/aacdecoder_lib.cpp925
-rw-r--r--libAACdec/src/arm/block_arm.cpp77
-rw-r--r--libAACdec/src/block.cpp703
-rw-r--r--libAACdec/src/block.h260
-rw-r--r--libAACdec/src/channel.cpp389
-rw-r--r--libAACdec/src/channel.h86
-rw-r--r--libAACdec/src/channelinfo.cpp214
-rw-r--r--libAACdec/src/channelinfo.h388
-rw-r--r--libAACdec/src/conceal.cpp1763
-rw-r--r--libAACdec/src/conceal.h86
-rw-r--r--libAACdec/src/conceal_types.h116
-rw-r--r--libAACdec/src/debug.h35
-rw-r--r--libAACdec/src/ldfiltbank.cpp148
-rw-r--r--libAACdec/src/ldfiltbank.h48
-rw-r--r--libAACdec/src/overlapadd.h43
-rw-r--r--libAACdec/src/pulsedata.cpp96
-rw-r--r--libAACdec/src/pulsedata.h83
-rw-r--r--libAACdec/src/rvlc.cpp1157
-rw-r--r--libAACdec/src/rvlc.h76
-rw-r--r--libAACdec/src/rvlc_info.h118
-rw-r--r--libAACdec/src/rvlcbit.cpp73
-rw-r--r--libAACdec/src/rvlcbit.h41
-rw-r--r--libAACdec/src/rvlcconceal.cpp639
-rw-r--r--libAACdec/src/rvlcconceal.h54
-rw-r--r--libAACdec/src/stereo.cpp235
-rw-r--r--libAACdec/src/stereo.h72
49 files changed, 18029 insertions, 0 deletions
diff --git a/libAACdec/Android.mk b/libAACdec/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/libAACdec/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h
new file mode 100644
index 0000000..881601b
--- /dev/null
+++ b/libAACdec/include/aacdecoder_lib.h
@@ -0,0 +1,626 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS 1999-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Manuel Jander
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+/**
+ * \file aacdecoder_lib.h
+ * \brief FDK AAC decoder library interface header file.
+ *
+
+\page INTRO Introduction
+
+\section SCOPE Scope
+
+This document describes the high-level interface and usage of the ISO/MPEG-2/4 AAC Decoder
+library developed by the Fraunhofer Institute for Integrated Circuits (IIS).
+Depending on the library configuration, it implements decoding of AAC-LC (Low-Complexity),
+HE-AAC (High-Efficiency AAC, v1 and v2), AAC-LD (Low-Delay) and AAC-ELD (Enhanced Low-Delay).
+
+All references to SBR (Spectral Band Replication) are only applicable to HE-AAC and AAC-ELD
+versions of the library. All references to PS (Parametric Stereo) are only applicable to
+HE-AAC v2 versions of the library.
+
+\section DecoderBasics Decoder Basics
+
+This document can only give a rough overview about the ISO/MPEG-2 and ISO/MPEG-4 AAC audio
+coding standard. To understand all the terms in this document, you are encouraged to read
+the following documents.
+
+- ISO/IEC 13818-7 (MPEG-2 AAC), which defines the syntax of MPEG-2 AAC audio bitstreams.
+- ISO/IEC 14496-3 (MPEG-4 AAC, subpart 1 and 4), which defines the syntax of MPEG-4 AAC audio bitstreams.
+- Lutzky, Schuller, Gayer, Kr&auml;mer, Wabnik, "A guideline to audio codec delay", 116th AES Convention, May 8, 2004
+
+MPEG Advanced Audio Coding is based on a time-to-frequency mapping of the signal. The signal
+is partitioned into overlapping portions and transformed into frequency domain. The spectral
+components are then quantized and coded.\n
+An MPEG2 or MPEG4 AAC audio bitstream is composed of frames. Contrary to MPEG-1/2 Layer-3 (mp3),
+the length of individual frames is not restricted to a fixed number of bytes, but can take on
+any length between 1 and 768 bytes.
+
+
+\page LIBUSE Library Usage
+
+\section InterfaceDescritpion API Description
+
+All API header files are located in the folder /include of the release package. They are described in
+detail in this document. All header files are provided for usage in C/C++ programs. The AAC decoder library
+API functions are located at aacdecoder_lib.h.
+
+In binary releases the decoder core resides in statically linkable libraries called for example libAACdec.a,
+(Linux) or FDK_aacDec_lib (Microsoft Visual C++).
+
+\section Calling_Sequence Calling Sequence
+
+For decoding of ISO/MPEG-2/4 AAC or HE-AAC v2 bitstreams the following sequence is mandatory. Input read
+and output write functions as well as the corresponding open and close functions are left out, since they
+may be implemented differently according to the user's specific requirements. The example implementation in
+main.cpp uses file-based input/output, and in such case call mpegFileRead_Open() to open an input file and
+to allocate memory for the required structures, and the corresponding mpegFileRead_Close() to close opened
+files and to de-allocate associated structures. mpegFileRead_Open() tries to detect the bitstream format and
+in case of MPEG-4 file format or Raw Packets file format (a Fraunhofer IIS proprietary format) reads the Audio
+Specific Config data (ASC). An unsuccessful attempt to recognize the bitstream format requires the user to
+provide this information manually (see \ref CommandLineUsage). For any other bitstream formats that are
+usually applicable in streaming applications, the decoder itself will try to synchronize and parse the given
+bitstream fragment using the FDK transport library. Hence, for streaming applications (without file access)
+this step is not necessary.
+
+-# Call aacDecoder_Open() to open and retrieve a handle to a new AAC decoder instance.
+\dontinclude main.cpp
+\skipline aacDecoder_Open
+-# If out-of-band config data (Audio Specific Config (ASC) or Stream Mux Config (SMC)) is available, call
+aacDecoder_ConfigRaw() to pass it to the decoder and before the decoding process starts. If this data is
+not available in advance, the decoder will get it from the bitstream and configure itself while decoding
+with aacDecoder_DecodeFrame().
+-# Begin decoding loop.
+\skipline do {
+-# Read data from bitstream file or stream into a client-supplied input buffer ("inBuffer" in main.cpp).
+If it is very small like just 4, aacDecoder_DecodeFrame() will
+repeatedly return ::AAC_DEC_NOT_ENOUGH_BITS until enough bits were fed by aacDecoder_Fill(). Only read data
+when this buffer has completely been processed and is then empty. For file-based input execute
+mpegFileRead_Read() or any other implementation with similar functionality.
+-# Call aacDecoder_Fill() to fill the decoder's internal bitstream input buffer with the client-supplied
+external bitstream input buffer.
+\skipline aacDecoder_Fill
+-# Call aacDecoder_DecodeFrame() which writes decoded PCM audio data to a client-supplied buffer. It is the
+client's responsibility to allocate a buffer which is large enough to hold this output data.
+\skipline aacDecoder_DecodeFrame
+If the bitstream's configuration (number of channels, sample rate, frame size) is not known in advance, you may
+call aacDecoder_GetStreamInfo() to retrieve a structure containing this information and then initialize an audio
+output device. In the example main.cpp, if the number of channels or the sample rate has changed since program
+start or since the previously decoded frame, the audio output device will be re-initialized. If WAVE file output
+is chosen, a new WAVE file for each new configuration will be created.
+\skipline aacDecoder_GetStreamInfo
+-# Repeat steps 5 to 7 until no data to decode is available anymore, or if an error occured.
+\skipline } while
+-# Call aacDecoder_Close() to de-allocate all AAC decoder and transport layer structures.
+\skipline aacDecoder_Close
+
+\section BufferSystem Buffer System
+
+There are three main buffers in an AAC decoder application. One external input buffer to hold bitstream
+data from file I/O or elsewhere, one decoder-internal input buffer, and one to hold the decoded output
+PCM sample data, whereas this output buffer may overlap with the external input buffer.
+
+The external input buffer is set in the example framework main.cpp and its size is defined by ::IN_BUF_SIZE.
+You may freely choose different sizes here. To feed the data to the decoder-internal input buffer, use the
+function aacDecoder_Fill(). This function returns important information about how many bytes in the
+external input buffer have not yet been copied into the internal input buffer (variable bytesValid).
+Once the external buffer has been fully copied, it can be re-filled again.
+In case you want to re-fill it when there are still unprocessed bytes (bytesValid is unequal 0), you
+would have to additionally perform a memcpy(), so that just means unnecessary computational overhead
+and therefore we recommend to re-fill the buffer only when bytesValid is 0.
+
+\image latex dec_buffer.png "Lifecycle of the external input buffer" width=9cm
+
+The size of the decoder-internal input buffer is set in tpdec_lib.h (see define ::TRANSPORTDEC_INBUF_SIZE).
+You may choose a smaller size under the following considerations:
+
+- each input channel requires 768 bytes
+- the whole buffer must be of size 2^n
+
+So for example a stereo decoder:
+
+\f[
+TRANSPORTDEC\_INBUF\_SIZE = 2 * 768 = 1536 => 2048
+\f]
+
+tpdec_lib.h and TRANSPORTDEC_INBUF_SIZE are not part of the decoder's library interface. Therefore
+only source-code clients may change this setting. If you received a library release, please ask us and
+we can change this in order to meet your memory requirements.
+
+\page OutputFormat Decoder audio output
+
+\section OutputFormatObtaining Obtaining channel mapping information
+
+The decoded audio output format is indicated by a set of variables of the CStreamInfo structure.
+While the members sampleRate, frameSize and numChannels might be quite self explaining,
+pChannelType and pChannelIndices might require some more detailed explanation.
+
+These two arrays indicate what is each output channel supposed to be. Both array have
+CStreamInfo::numChannels cells. Each cell of pChannelType indicates the channel type, described in
+the enum ::AUDIO_CHANNEL_TYPE defined in FDK_audio.h. The cells of pChannelIndices indicate the sub index
+among the channels starting with 0 among all channels of the same audio channel type.
+
+The indexing scheme is the same as for MPEG-2/4. Thus indices are counted upwards starting from the front
+direction (thus a center channel if any, will always be index 0). Then the indices count up, starting always
+with the left side, pairwise from front toward back. For detailed explanation, please refer to
+ISO/IEC 13818-7:2005(E), chapter 8.5.3.2.
+
+In case a Program Config is included in the audio configuration, the channel mapping described within
+it will be adopted.
+
+In case of MPEG-D Surround the channel mapping will follow the same criteria described in ISO/IEC 13818-7:2005(E),
+but adding corresponding top channels to the channel types front, side and back, in order to avoid any
+loss of information.
+
+\section OutputFormatChange Changing the audio output format
+
+The channel interleaving scheme and the actual channel order can be changed at runtime through the
+parameters ::AAC_PCM_OUTPUT_INTERLEAVED and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING. See the description of those
+parameters and the decoder library function aacDecoder_SetParam() for more detail.
+
+\section OutputFormatExample Channel mapping examples
+
+The following examples illustrate the location of individual audio samples in the audio buffer that
+is passed to aacDecoder_DecodeFrame() and the expected data in the CStreamInfo structure which can be obtained
+by calling aacDecoder_GetStreamInfo().
+
+\subsection ExamplesStereo Stereo
+
+In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 0 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1,
+a AAC-LC bit stream which has channelConfiguration = 2 in its audio specific config would lead
+to the following values in CStreamInfo:
+
+CStreamInfo::numChannels = 2
+
+CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT }
+
+CStreamInfo::pChannelIndices = { 0, 1 }
+
+Since ::AAC_PCM_OUTPUT_INTERLEAVED is set to 0, the audio channels will be located as contiguous blocks
+in the output buffer as follows:
+
+\verbatim
+ <left sample 0> <left sample 1> <left sample 2> ... <left sample N>
+ <right sample 0> <right sample 1> <right sample 2> ... <right sample N>
+\endverbatim
+
+Where N equals to CStreamInfo::frameSize .
+
+\subsection ExamplesSurround Surround 5.1
+
+In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 1 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1,
+a AAC-LC bit stream which has channelConfiguration = 6 in its audio specific config, would lead
+to the following values in CStreamInfo:
+
+CStreamInfo::numChannels = 6
+
+CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT, ::ACT_FRONT, ::ACT_LFE, ::ACT_BACK, ::ACT_BACK }
+
+CStreamInfo::pChannelIndices = { 1, 2, 0, 0, 0, 1 }
+
+Since ::AAC_PCM_OUTPUT_CHANNEL_MAPPING is 1, WAV file channel ordering will be used. For a 5.1 channel
+scheme, thus the channels would be: front left, front right, center, LFE, surround left, surround right.
+Thus the third channel is the center channel, receiving the index 0. The other front channels are
+front left, front right being placed as first and second channels with indices 1 and 2 correspondingly.
+There is only one LFE, placed as the fourth channel and index 0. Finally both surround
+channels get the type definition ACT_BACK, and the indices 0 and 1.
+
+Since ::AAC_PCM_OUTPUT_INTERLEAVED is set to 1, the audio channels will be placed in the output buffer
+as follows:
+
+\verbatim
+<front left sample 0> <front right sample 0>
+<center sample 0> <LFE sample 0>
+<surround left sample 0> <surround right sample 0>
+
+<front left sample 1> <front right sample 1>
+<center sample 1> <LFE sample 1>
+<surround left sample 1> <surround right sample 1>
+
+...
+
+<front left sample N> <front right sample N>
+<center sample N> <LFE sample N>
+<surround left sample N> <surround right sample N>
+\endverbatim
+
+Where N equals to CStreamInfo::frameSize .
+
+\subsection ExamplesArib ARIB coding mode 2/1
+
+In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 1 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1,
+in case of a ARIB bit stream using coding mode 2/1 as described in ARIB STD-B32 Part 2 Version 2.1-E1, page 61,
+would lead to the following values in CStreamInfo:
+
+CStreamInfo::numChannels = 3
+
+CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT,:: ACT_BACK }
+
+CStreamInfo::pChannelIndices = { 0, 1, 0 }
+
+The audio channels will be placed as follows in the audio output buffer:
+
+\verbatim
+<front left sample 0> <front right sample 0> <mid surround sample 0>
+
+<front left sample 1> <front right sample 1> <mid surround sample 1>
+
+...
+
+<front left sample N> <front right sample N> <mid surround sample N>
+
+Where N equals to CStreamInfo::frameSize .
+
+\endverbatim
+
+*/
+
+#ifndef AACDECODER_LIB_H
+#define AACDECODER_LIB_H
+
+#include "machine_type.h"
+#include "FDK_audio.h"
+
+#include "genericStds.h"
+
+/**
+ * \brief AAC decoder error codes.
+ */
+typedef enum {
+ AAC_DEC_OK = 0x0000, /*!< No error occured. Output buffer is valid and error free. */
+ AAC_DEC_OUT_OF_MEMORY = 0x0002, /*!< Heap returned NULL pointer. Output buffer is invalid. */
+ AAC_DEC_UNKNOWN = 0x0005, /*!< Error condition is of unknown reason, or from a another module. Output buffer is invalid. */
+
+ /* Synchronization errors. Output buffer is invalid. */
+ aac_dec_sync_error_start = 0x1000,
+ AAC_DEC_TRANSPORT_SYNC_ERROR = 0x1001, /*!< The transport decoder had syncronisation problems. Do not exit decoding. Just feed new
+ bitstream data. */
+ AAC_DEC_NOT_ENOUGH_BITS = 0x1002, /*!< The input buffer ran out of bits. */
+ aac_dec_sync_error_end = 0x1FFF,
+
+ /* Initialization errors. Output buffer is invalid. */
+ aac_dec_init_error_start = 0x2000,
+ AAC_DEC_INVALID_HANDLE = 0x2001, /*!< The handle passed to the function call was invalid (NULL). */
+ AAC_DEC_UNSUPPORTED_AOT = 0x2002, /*!< The AOT found in the configuration is not supported. */
+ AAC_DEC_UNSUPPORTED_FORMAT = 0x2003, /*!< The bitstream format is not supported. */
+ AAC_DEC_UNSUPPORTED_ER_FORMAT = 0x2004, /*!< The error resilience tool format is not supported. */
+ AAC_DEC_UNSUPPORTED_EPCONFIG = 0x2005, /*!< The error protection format is not supported. */
+ AAC_DEC_UNSUPPORTED_MULTILAYER = 0x2006, /*!< More than one layer for AAC scalable is not supported. */
+ AAC_DEC_UNSUPPORTED_CHANNELCONFIG = 0x2007, /*!< The channel configuration (either number or arrangement) is not supported. */
+ AAC_DEC_UNSUPPORTED_SAMPLINGRATE = 0x2008, /*!< The sample rate specified in the configuration is not supported. */
+ AAC_DEC_INVALID_SBR_CONFIG = 0x2009, /*!< The SBR configuration is not supported. */
+ AAC_DEC_SET_PARAM_FAIL = 0x200A, /*!< The parameter could not be set. Either the value was out of range or the parameter does
+ not exist. */
+ AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, since the requiered configuration change cannot be
+ performed. */
+ aac_dec_init_error_end = 0x2FFF,
+
+ /* Decode errors. Output buffer is valid but concealed. */
+ aac_dec_decode_error_start = 0x4000,
+ AAC_DEC_TRANSPORT_ERROR = 0x4001, /*!< The transport decoder encountered an unexpected error. */
+ AAC_DEC_PARSE_ERROR = 0x4002, /*!< Error while parsing the bitstream. Most probably it is corrupted, or the system crashed. */
+ AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD = 0x4003, /*!< Error while parsing the extension payload of the bitstream. The extension payload type
+ found is not supported. */
+ AAC_DEC_DECODE_FRAME_ERROR = 0x4004, /*!< The parsed bitstream value is out of range. Most probably the bitstream is corrupt, or
+ the system crashed. */
+ AAC_DEC_CRC_ERROR = 0x4005, /*!< The embedded CRC did not match. */
+ AAC_DEC_INVALID_CODE_BOOK = 0x4006, /*!< An invalid codebook was signalled. Most probably the bitstream is corrupt, or the system
+ crashed. */
+ AAC_DEC_UNSUPPORTED_PREDICTION = 0x4007, /*!< Predictor found, but not supported in the AAC Low Complexity profile. Most probably the
+ bitstream is corrupt, or has a wrong format. */
+ AAC_DEC_UNSUPPORTED_CCE = 0x4008, /*!< A CCE element was found which is not supported. Most probably the bitstream is corrupt, or
+ has a wrong format. */
+ AAC_DEC_UNSUPPORTED_LFE = 0x4009, /*!< A LFE element was found which is not supported. Most probably the bitstream is corrupt, or
+ has a wrong format. */
+ AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA = 0x400A, /*!< Gain control data found but not supported. Most probably the bitstream is corrupt, or has
+ a wrong format. */
+ AAC_DEC_UNSUPPORTED_SBA = 0x400B, /*!< SBA found, but currently not supported in the BSAC profile. */
+ AAC_DEC_TNS_READ_ERROR = 0x400C, /*!< Error while reading TNS data. Most probably the bitstream is corrupt or the system
+ crashed. */
+ AAC_DEC_RVLC_ERROR = 0x400D, /*!< Error while decoding error resillient data. */
+ aac_dec_decode_error_end = 0x4FFF,
+
+ /* Ancillary data errors. Output buffer is valid. */
+ aac_dec_anc_data_error_start = 0x8000,
+ AAC_DEC_ANC_DATA_ERROR = 0x8001, /*!< Non severe error concerning the ancillary data handling. */
+ AAC_DEC_TOO_SMALL_ANC_BUFFER = 0x8002, /*!< The registered ancillary data buffer is too small to receive the parsed data. */
+ AAC_DEC_TOO_MANY_ANC_ELEMENTS = 0x8003, /*!< More than the allowed number of ancillary data elements should be written to buffer. */
+ aac_dec_anc_data_error_end = 0x8FFF
+
+
+} AAC_DECODER_ERROR;
+
+
+/** Macro to identify initialization errors. */
+#define IS_INIT_ERROR(err) ( (((err)>=aac_dec_init_error_start) && ((err)<=aac_dec_init_error_end)) ? 1 : 0)
+/** Macro to identify decode errors. */
+#define IS_DECODE_ERROR(err) ( (((err)>=aac_dec_decode_error_start) && ((err)<=aac_dec_decode_error_end)) ? 1 : 0)
+/** Macro to identify if the audio output buffer contains valid samples after calling aacDecoder_DecodeFrame(). */
+#define IS_OUTPUT_VALID(err) ( ((err) == AAC_DEC_OK) || IS_DECODE_ERROR(err) )
+
+/**
+ * \brief AAC decoder setting parameters
+ */
+typedef enum
+{
+ AAC_PCM_OUTPUT_INTERLEAVED = 0x0000, /*!< PCM output mode (1: interleaved (default); 0: not interleaved). */
+ AAC_PCM_OUTPUT_CHANNELS = 0x0001, /*!< Number of PCM output channels (if different from encoded audio channels, downmixing or
+ upmixing is applied). \n
+ -1: Disable up-/downmixing. The decoder output contains the same number of channels as the
+ encoded bitstream. \n
+ 1: The decoder performs a mono matrix mix-down if the encoded audio channels are greater
+ than one. Thus it ouputs always exact one channel. \n
+ 2: The decoder performs a stereo matrix mix-down if the encoded audio channels are greater
+ than two. If the encoded audio channels are smaller than two the decoder duplicates the
+ output. Thus it ouputs always exact two channels. \n */
+ AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = 0x0002, /*!< Defines how the decoder processes two channel signals:
+ 0: Leave both signals as they are (default).
+ 1: Create a dual mono output signal from channel 1.
+ 2: Create a dual mono output signal from channel 2.
+ 3: Create a dual mono output signal by mixing both channels (L' = R' = 0.5*Ch1 + 0.5*Ch2). */
+ AAC_PCM_OUTPUT_CHANNEL_MAPPING = 0x0003, /*!< Output buffer channel ordering. 0: MPEG PCE style order, 1: WAV file channel order (default). */
+
+ AAC_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n
+ 0: Spectral muting. \n
+ 1: Noise substitution (see ::CONCEAL_NOISE). \n
+ 2: Energy interpolation (adds additional signal delay of one frame, see ::CONCEAL_INTER). \n */
+
+ AAC_DRC_BOOST_FACTOR = 0x0200, /*!< Dynamic Range Control: Scaling factor for boosting gain values.
+ Defines how the boosting DRC factors (conveyed in the bitstream) will be applied to the
+ decoded signal. The valid values range from 0 (don't apply boost factors) to 127 (fully
+ apply all boosting factors). */
+ AAC_DRC_ATTENUATION_FACTOR = 0x0201, /*!< Dynamic Range Control: Scaling factor for attenuating gain values. Same as
+ AAC_DRC_BOOST_FACTOR but for attenuating DRC factors. */
+ AAC_DRC_REFERENCE_LEVEL = 0x0202, /*!< Dynamic Range Control: Target reference level. Defines the level below full-scale
+ (quantized in steps of 0.25dB) to which the output audio signal will be normalized to by
+ the DRC module. The valid values range from 0 (full-scale) to 127 (31.75 dB below
+ full-scale). The value smaller than 0 switches off normalization. */
+ AAC_DRC_HEAVY_COMPRESSION = 0x0203, /*!< Dynamic Range Control: En-/Disable DVB specific heavy compression (aka RF mode).
+ If set to 1, the decoder will apply the compression values from the DVB specific ancillary
+ data field. At the same time the MPEG-4 Dynamic Range Control tool will be disabled. By
+ default heavy compression is disabled. */
+
+ AAC_QMF_LOWPOWER = 0x0300, /*!< Quadrature Mirror Filter (QMF) Bank processing mode. \n
+ -1: Use internal default. Implies MPEG Surround partially complex accordingly. \n
+ 0: Use complex QMF data mode. \n
+ 1: Use real (low power) QMF data mode. \n */
+
+ AAC_MPEGS_ENABLE = 0x0500, /*!< MPEG Surround: Allow/Disable decoding of MPS content. Available only for decoders with MPEG
+ Surround support. */
+
+ AAC_TPDEC_CLEAR_BUFFER = 0x0603 /*!< Clear internal bit stream buffer of transport layers. The decoder will start decoding
+ at new data passed after this event and any previous data is discarded. */
+
+} AACDEC_PARAM;
+
+/**
+ * \brief This structure gives information about the currently decoded audio data.
+ * All fields are read-only.
+ */
+typedef struct
+{
+ /* These three members are the only really relevant ones for the user. */
+ INT sampleRate; /*!< The samplerate in Hz of the fully decoded PCM audio signal (after SBR processing). */
+ INT frameSize; /*!< The frame size of the decoded PCM audio signal. \n
+ 1024 or 960 for AAC-LC \n
+ 2048 or 1920 for HE-AAC (v2) \n
+ 512 or 480 for AAC-LD and AAC-ELD */
+ INT numChannels; /*!< The number of output audio channels in the decoded and interleaved PCM audio signal. */
+ AUDIO_CHANNEL_TYPE *pChannelType; /*!< Audio channel type of each output audio channel. */
+ UCHAR *pChannelIndices; /*!< Audio channel index for each output audio channel.
+ See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */
+ /* Decoder internal members. */
+ INT aacSampleRate; /*!< sampling rate in Hz without SBR (from configuration info). */
+ INT profile; /*!< MPEG-2 profile (from file header) (-1: not applicable (e. g. MPEG-4)). */
+ AUDIO_OBJECT_TYPE aot; /*!< Audio Object Type (from ASC): is set to the appropriate value for MPEG-2 bitstreams (e. g. 2 for AAC-LC). */
+ INT channelConfig; /*!< Channel configuration (0: PCE defined, 1: mono, 2: stereo, ... */
+ INT bitRate; /*!< Instantaneous bit rate. */
+ INT aacSamplesPerFrame; /*!< Samples per frame for the AAC core (from ASC). \n
+ 1024 or 960 for AAC-LC \n
+ 512 or 480 for AAC-LD and AAC-ELD */
+
+ AUDIO_OBJECT_TYPE extAot; /*!< Extension Audio Object Type (from ASC) */
+ INT extSamplingRate; /*!< Extension sampling rate in Hz (from ASC) */
+
+ UINT flags; /*!< Copy if internal flags. Only to be written by the decoder, and only to be read externally. */
+
+ SCHAR epConfig; /*!< epConfig level (from ASC): only level 0 supported, -1 means no ER (e. g. AOT=2, MPEG-2 AAC, etc.) */
+
+ /* Statistics */
+ INT numLostAccessUnits; /*!< This integer will reflect the estimated amount of lost access units in case aacDecoder_DecodeFrame()
+ returns AAC_DEC_TRANSPORT_SYNC_ERROR. It will be < 0 if the estimation failed. */
+
+ UINT numTotalBytes; /*!< This is the number of total bytes that have passed through the decoder. */
+ UINT numBadBytes; /*!< This is the number of total bytes that were considered with errors from numTotalBytes. */
+ UINT numTotalAccessUnits; /*!< This is the number of total access units that have passed through the decoder. */
+ UINT numBadAccessUnits; /*!< This is the number of total access units that were considered with errors from numTotalBytes. */
+
+} CStreamInfo;
+
+
+typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * \brief Initialize ancillary data buffer.
+ *
+ * \param self AAC decoder handle.
+ * \param buffer Pointer to (external) ancillary data buffer.
+ * \param size Size of the buffer pointed to by buffer.
+ * \return Error code.
+ */
+LINKSPEC_H AAC_DECODER_ERROR
+aacDecoder_AncDataInit ( HANDLE_AACDECODER self,
+ UCHAR *buffer,
+ int size );
+
+/**
+ * \brief Get one ancillary data element.
+ *
+ * \param self AAC decoder handle.
+ * \param index Index of the ancillary data element to get.
+ * \param ptr Pointer to a buffer receiving a pointer to the requested ancillary data element.
+ * \param size Pointer to a buffer receiving the length of the requested ancillary data element.
+ * \return Error code.
+ */
+LINKSPEC_H AAC_DECODER_ERROR
+aacDecoder_AncDataGet ( HANDLE_AACDECODER self,
+ int index,
+ UCHAR **ptr,
+ int *size );
+
+/**
+ * \brief Set one single decoder parameter.
+ *
+ * \param self AAC decoder handle.
+ * \param param Parameter to be set.
+ * \param value Parameter value.
+ * \return Error code.
+ */
+LINKSPEC_H AAC_DECODER_ERROR
+aacDecoder_SetParam ( const HANDLE_AACDECODER self,
+ const AACDEC_PARAM param,
+ const INT value );
+
+
+/**
+ * \brief Get free bytes inside decoder internal buffer
+ * \param self Handle of AAC decoder instance
+ * \param pFreeBytes Pointer to variable receving amount of free bytes inside decoder internal buffer
+ * \return Error code
+ */
+LINKSPEC_H AAC_DECODER_ERROR
+aacDecoder_GetFreeBytes ( const HANDLE_AACDECODER self,
+ UINT *pFreeBytes);
+
+/**
+ * \brief Open an AAC decoder instance
+ * \param transportFmt The transport type to be used
+ * \return AAC decoder handle
+ */
+LINKSPEC_H HANDLE_AACDECODER
+aacDecoder_Open ( TRANSPORT_TYPE transportFmt, UINT nrOfLayers );
+
+/**
+ * \brief Explicitly configure the decoder by passing a raw AudioSpecificConfig (ASC) or a StreamMuxConfig (SMC),
+ * contained in a binary buffer. This is required for MPEG-4 and Raw Packets file format bitstreams
+ * as well as for LATM bitstreams with no in-band SMC. If the transport format is LATM with or without
+ * LOAS, configuration is assumed to be an SMC, for all other file formats an ASC.
+ *
+ * \param self AAC decoder handle.
+ * \param conf Pointer to an unsigned char buffer containing the binary configuration buffer (either ASC or SMC).
+ * \param length Length of the configuration buffer in bytes.
+ * \return Error code.
+ */
+LINKSPEC_H AAC_DECODER_ERROR
+aacDecoder_ConfigRaw ( HANDLE_AACDECODER self,
+ UCHAR *conf[],
+ const UINT length[] );
+
+
+/**
+ * \brief Fill AAC decoder's internal input buffer with bitstream data from the external input buffer.
+ * The function only copies such data as long as the decoder-internal input buffer is not full.
+ * So it grabs whatever it can from pBuffer and returns information (bytesValid) so that at a
+ * subsequent call of %aacDecoder_Fill(), the right position in pBuffer can be determined to
+ * grab the next data.
+ *
+ * \param self AAC decoder handle.
+ * \param pBuffer Pointer to external input buffer.
+ * \param bufferSize Size of external input buffer. This argument is required because decoder-internally
+ * we need the information to calculate the offset to pBuffer, where the next
+ * available data is, which is then fed into the decoder-internal buffer (as much
+ * as possible). Our example framework implementation fills the buffer at pBuffer
+ * again, once it contains no available valid bytes anymore (meaning bytesValid equal 0).
+ * \param bytesValid Number of bitstream bytes in the external bitstream buffer that have not yet been
+ * copied into the decoder's internal bitstream buffer by calling this function.
+ * The value is updated according to the amount of newly copied bytes.
+ * \return Error code.
+ */
+LINKSPEC_H AAC_DECODER_ERROR
+aacDecoder_Fill ( HANDLE_AACDECODER self,
+ UCHAR *pBuffer[],
+ const UINT bufferSize[],
+ UINT *bytesValid );
+
+#define AACDEC_CONCEAL 1 /*!< Flag for aacDecoder_DecodeFrame(): do not consider new input data. Do concealment. */
+#define AACDEC_FLUSH 2 /*!< Flag for aacDecoder_DecodeFrame(): Do not consider new input data. Flush filterbanks (output delayed audio). */
+#define AACDEC_INTR 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data discontinuity. Resync any internals as necessary. */
+#define AACDEC_CLRHIST 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history buffers.
+ Caution: This can cause discontinuities in the output signal. */
+
+/**
+ * \brief Decode one audio frame
+ *
+ * \param self AAC decoder handle.
+ * \param pTimeData Pointer to external output buffer where the decoded PCM samples will be stored into.
+ * \param flags Bit field with flags for the decoder: \n
+ * (flags & AACDEC_CONCEAL) == 1: Do concealment. \n
+ * (flags & AACDEC_FLUSH) == 2: Discard input data. Flush filter banks (output delayed audio). \n
+ * (flags & AACDEC_INTR) == 4: Input data is discontinuous. Resynchronize any internals as necessary.
+ * \return Error code.
+ */
+LINKSPEC_H AAC_DECODER_ERROR
+aacDecoder_DecodeFrame ( HANDLE_AACDECODER self,
+ INT_PCM *pTimeData,
+ const INT timeDataSize,
+ const UINT flags );
+
+/**
+ * \brief De-allocate all resources of an AAC decoder instance.
+ *
+ * \param self AAC decoder handle.
+ * \return void
+ */
+LINKSPEC_H void aacDecoder_Close ( HANDLE_AACDECODER self );
+
+/**
+ * \brief Get CStreamInfo handle from decoder.
+ *
+ * \param self AAC decoder handle.
+ * \return Reference to requested CStreamInfo.
+ */
+LINKSPEC_H CStreamInfo* aacDecoder_GetStreamInfo( HANDLE_AACDECODER self );
+
+/**
+ * \brief Get decoder library info.
+ *
+ * \param info Pointer to an allocated LIB_INFO structure.
+ * \return 0 on success
+ */
+LINKSPEC_H INT aacDecoder_GetLibInfo( LIB_INFO *info );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AACDECODER_LIB_H */
diff --git a/libAACdec/src/Android.mk b/libAACdec/src/Android.mk
new file mode 100644
index 0000000..ae53694
--- /dev/null
+++ b/libAACdec/src/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ aacdec_drc.cpp \
+ aacdec_hcr.cpp \
+ aacdecoder.cpp \
+ aacdec_pns.cpp \
+ aac_ram.cpp \
+ block.cpp \
+ channelinfo.cpp \
+ ldfiltbank.cpp \
+ rvlcbit.cpp \
+ rvlc.cpp \
+ aacdec_hcr_bit.cpp \
+ aacdec_hcrs.cpp \
+ aacdecoder_lib.cpp \
+ aacdec_tns.cpp \
+ aac_rom.cpp \
+ channel.cpp \
+ conceal.cpp \
+ pulsedata.cpp \
+ rvlcconceal.cpp \
+ stereo.cpp
+
+LOCAL_CFLAGS := -DANDROID
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH) \
+ $(LOCAL_PATH)/../include \
+ $(LOCAL_PATH)/../../libPCMutils/include \
+ $(LOCAL_PATH)/../../libFDK/include \
+ $(LOCAL_PATH)/../../libSYS/include \
+ $(LOCAL_PATH)/../../libMpegTPDec/include \
+ $(LOCAL_PATH)/../../libSBRdec/include
+
+LOCAL_MODULE:= libAACdec
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp
new file mode 100644
index 0000000..ce8aee6
--- /dev/null
+++ b/libAACdec/src/aac_ram.cpp
@@ -0,0 +1,81 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2002)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "aac_ram.h"
+#include "aac_rom.h"
+
+#define WORKBUFFER1_TAG 0
+#define WORKBUFFER2_TAG 1
+
+/*! The structure AAC_DECODER_INSTANCE is the top level structure holding all decoder configurations,
+ handles and structs.
+ */
+C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1)
+
+/*!
+ \name StaticAacData
+
+ Static memory areas, must not be overwritten in other sections of the decoder
+*/
+/* @{ */
+
+/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo which is needed
+ for the decoding of one aac channel. <br>
+ Dimension: #AacDecoderChannels */
+C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (6))
+
+/*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is needed
+ for the decoding of one aac channel. <br>
+ Dimension: #AacDecoderChannels */
+C_ALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (6))
+
+/*! Overlap buffer */
+C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (6))
+
+C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
+
+/* @} */
+
+/*!
+ \name DynamicAacData
+
+ Dynamic memory areas, might be reused in other algorithm sections,
+ e.g. the sbr decoder
+*/
+C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((6)*1024), SECT_DATA_L2, WORKBUFFER2_TAG)
+
+
+C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, WORKBUFFER1_TAG)
+
+/* @{ */
+
+
+/* @} */
+
+
+
diff --git a/libAACdec/src/aac_ram.h b/libAACdec/src/aac_ram.h
new file mode 100644
index 0000000..7c129e2
--- /dev/null
+++ b/libAACdec/src/aac_ram.h
@@ -0,0 +1,58 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2005)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef AAC_RAM_H
+#define AAC_RAM_H
+
+#include "common_fix.h"
+
+#include "aacdecoder.h"
+
+#include "channel.h"
+
+#include "aacdec_hcr_types.h"
+#include "aacdec_hcr.h"
+
+/* End of formal fix.h */
+
+#define MAX_SYNCHS 10
+#define SAMPL_FREQS 12
+
+H_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE)
+
+H_ALLOC_MEM(DrcInfo, CDrcInfo)
+
+H_ALLOC_MEM(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo)
+H_ALLOC_MEM(AacDecoderChannelInfo, CAacDecoderChannelInfo)
+H_ALLOC_MEM(OverlapBuffer, FIXP_DBL)
+
+H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1)
+H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL)
+
+
+#endif /* #ifndef AAC_RAM_H */
diff --git a/libAACdec/src/aac_rom.cpp b/libAACdec/src/aac_rom.cpp
new file mode 100644
index 0000000..c4246c0
--- /dev/null
+++ b/libAACdec/src/aac_rom.cpp
@@ -0,0 +1,1780 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: Definition of constant tables
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "aac_rom.h"
+
+
+/* Prescale InverseQuantTable by 4 to save
+ redundant shifts in invers quantization
+ */
+#define SCL_TAB(a) (a>>4)
+const FIXP_DBL InverseQuantTable [INV_QUANT_TABLESIZE + 1] =
+{
+ SCL_TAB(0x32CBFD40), SCL_TAB(0x330FC340), SCL_TAB(0x33539FC0), SCL_TAB(0x33979280), SCL_TAB(0x33DB9BC0), SCL_TAB(0x341FBB80), SCL_TAB(0x3463F180), SCL_TAB(0x34A83DC0),
+ SCL_TAB(0x34ECA000), SCL_TAB(0x35311880), SCL_TAB(0x3575A700), SCL_TAB(0x35BA4B80), SCL_TAB(0x35FF0600), SCL_TAB(0x3643D680), SCL_TAB(0x3688BCC0), SCL_TAB(0x36CDB880),
+ SCL_TAB(0x3712CA40), SCL_TAB(0x3757F1C0), SCL_TAB(0x379D2F00), SCL_TAB(0x37E28180), SCL_TAB(0x3827E9C0), SCL_TAB(0x386D6740), SCL_TAB(0x38B2FA40), SCL_TAB(0x38F8A2C0),
+ SCL_TAB(0x393E6080), SCL_TAB(0x39843380), SCL_TAB(0x39CA1BC0), SCL_TAB(0x3A101940), SCL_TAB(0x3A562BC0), SCL_TAB(0x3A9C5340), SCL_TAB(0x3AE28FC0), SCL_TAB(0x3B28E180),
+ SCL_TAB(0x3B6F4800), SCL_TAB(0x3BB5C340), SCL_TAB(0x3BFC5380), SCL_TAB(0x3C42F880), SCL_TAB(0x3C89B200), SCL_TAB(0x3CD08080), SCL_TAB(0x3D176340), SCL_TAB(0x3D5E5B00),
+ SCL_TAB(0x3DA56700), SCL_TAB(0x3DEC87C0), SCL_TAB(0x3E33BCC0), SCL_TAB(0x3E7B0640), SCL_TAB(0x3EC26400), SCL_TAB(0x3F09D640), SCL_TAB(0x3F515C80), SCL_TAB(0x3F98F740),
+ SCL_TAB(0x3FE0A600), SCL_TAB(0x40286900), SCL_TAB(0x40704000), SCL_TAB(0x40B82B00), SCL_TAB(0x41002A00), SCL_TAB(0x41483D00), SCL_TAB(0x41906400), SCL_TAB(0x41D89F00),
+ SCL_TAB(0x4220ED80), SCL_TAB(0x42695000), SCL_TAB(0x42B1C600), SCL_TAB(0x42FA5000), SCL_TAB(0x4342ED80), SCL_TAB(0x438B9E80), SCL_TAB(0x43D46380), SCL_TAB(0x441D3B80),
+ SCL_TAB(0x44662780), SCL_TAB(0x44AF2680), SCL_TAB(0x44F83900), SCL_TAB(0x45415F00), SCL_TAB(0x458A9880), SCL_TAB(0x45D3E500), SCL_TAB(0x461D4500), SCL_TAB(0x4666B800),
+ SCL_TAB(0x46B03E80), SCL_TAB(0x46F9D800), SCL_TAB(0x47438480), SCL_TAB(0x478D4400), SCL_TAB(0x47D71680), SCL_TAB(0x4820FC00), SCL_TAB(0x486AF500), SCL_TAB(0x48B50000),
+ SCL_TAB(0x48FF1E80), SCL_TAB(0x49494F80), SCL_TAB(0x49939380), SCL_TAB(0x49DDEA80), SCL_TAB(0x4A285400), SCL_TAB(0x4A72D000), SCL_TAB(0x4ABD5E80), SCL_TAB(0x4B080000),
+ SCL_TAB(0x4B52B400), SCL_TAB(0x4B9D7A80), SCL_TAB(0x4BE85380), SCL_TAB(0x4C333F00), SCL_TAB(0x4C7E3D00), SCL_TAB(0x4CC94D00), SCL_TAB(0x4D146F80), SCL_TAB(0x4D5FA500),
+ SCL_TAB(0x4DAAEC00), SCL_TAB(0x4DF64580), SCL_TAB(0x4E41B180), SCL_TAB(0x4E8D2F00), SCL_TAB(0x4ED8BF80), SCL_TAB(0x4F246180), SCL_TAB(0x4F701600), SCL_TAB(0x4FBBDC00),
+ SCL_TAB(0x5007B480), SCL_TAB(0x50539F00), SCL_TAB(0x509F9B80), SCL_TAB(0x50EBA980), SCL_TAB(0x5137C980), SCL_TAB(0x5183FB80), SCL_TAB(0x51D03F80), SCL_TAB(0x521C9500),
+ SCL_TAB(0x5268FC80), SCL_TAB(0x52B57580), SCL_TAB(0x53020000), SCL_TAB(0x534E9C80), SCL_TAB(0x539B4A80), SCL_TAB(0x53E80A80), SCL_TAB(0x5434DB80), SCL_TAB(0x5481BE80),
+ SCL_TAB(0x54CEB280), SCL_TAB(0x551BB880), SCL_TAB(0x5568CF80), SCL_TAB(0x55B5F800), SCL_TAB(0x56033200), SCL_TAB(0x56507D80), SCL_TAB(0x569DDA00), SCL_TAB(0x56EB4800),
+ SCL_TAB(0x5738C700), SCL_TAB(0x57865780), SCL_TAB(0x57D3F900), SCL_TAB(0x5821AC00), SCL_TAB(0x586F7000), SCL_TAB(0x58BD4500), SCL_TAB(0x590B2B00), SCL_TAB(0x59592200),
+ SCL_TAB(0x59A72A80), SCL_TAB(0x59F54380), SCL_TAB(0x5A436D80), SCL_TAB(0x5A91A900), SCL_TAB(0x5ADFF500), SCL_TAB(0x5B2E5180), SCL_TAB(0x5B7CBF80), SCL_TAB(0x5BCB3E00),
+ SCL_TAB(0x5C19CD00), SCL_TAB(0x5C686D80), SCL_TAB(0x5CB71E00), SCL_TAB(0x5D05DF80), SCL_TAB(0x5D54B200), SCL_TAB(0x5DA39500), SCL_TAB(0x5DF28880), SCL_TAB(0x5E418C80),
+ SCL_TAB(0x5E90A100), SCL_TAB(0x5EDFC680), SCL_TAB(0x5F2EFC00), SCL_TAB(0x5F7E4280), SCL_TAB(0x5FCD9900), SCL_TAB(0x601D0080), SCL_TAB(0x606C7800), SCL_TAB(0x60BC0000),
+ SCL_TAB(0x610B9800), SCL_TAB(0x615B4100), SCL_TAB(0x61AAF980), SCL_TAB(0x61FAC300), SCL_TAB(0x624A9C80), SCL_TAB(0x629A8600), SCL_TAB(0x62EA8000), SCL_TAB(0x633A8A00),
+ SCL_TAB(0x638AA480), SCL_TAB(0x63DACF00), SCL_TAB(0x642B0980), SCL_TAB(0x647B5400), SCL_TAB(0x64CBAE80), SCL_TAB(0x651C1900), SCL_TAB(0x656C9400), SCL_TAB(0x65BD1E80),
+ SCL_TAB(0x660DB900), SCL_TAB(0x665E6380), SCL_TAB(0x66AF1E00), SCL_TAB(0x66FFE880), SCL_TAB(0x6750C280), SCL_TAB(0x67A1AC80), SCL_TAB(0x67F2A600), SCL_TAB(0x6843B000),
+ SCL_TAB(0x6894C900), SCL_TAB(0x68E5F200), SCL_TAB(0x69372B00), SCL_TAB(0x69887380), SCL_TAB(0x69D9CB80), SCL_TAB(0x6A2B3300), SCL_TAB(0x6A7CAA80), SCL_TAB(0x6ACE3180),
+ SCL_TAB(0x6B1FC800), SCL_TAB(0x6B716E00), SCL_TAB(0x6BC32400), SCL_TAB(0x6C14E900), SCL_TAB(0x6C66BD80), SCL_TAB(0x6CB8A180), SCL_TAB(0x6D0A9500), SCL_TAB(0x6D5C9800),
+ SCL_TAB(0x6DAEAA00), SCL_TAB(0x6E00CB80), SCL_TAB(0x6E52FC80), SCL_TAB(0x6EA53D00), SCL_TAB(0x6EF78C80), SCL_TAB(0x6F49EB80), SCL_TAB(0x6F9C5980), SCL_TAB(0x6FEED700),
+ SCL_TAB(0x70416380), SCL_TAB(0x7093FF00), SCL_TAB(0x70E6AA00), SCL_TAB(0x71396400), SCL_TAB(0x718C2D00), SCL_TAB(0x71DF0580), SCL_TAB(0x7231ED00), SCL_TAB(0x7284E300),
+ SCL_TAB(0x72D7E880), SCL_TAB(0x732AFD00), SCL_TAB(0x737E2080), SCL_TAB(0x73D15300), SCL_TAB(0x74249480), SCL_TAB(0x7477E480), SCL_TAB(0x74CB4400), SCL_TAB(0x751EB200),
+ SCL_TAB(0x75722F00), SCL_TAB(0x75C5BB00), SCL_TAB(0x76195580), SCL_TAB(0x766CFF00), SCL_TAB(0x76C0B700), SCL_TAB(0x77147E00), SCL_TAB(0x77685400), SCL_TAB(0x77BC3880),
+ SCL_TAB(0x78102B80), SCL_TAB(0x78642D80), SCL_TAB(0x78B83E00), SCL_TAB(0x790C5D00), SCL_TAB(0x79608B00), SCL_TAB(0x79B4C780), SCL_TAB(0x7A091280), SCL_TAB(0x7A5D6C00),
+ SCL_TAB(0x7AB1D400), SCL_TAB(0x7B064A80), SCL_TAB(0x7B5ACF80), SCL_TAB(0x7BAF6380), SCL_TAB(0x7C040580), SCL_TAB(0x7C58B600), SCL_TAB(0x7CAD7500), SCL_TAB(0x7D024200),
+ SCL_TAB(0x7D571E00), SCL_TAB(0x7DAC0800), SCL_TAB(0x7E010080), SCL_TAB(0x7E560780), SCL_TAB(0x7EAB1C80), SCL_TAB(0x7F004000), SCL_TAB(0x7F557200), SCL_TAB(0x7FAAB200),
+ SCL_TAB(0x7FFFFFFF)
+} ;
+
+/**
+ * \brief Table representing scale factor gains. Given a scale factor sf, and a value pSpec[i] the
+ * gain is given by: MantissaTable[sf % 4][msb] = 2^(sf % 4) / (1<<ExponentTable[sf % 4][msb]
+ * The second dimension "msb" represents the upper scale factor bit count floor(log2(scalefactor >> 2))
+ * The corresponding exponents for the values in this tables are stored in ExponentTable[sf % 4][msb] below.
+ */
+const FIXP_DBL MantissaTable [4][14] =
+{
+ {
+ 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00,
+ 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00
+ },
+ {
+ 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380,
+ 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380
+ },
+ {
+ 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800,
+ 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800
+ },
+ {
+ 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80,
+ 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80
+ }
+} ;
+
+const SCHAR ExponentTable [4][14] =
+{
+ { 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18 },
+ { 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18 },
+ { 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18 },
+ { 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19 }
+} ;
+
+
+
+/* 49 scfbands */
+static const SHORT sfb_48_1024[50] = {
+ 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
+};
+/* 14 scfbands */
+static const SHORT sfb_48_128[15] =
+{
+ 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112,
+ 128
+};
+
+/* 51 scfbands */
+static const SHORT sfb_32_1024[52] =
+{
+ 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
+};
+
+/* 47 scfbands */
+static const SHORT sfb_24_1024[48] =
+{
+ 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
+};
+
+/* 15 scfbands */
+static const SHORT sfb_24_128[16] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92,
+ 108, 128
+};
+
+/* 43 scfbands */
+static const SHORT sfb_16_1024[44] =
+{
+ 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
+};
+
+/* 15 scfbands */
+static const SHORT sfb_16_128[16] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88,
+ 108, 128
+};
+
+/* 40 scfbands */
+static const SHORT sfb_8_1024[41] =
+{
+ 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
+};
+
+/* 15 scfbands */
+static const SHORT sfb_8_128[16] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88,
+ 108, 128
+};
+
+
+
+static const SHORT sfb_48_960[50] =
+{
+ 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
+}; /* 49 scfbands */
+static const SHORT sfb_48_120[15] =
+{
+ 0, 4, 8, 12, 16, 20, 28, 36, 44, 56,
+ 68, 80, 96, 112, 120
+}; /* 14 scfbands */
+
+static const SHORT sfb_32_960[50] =
+{
+ 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
+}; /* 49 scfbands */
+
+static const SHORT sfb_24_960[47] =
+{
+ 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
+}; /* 46 scfbands */
+
+static const SHORT sfb_24_120[16] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44,
+ 52, 64, 76, 92, 108, 120
+}; /* 15 scfbands */
+
+static const SHORT sfb_16_960[43] =
+{
+ 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
+}; /* 42 scfbands */
+
+static const SHORT sfb_16_120[16] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 40,
+ 48, 60, 72, 88, 108, 120
+}; /* 15 scfbands */
+
+static const SHORT sfb_8_960[41] =
+{
+ 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,
+ 960
+}; /* 40 scfbands */
+
+static const SHORT sfb_8_120[16] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44,
+ 52, 60, 72, 88, 108, 120
+}; /* 15 scfbands */
+
+
+
+
+static const SHORT sfb_48_512[37] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 48, 52, 56, 60, 68, 76, 84, 92,
+ 100, 112, 124, 136, 148, 164, 184, 208, 236, 268,
+ 300, 332, 364, 396, 428, 460, 512
+}; /* 36 scfbands */
+static const SHORT sfb_32_512[38] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 48, 52, 56, 64, 72, 80, 88, 96,
+ 108, 120, 132, 144, 160, 176, 192, 212, 236, 260,
+ 288, 320, 352, 384, 416, 448, 480, 512
+}; /* 37 scfbands */
+static const SHORT sfb_24_512[32] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 52, 60, 68, 80, 92, 104, 120, 140,
+ 164, 192, 224, 256, 288, 320, 352, 384, 416, 448,
+ 480, 512
+}; /* 31 scfbands */
+
+static const SHORT sfb_48_480[36] =
+{
+ 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, 272,
+ 304, 336, 368, 400, 432, 480
+}; /* 35 scfbands */
+static const SHORT sfb_32_480[38] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 48, 52, 56, 60, 64, 72, 80, 88,
+ 96, 104, 112, 124, 136, 148, 164, 180, 200, 224,
+ 256, 288, 320, 352, 384, 416, 448, 480
+}; /* 37 scfbands */
+static const SHORT sfb_24_480[31] =
+{
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 52, 60, 68, 80, 92, 104, 120, 140,
+ 164, 192, 224, 256, 288, 320, 352, 384, 416, 448,
+ 480
+}; /* 30 scfbands */
+
+const SFB_INFO sfbOffsetTables[5][16] =
+{
+ {
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { sfb_48_1024, sfb_48_128, 49, 14 },
+ { sfb_48_1024, sfb_48_128, 49, 14 },
+ { sfb_32_1024, sfb_48_128, 51, 14 },
+ { sfb_24_1024, sfb_24_128, 47, 15 },
+ { sfb_24_1024, sfb_24_128, 47, 15 },
+ { sfb_16_1024, sfb_16_128, 43, 15 },
+ { sfb_16_1024, sfb_16_128, 43, 15 },
+ { sfb_16_1024, sfb_16_128, 43, 15 },
+ { sfb_8_1024, sfb_8_128, 40, 15 },
+ { sfb_8_1024, sfb_8_128, 40, 15 },
+ }, {
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { sfb_48_960, sfb_48_120, 49, 14 },
+ { sfb_48_960, sfb_48_120, 49, 14 },
+ { sfb_32_960, sfb_48_120, 49, 14 },
+ { sfb_24_960, sfb_24_120, 46, 15 },
+ { sfb_24_960, sfb_24_120, 46, 15 },
+ { sfb_16_960, sfb_16_120, 42, 15 },
+ { sfb_16_960, sfb_16_120, 42, 15 },
+ { sfb_16_960, sfb_16_120, 42, 15 },
+ { sfb_8_960, sfb_8_120, 40, 15 },
+ { sfb_8_960, sfb_8_120, 40, 15 },
+ }, {
+ { NULL, NULL, 0, 0 },
+ }, {
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { sfb_48_512, NULL, 36, 0 },
+ { sfb_48_512, NULL, 36, 0},
+ { sfb_32_512, NULL, 37, 0 },
+ { sfb_24_512, NULL, 31, 0 },
+ { sfb_24_512, NULL, 31, 0 },
+ { sfb_24_512, NULL, 31, 0 },
+ { sfb_24_512, NULL, 31, 0 },
+ { sfb_24_512, NULL, 31, 0 },
+ { sfb_24_512, NULL, 31, 0 },
+ { sfb_24_512, NULL, 31, 0 },
+ }, {
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { NULL, NULL, 0, 0 },
+ { sfb_48_480, NULL, 35, 0 },
+ { sfb_48_480, NULL, 35, 0 },
+ { sfb_32_480, NULL, 37, 0 },
+ { sfb_24_480, NULL, 30, 0 },
+ { sfb_24_480, NULL, 30, 0 },
+ { sfb_24_480, NULL, 30, 0 },
+ { sfb_24_480, NULL, 30, 0 },
+ { sfb_24_480, NULL, 30, 0 },
+ { sfb_24_480, NULL, 30, 0 },
+ { sfb_24_480, NULL, 30, 0 },
+ }
+};
+
+
+/*# don't use 1 bit hufman tables */
+/*
+ MPEG-2 AAC 2 BITS parallel Hufman Tables
+
+ Bit 0: = 1=ENDNODE, 0=INDEX
+ Bit 1: = CODEWORD LEN MOD 2
+ Bit 2..9: = VALUE/REF Tables 1..10,SCL
+ Bit 2..11: = VALUE/REF Table 11
+*/
+ const USHORT HuffmanCodeBook_1[51][4] =
+{
+ {0x0157,0x0157,0x0004,0x0018}, {0x0008,0x000c,0x0010,0x0014}, {0x015b,0x015b,0x0153,0x0153}, {0x0057,0x0057,0x0167,0x0167},
+ {0x0257,0x0257,0x0117,0x0117}, {0x0197,0x0197,0x0147,0x0147}, {0x001c,0x0030,0x0044,0x0058}, {0x0020,0x0024,0x0028,0x002c},
+ {0x014b,0x014b,0x0163,0x0163}, {0x0217,0x0217,0x0127,0x0127}, {0x0187,0x0187,0x0097,0x0097}, {0x016b,0x016b,0x0017,0x0017},
+ {0x0034,0x0038,0x003c,0x0040}, {0x0143,0x0143,0x0107,0x0107}, {0x011b,0x011b,0x0067,0x0067}, {0x0193,0x0193,0x0297,0x0297},
+ {0x019b,0x019b,0x0247,0x0247}, {0x0048,0x004c,0x0050,0x0054}, {0x01a7,0x01a7,0x0267,0x0267}, {0x0113,0x0113,0x025b,0x025b},
+ {0x0053,0x0053,0x005b,0x005b}, {0x0253,0x0253,0x0047,0x0047}, {0x005c,0x0070,0x0084,0x0098}, {0x0060,0x0064,0x0068,0x006c},
+ {0x012b,0x012b,0x0123,0x0123}, {0x018b,0x018b,0x00a7,0x00a7}, {0x0227,0x0227,0x0287,0x0287}, {0x0087,0x0087,0x010b,0x010b},
+ {0x0074,0x0078,0x007c,0x0080}, {0x021b,0x021b,0x0027,0x0027}, {0x01a3,0x01a3,0x0093,0x0093}, {0x0183,0x0183,0x0207,0x0207},
+ {0x024b,0x024b,0x004b,0x004b}, {0x0088,0x008c,0x0090,0x0094}, {0x0063,0x0063,0x0103,0x0103}, {0x0007,0x0007,0x02a7,0x02a7},
+ {0x009b,0x009b,0x026b,0x026b}, {0x0263,0x0263,0x01ab,0x01ab}, {0x009c,0x00a0,0x00a4,0x00b8}, {0x0241,0x0011,0x0069,0x0019},
+ {0x0211,0x0041,0x0291,0x0299}, {0x00a8,0x00ac,0x00b0,0x00b4}, {0x008b,0x008b,0x0223,0x0223}, {0x00a3,0x00a3,0x020b,0x020b},
+ {0x02ab,0x02ab,0x0283,0x0283}, {0x002b,0x002b,0x0083,0x0083}, {0x00bc,0x00c0,0x00c4,0x00c8}, {0x0003,0x0003,0x022b,0x022b},
+ {0x028b,0x028b,0x02a3,0x02a3}, {0x0023,0x0023,0x0203,0x0203}, {0x000b,0x000b,0x00ab,0x00ab}
+};
+
+const USHORT HuffmanCodeBook_2[39][4] =
+{
+ {0x0004,0x000c,0x0020,0x0034}, {0x0157,0x0157,0x0159,0x0008}, {0x0153,0x0153,0x0257,0x0257}, {0x0010,0x0014,0x0018,0x001c},
+ {0x0117,0x0117,0x0057,0x0057}, {0x0147,0x0147,0x0197,0x0197}, {0x0167,0x0167,0x0185,0x0161}, {0x0125,0x0095,0x0065,0x0215},
+ {0x0024,0x0028,0x002c,0x0030}, {0x0051,0x0149,0x0119,0x0141}, {0x0015,0x0199,0x0259,0x0245}, {0x0191,0x0265,0x0105,0x0251},
+ {0x0045,0x0111,0x0169,0x01a5}, {0x0038,0x0044,0x0058,0x006c}, {0x0295,0x0059,0x003c,0x0040}, {0x0227,0x0227,0x021b,0x021b},
+ {0x0123,0x0123,0x0087,0x0087}, {0x0048,0x004c,0x0050,0x0054}, {0x018b,0x018b,0x006b,0x006b}, {0x029b,0x029b,0x01a3,0x01a3},
+ {0x0207,0x0207,0x01ab,0x01ab}, {0x0093,0x0093,0x0103,0x0103}, {0x005c,0x0060,0x0064,0x0068}, {0x0213,0x0213,0x010b,0x010b},
+ {0x012b,0x012b,0x0249,0x0061}, {0x0181,0x0291,0x0241,0x0041}, {0x0005,0x0099,0x0019,0x0025}, {0x0070,0x0074,0x0078,0x0088},
+ {0x02a5,0x0261,0x0011,0x00a5}, {0x0049,0x0285,0x0269,0x0089}, {0x0221,0x007c,0x0080,0x0084}, {0x020b,0x020b,0x0003,0x0003},
+ {0x00a3,0x00a3,0x02a3,0x02a3}, {0x02ab,0x02ab,0x0083,0x0083}, {0x008c,0x0090,0x0094,0x0098}, {0x028b,0x028b,0x0023,0x0023},
+ {0x0283,0x0283,0x002b,0x002b}, {0x000b,0x000b,0x0203,0x0203}, {0x022b,0x022b,0x00ab,0x00ab}
+};
+
+const USHORT HuffmanCodeBook_3[39][4] =
+{
+ {0x0003,0x0003,0x0004,0x0008}, {0x0005,0x0101,0x0011,0x0041}, {0x000c,0x0010,0x0014,0x0020}, {0x0017,0x0017,0x0143,0x0143},
+ {0x0051,0x0111,0x0045,0x0151}, {0x0105,0x0055,0x0018,0x001c}, {0x0157,0x0157,0x0147,0x0147}, {0x0117,0x0117,0x0009,0x0201},
+ {0x0024,0x002c,0x0040,0x0054}, {0x0241,0x0019,0x0065,0x0028}, {0x0183,0x0183,0x0193,0x0193}, {0x0030,0x0034,0x0038,0x003c},
+ {0x0027,0x0027,0x0253,0x0253}, {0x005b,0x005b,0x0083,0x0083}, {0x0063,0x0063,0x0093,0x0093}, {0x0023,0x0023,0x0213,0x0213},
+ {0x0044,0x0048,0x004c,0x0050}, {0x004b,0x004b,0x0167,0x0167}, {0x0163,0x0163,0x0097,0x0097}, {0x0197,0x0197,0x0125,0x0085},
+ {0x0185,0x0121,0x0159,0x0255}, {0x0058,0x005c,0x0060,0x0070}, {0x0119,0x0245,0x0281,0x0291}, {0x0069,0x00a5,0x0205,0x0109},
+ {0x01a1,0x0064,0x0068,0x006c}, {0x002b,0x002b,0x01a7,0x01a7}, {0x0217,0x0217,0x014b,0x014b}, {0x0297,0x0297,0x016b,0x016b},
+ {0x0074,0x0078,0x007c,0x0080}, {0x00a3,0x00a3,0x0263,0x0263}, {0x0285,0x0129,0x0099,0x00a9}, {0x02a1,0x01a9,0x0199,0x0265},
+ {0x02a5,0x0084,0x0088,0x008c}, {0x0223,0x0223,0x008b,0x008b}, {0x0227,0x0227,0x0189,0x0259}, {0x0219,0x0090,0x0094,0x0098},
+ {0x02ab,0x02ab,0x026b,0x026b}, {0x029b,0x029b,0x024b,0x024b}, {0x020b,0x020b,0x0229,0x0289}
+};
+
+const USHORT HuffmanCodeBook_4[38][4] =
+{
+ {0x0004,0x0008,0x000c,0x0018}, {0x0155,0x0151,0x0115,0x0055}, {0x0145,0x0005,0x0015,0x0001}, {0x0141,0x0045,0x0010,0x0014},
+ {0x0107,0x0107,0x0053,0x0053}, {0x0103,0x0103,0x0113,0x0113}, {0x001c,0x0020,0x0034,0x0048}, {0x0043,0x0043,0x0013,0x0013},
+ {0x0024,0x0028,0x002c,0x0030}, {0x015b,0x015b,0x0197,0x0197}, {0x0167,0x0167,0x0257,0x0257}, {0x005b,0x005b,0x011b,0x011b},
+ {0x0067,0x0067,0x014b,0x014b}, {0x0038,0x003c,0x0040,0x0044}, {0x0193,0x0193,0x0251,0x0095}, {0x0161,0x0245,0x0125,0x0215},
+ {0x0185,0x0019,0x0049,0x0025}, {0x0109,0x0211,0x0061,0x0241}, {0x004c,0x0050,0x0058,0x006c}, {0x0091,0x0121,0x0205,0x0181},
+ {0x0085,0x0009,0x0201,0x0054}, {0x0023,0x0023,0x0083,0x0083}, {0x005c,0x0060,0x0064,0x0068}, {0x01a7,0x01a7,0x016b,0x016b},
+ {0x019b,0x019b,0x0297,0x0297}, {0x0267,0x0267,0x025b,0x025b}, {0x00a5,0x0069,0x0099,0x01a1}, {0x0070,0x0074,0x0078,0x0084},
+ {0x0291,0x0129,0x0261,0x0189}, {0x0285,0x01a9,0x0225,0x0249}, {0x0219,0x02a5,0x007c,0x0080}, {0x029b,0x029b,0x026b,0x026b},
+ {0x00a3,0x00a3,0x002b,0x002b}, {0x0088,0x008c,0x0090,0x0094}, {0x0283,0x0283,0x008b,0x008b}, {0x0223,0x0223,0x020b,0x020b},
+ {0x02ab,0x02ab,0x02a3,0x02a3}, {0x00ab,0x00ab,0x0229,0x0289}
+};
+
+const USHORT HuffmanCodeBook_5[41][4] =
+{
+ {0x0113,0x0113,0x0004,0x0008}, {0x010d,0x0115,0x0151,0x00d1}, {0x000c,0x0010,0x0014,0x0028}, {0x00d7,0x00d7,0x014f,0x014f},
+ {0x00cf,0x00cf,0x0157,0x0157}, {0x0018,0x001c,0x0020,0x0024}, {0x010b,0x010b,0x0193,0x0193}, {0x011b,0x011b,0x0093,0x0093},
+ {0x00c9,0x0159,0x008d,0x0195}, {0x0149,0x00d9,0x018d,0x0095}, {0x002c,0x0030,0x0044,0x0058}, {0x0105,0x011d,0x0051,0x01d1},
+ {0x0034,0x0038,0x003c,0x0040}, {0x00c7,0x00c7,0x01d7,0x01d7}, {0x015f,0x015f,0x004f,0x004f}, {0x0147,0x0147,0x00df,0x00df},
+ {0x0057,0x0057,0x01cf,0x01cf}, {0x0048,0x004c,0x0050,0x0054}, {0x018b,0x018b,0x019b,0x019b}, {0x008b,0x008b,0x009b,0x009b},
+ {0x0085,0x009d,0x01c9,0x0059}, {0x019d,0x01d9,0x0185,0x0049}, {0x005c,0x0060,0x0074,0x0088}, {0x0011,0x0101,0x0161,0x0121},
+ {0x0064,0x0068,0x006c,0x0070}, {0x00c3,0x00c3,0x0213,0x0213}, {0x00e3,0x00e3,0x000f,0x000f}, {0x0217,0x0217,0x020f,0x020f},
+ {0x0143,0x0143,0x0017,0x0017}, {0x0078,0x007c,0x0080,0x0084}, {0x005f,0x005f,0x0047,0x0047}, {0x01c7,0x01c7,0x020b,0x020b},
+ {0x0083,0x0083,0x01a3,0x01a3}, {0x001b,0x001b,0x021b,0x021b}, {0x008c,0x0090,0x0094,0x0098}, {0x01df,0x01df,0x0183,0x0183},
+ {0x0009,0x00a1,0x001d,0x0041}, {0x01c1,0x021d,0x0205,0x01e1}, {0x0061,0x0005,0x009c,0x00a0}, {0x0023,0x0023,0x0203,0x0203},
+ {0x0223,0x0223,0x0003,0x0003}
+};
+
+const USHORT HuffmanCodeBook_6[40][4] =
+{
+ {0x0004,0x0008,0x000c,0x001c}, {0x0111,0x0115,0x00d1,0x0151}, {0x010d,0x0155,0x014d,0x00d5}, {0x00cd,0x0010,0x0014,0x0018},
+ {0x00d9,0x0159,0x0149,0x00c9}, {0x0109,0x018d,0x0119,0x0095}, {0x0195,0x0091,0x008d,0x0191}, {0x0020,0x0024,0x0038,0x004c},
+ {0x0099,0x0189,0x0089,0x0199}, {0x0028,0x002c,0x0030,0x0034}, {0x0147,0x0147,0x015f,0x015f}, {0x00df,0x00df,0x01cf,0x01cf},
+ {0x00c7,0x00c7,0x01d7,0x01d7}, {0x0057,0x0057,0x004f,0x004f}, {0x003c,0x0040,0x0044,0x0048}, {0x011f,0x011f,0x0107,0x0107},
+ {0x0053,0x0053,0x01d3,0x01d3}, {0x019f,0x019f,0x0085,0x01c9}, {0x01d9,0x009d,0x0059,0x0049}, {0x0050,0x005c,0x0070,0x0084},
+ {0x0185,0x01dd,0x0054,0x0058}, {0x005f,0x005f,0x0047,0x0047}, {0x01c7,0x01c7,0x0017,0x0017}, {0x0060,0x0064,0x0068,0x006c},
+ {0x000f,0x000f,0x0163,0x0163}, {0x0143,0x0143,0x00c3,0x00c3}, {0x0217,0x0217,0x00e3,0x00e3}, {0x020f,0x020f,0x0013,0x0013},
+ {0x0074,0x0078,0x007c,0x0080}, {0x0183,0x0183,0x0083,0x0083}, {0x021b,0x021b,0x000b,0x000b}, {0x0103,0x0103,0x01a3,0x01a3},
+ {0x00a3,0x00a3,0x020b,0x020b}, {0x0088,0x008c,0x0090,0x0094}, {0x0123,0x0123,0x001b,0x001b}, {0x0213,0x0213,0x0005,0x0205},
+ {0x001d,0x0061,0x021d,0x01e1}, {0x01c1,0x0041,0x0098,0x009c}, {0x0223,0x0223,0x0203,0x0203}, {0x0003,0x0003,0x0023,0x0023}
+};
+
+const USHORT HuffmanCodeBook_7[31][4] =
+{
+ {0x0003,0x0003,0x0004,0x0008}, {0x0007,0x0007,0x0043,0x0043}, {0x0045,0x000c,0x0010,0x0024}, {0x0049,0x0085,0x0009,0x0081},
+ {0x0014,0x0018,0x001c,0x0020}, {0x004f,0x004f,0x00c7,0x00c7}, {0x008b,0x008b,0x000f,0x000f}, {0x00c3,0x00c3,0x00c9,0x008d},
+ {0x0105,0x0051,0x0145,0x0055}, {0x0028,0x002c,0x0040,0x0054}, {0x00cd,0x0109,0x0101,0x0011}, {0x0030,0x0034,0x0038,0x003c},
+ {0x0093,0x0093,0x014b,0x014b}, {0x0097,0x0097,0x0143,0x0143}, {0x005b,0x005b,0x0017,0x0017}, {0x0187,0x0187,0x00d3,0x00d3},
+ {0x0044,0x0048,0x004c,0x0050}, {0x014f,0x014f,0x010f,0x010f}, {0x00d7,0x00d7,0x018b,0x018b}, {0x009b,0x009b,0x01c7,0x01c7},
+ {0x018d,0x0181,0x0019,0x0111}, {0x0058,0x005c,0x0060,0x0068}, {0x005d,0x0151,0x009d,0x0115}, {0x00d9,0x01c9,0x00dd,0x0119},
+ {0x0155,0x0191,0x01cd,0x0064}, {0x001f,0x001f,0x01c3,0x01c3}, {0x006c,0x0070,0x0074,0x0078}, {0x015b,0x015b,0x0197,0x0197},
+ {0x011f,0x011f,0x01d3,0x01d3}, {0x01d7,0x01d7,0x015f,0x015f}, {0x019d,0x0199,0x01d9,0x01dd}
+};
+
+const USHORT HuffmanCodeBook_8[31][4] =
+{
+ {0x0004,0x0008,0x0010,0x0024}, {0x0047,0x0047,0x0049,0x0005}, {0x0085,0x0041,0x0089,0x000c}, {0x0003,0x0003,0x000b,0x000b},
+ {0x0014,0x0018,0x001c,0x0020}, {0x0083,0x0083,0x004f,0x004f}, {0x00c7,0x00c7,0x008f,0x008f}, {0x00cb,0x00cb,0x00cd,0x0051},
+ {0x0105,0x0091,0x0109,0x000d}, {0x0028,0x002c,0x0040,0x0054}, {0x00c1,0x00d1,0x010d,0x0095}, {0x0030,0x0034,0x0038,0x003c},
+ {0x0057,0x0057,0x014b,0x014b}, {0x0147,0x0147,0x00d7,0x00d7}, {0x014f,0x014f,0x0113,0x0113}, {0x0117,0x0117,0x0103,0x0103},
+ {0x0044,0x0048,0x004c,0x0050}, {0x0153,0x0153,0x0013,0x0013}, {0x018b,0x018b,0x009b,0x009b}, {0x005b,0x005b,0x0187,0x0187},
+ {0x018d,0x00d9,0x0155,0x0015}, {0x0058,0x005c,0x0060,0x0068}, {0x0119,0x0141,0x0191,0x005d}, {0x009d,0x01c9,0x0159,0x00dd},
+ {0x01c5,0x0195,0x01cd,0x0064}, {0x019b,0x019b,0x011f,0x011f}, {0x006c,0x0070,0x0074,0x0078}, {0x001b,0x001b,0x01d3,0x01d3},
+ {0x0183,0x0183,0x015f,0x015f}, {0x019f,0x019f,0x01db,0x01db}, {0x01d5,0x001d,0x01c1,0x01dd}
+};
+
+const USHORT HuffmanCodeBook_9[84][4] =
+{
+ {0x0003,0x0003,0x0004,0x0008}, {0x0007,0x0007,0x0043,0x0043}, {0x0045,0x000c,0x0010,0x002c}, {0x0049,0x0085,0x0009,0x0081},
+ {0x0014,0x0018,0x001c,0x0020}, {0x004f,0x004f,0x008b,0x008b}, {0x00c7,0x00c7,0x000d,0x00c1}, {0x00c9,0x008d,0x0105,0x0051},
+ {0x0109,0x0145,0x0024,0x0028}, {0x0093,0x0093,0x00cf,0x00cf}, {0x0103,0x0103,0x0013,0x0013}, {0x0030,0x0044,0x0058,0x00a4},
+ {0x0034,0x0038,0x003c,0x0040}, {0x0057,0x0057,0x014b,0x014b}, {0x0187,0x0187,0x010f,0x010f}, {0x0097,0x0097,0x005b,0x005b},
+ {0x00d3,0x00d3,0x0141,0x0189}, {0x0048,0x004c,0x0050,0x0054}, {0x0015,0x01c5,0x014d,0x0205}, {0x0061,0x0111,0x00d5,0x0099},
+ {0x005d,0x0181,0x00a1,0x0209}, {0x018d,0x01c9,0x0151,0x0065}, {0x005c,0x0068,0x007c,0x0090}, {0x0245,0x009d,0x0060,0x0064},
+ {0x001b,0x001b,0x0117,0x0117}, {0x00db,0x00db,0x00e3,0x00e3}, {0x006c,0x0070,0x0074,0x0078}, {0x01c3,0x01c3,0x00a7,0x00a7},
+ {0x020f,0x020f,0x0193,0x0193}, {0x01cf,0x01cf,0x0203,0x0203}, {0x006b,0x006b,0x011b,0x011b}, {0x0080,0x0084,0x0088,0x008c},
+ {0x024b,0x024b,0x0157,0x0157}, {0x0023,0x0023,0x001f,0x001f}, {0x00df,0x00df,0x00ab,0x00ab}, {0x00e7,0x00e7,0x0123,0x0123},
+ {0x0094,0x0098,0x009c,0x00a0}, {0x0287,0x0287,0x011f,0x011f}, {0x015b,0x015b,0x0197,0x0197}, {0x0213,0x0213,0x01d3,0x01d3},
+ {0x024f,0x024f,0x006f,0x006f}, {0x00a8,0x00bc,0x00d0,0x00f4}, {0x00ac,0x00b0,0x00b4,0x00b8}, {0x0217,0x0217,0x0027,0x0027},
+ {0x0163,0x0163,0x00e9,0x0289}, {0x0241,0x00ad,0x0125,0x0199}, {0x0071,0x0251,0x01a1,0x02c5}, {0x00c0,0x00c4,0x00c8,0x00cc},
+ {0x0165,0x0129,0x01d5,0x015d}, {0x02c9,0x0305,0x00b1,0x00ed}, {0x028d,0x0255,0x01d9,0x01e1}, {0x012d,0x0281,0x019d,0x00f1},
+ {0x00d4,0x00d8,0x00dc,0x00e0}, {0x0029,0x0169,0x0291,0x0219}, {0x0309,0x01a5,0x01e5,0x02d1}, {0x002d,0x0259,0x02cd,0x0295},
+ {0x00e4,0x00e8,0x00ec,0x00f0}, {0x0223,0x0223,0x021f,0x021f}, {0x0173,0x0173,0x030f,0x030f}, {0x016f,0x016f,0x01df,0x01df},
+ {0x0133,0x0133,0x01af,0x01af}, {0x00f8,0x010c,0x0120,0x0134}, {0x00fc,0x0100,0x0104,0x0108}, {0x01ab,0x01ab,0x0313,0x0313},
+ {0x025f,0x025f,0x02d7,0x02d7}, {0x02c3,0x02c3,0x01b3,0x01b3}, {0x029b,0x029b,0x0033,0x0033}, {0x0110,0x0114,0x0118,0x011c},
+ {0x01eb,0x01eb,0x0317,0x0317}, {0x029f,0x029f,0x0227,0x0227}, {0x0303,0x0303,0x01ef,0x01ef}, {0x0263,0x0263,0x0267,0x0267},
+ {0x0124,0x0128,0x012c,0x0130}, {0x022b,0x022b,0x02df,0x02df}, {0x01f3,0x01f3,0x02db,0x02db}, {0x02e3,0x02e3,0x022f,0x022f},
+ {0x031f,0x031f,0x031b,0x031b}, {0x0138,0x013c,0x0140,0x0144}, {0x02a1,0x0269,0x0321,0x02a5}, {0x02e5,0x0325,0x02e9,0x0271},
+ {0x02a9,0x026d,0x0231,0x02ad}, {0x02b1,0x02f1,0x0148,0x014c}, {0x032b,0x032b,0x02ef,0x02ef}, {0x032f,0x032f,0x0333,0x0333}
+};
+
+const USHORT HuffmanCodeBook_10[82][4] =
+{
+ {0x0004,0x000c,0x0020,0x004c}, {0x0045,0x0085,0x0049,0x0008}, {0x008b,0x008b,0x0007,0x0007}, {0x0010,0x0014,0x0018,0x001c},
+ {0x0043,0x0043,0x00c7,0x00c7}, {0x008f,0x008f,0x004f,0x004f}, {0x00cb,0x00cb,0x00cf,0x00cf}, {0x0009,0x0081,0x0109,0x0091},
+ {0x0024,0x0028,0x002c,0x0038}, {0x0105,0x0051,0x0001,0x00d1}, {0x010d,0x000d,0x00c1,0x0111}, {0x0149,0x0095,0x0030,0x0034},
+ {0x0147,0x0147,0x0057,0x0057}, {0x00d7,0x00d7,0x014f,0x014f}, {0x003c,0x0040,0x0044,0x0048}, {0x0117,0x0117,0x0153,0x0153},
+ {0x009b,0x009b,0x018b,0x018b}, {0x00db,0x00db,0x0013,0x0013}, {0x005b,0x005b,0x0103,0x0103}, {0x0050,0x0064,0x0078,0x00c0},
+ {0x0054,0x0058,0x005c,0x0060}, {0x0187,0x0187,0x018f,0x018f}, {0x0157,0x0157,0x011b,0x011b}, {0x0193,0x0193,0x0159,0x009d},
+ {0x01cd,0x01c9,0x0195,0x00a1}, {0x0068,0x006c,0x0070,0x0074}, {0x00dd,0x0015,0x005d,0x0141}, {0x0061,0x01c5,0x00e1,0x011d},
+ {0x01d1,0x0209,0x0199,0x015d}, {0x0205,0x020d,0x0121,0x0211}, {0x007c,0x0084,0x0098,0x00ac}, {0x01d5,0x0161,0x0215,0x0080},
+ {0x019f,0x019f,0x01db,0x01db}, {0x0088,0x008c,0x0090,0x0094}, {0x00a7,0x00a7,0x001b,0x001b}, {0x021b,0x021b,0x00e7,0x00e7},
+ {0x024f,0x024f,0x0067,0x0067}, {0x024b,0x024b,0x0183,0x0183}, {0x009c,0x00a0,0x00a4,0x00a8}, {0x01a3,0x01a3,0x0127,0x0127},
+ {0x0253,0x0253,0x00ab,0x00ab}, {0x0247,0x0247,0x01df,0x01df}, {0x01e3,0x01e3,0x0167,0x0167}, {0x00b0,0x00b4,0x00b8,0x00bc},
+ {0x021f,0x021f,0x00eb,0x00eb}, {0x0257,0x0257,0x012b,0x012b}, {0x028b,0x028b,0x006b,0x006b}, {0x028f,0x028f,0x01a7,0x01a7},
+ {0x00c4,0x00d8,0x00ec,0x0100}, {0x00c8,0x00cc,0x00d0,0x00d4}, {0x025b,0x025b,0x0023,0x0023}, {0x0293,0x0293,0x001f,0x001f},
+ {0x00af,0x00af,0x025d,0x00ed}, {0x01a9,0x0285,0x006d,0x01e5}, {0x00dc,0x00e0,0x00e4,0x00e8}, {0x01c1,0x0221,0x0169,0x02cd},
+ {0x0295,0x0261,0x016d,0x0201}, {0x012d,0x02c9,0x029d,0x0299}, {0x01e9,0x02d1,0x02c5,0x00b1}, {0x00f0,0x00f4,0x00f8,0x00fc},
+ {0x0225,0x00f1,0x01ad,0x02d5}, {0x0131,0x01ed,0x0171,0x030d}, {0x02d9,0x0025,0x0229,0x0029}, {0x0071,0x0241,0x0311,0x0265},
+ {0x0104,0x010c,0x0120,0x0134}, {0x01b1,0x0309,0x02a1,0x0108}, {0x02a7,0x02a7,0x0307,0x0307}, {0x0110,0x0114,0x0118,0x011c},
+ {0x022f,0x022f,0x01f3,0x01f3}, {0x02df,0x02df,0x0317,0x0317}, {0x031b,0x031b,0x026b,0x026b}, {0x02e3,0x02e3,0x0233,0x0233},
+ {0x0124,0x0128,0x012c,0x0130}, {0x0283,0x0283,0x031f,0x031f}, {0x002f,0x002f,0x02ab,0x02ab}, {0x026f,0x026f,0x02af,0x02af},
+ {0x02c3,0x02c3,0x02ef,0x02ef}, {0x0138,0x013c,0x0140,0x0144}, {0x02e7,0x02e7,0x02eb,0x02eb}, {0x0033,0x0033,0x0323,0x0323},
+ {0x0271,0x0329,0x0325,0x032d}, {0x02f1,0x0301,0x02b1,0x0331}
+};
+
+const USHORT HuffmanCodeBook_11[152][4] =
+{
+ {0x0004,0x0010,0x0038,0x008c}, {0x0001,0x0085,0x0008,0x000c}, {0x0843,0x0843,0x0007,0x0007}, {0x0083,0x0083,0x008b,0x008b},
+ {0x0014,0x0018,0x001c,0x0024}, {0x0107,0x0107,0x010b,0x010b}, {0x0185,0x008d,0x010d,0x0009}, {0x0189,0x0101,0x018d,0x0020},
+ {0x0093,0x0093,0x0207,0x0207}, {0x0028,0x002c,0x0030,0x0034}, {0x0113,0x0113,0x020b,0x020b}, {0x0193,0x0193,0x020f,0x020f},
+ {0x000f,0x000f,0x0183,0x0183}, {0x0097,0x0097,0x0117,0x0117}, {0x003c,0x0050,0x0064,0x0078}, {0x0040,0x0044,0x0048,0x004c},
+ {0x028b,0x028b,0x0213,0x0213}, {0x0287,0x0287,0x0197,0x0197}, {0x028f,0x028f,0x0217,0x0217}, {0x0291,0x0119,0x0309,0x0099},
+ {0x0054,0x0058,0x005c,0x0060}, {0x0199,0x030d,0x0305,0x0811}, {0x080d,0x02c1,0x01c1,0x0241}, {0x0219,0x0341,0x0011,0x0311},
+ {0x0201,0x0809,0x0295,0x0815}, {0x0068,0x006c,0x0070,0x0074}, {0x03c1,0x0141,0x0441,0x0389}, {0x011d,0x038d,0x0299,0x0315},
+ {0x0819,0x0541,0x019d,0x009d}, {0x04c1,0x081d,0x0805,0x0385}, {0x007c,0x0080,0x0084,0x0088}, {0x0391,0x05c1,0x021d,0x0641},
+ {0x0821,0x00c1,0x0319,0x0825}, {0x0409,0x0395,0x0829,0x06c1}, {0x01a1,0x0121,0x040d,0x0015}, {0x0090,0x00c8,0x011c,0x0170},
+ {0x0094,0x0098,0x00a0,0x00b4}, {0x0741,0x082d,0x029d,0x0411}, {0x0399,0x031d,0x0281,0x009c}, {0x0223,0x0223,0x07c3,0x07c3},
+ {0x00a4,0x00a8,0x00ac,0x00b0}, {0x0833,0x0833,0x0407,0x0407}, {0x00a3,0x00a3,0x083b,0x083b}, {0x0417,0x0417,0x0837,0x0837},
+ {0x048f,0x048f,0x02a3,0x02a3}, {0x00b8,0x00bc,0x00c0,0x00c4}, {0x039f,0x039f,0x048b,0x048b}, {0x0323,0x0323,0x0127,0x0127},
+ {0x01a7,0x01a7,0x083f,0x083f}, {0x0493,0x0493,0x041b,0x041b}, {0x00cc,0x00e0,0x00f4,0x0108}, {0x00d0,0x00d4,0x00d8,0x00dc},
+ {0x001b,0x001b,0x0227,0x0227}, {0x0497,0x0497,0x03a3,0x03a3}, {0x041f,0x041f,0x0487,0x0487}, {0x01ab,0x01ab,0x0303,0x0303},
+ {0x00e4,0x00e8,0x00ec,0x00f0}, {0x012b,0x012b,0x00a7,0x00a7}, {0x02a7,0x02a7,0x0513,0x0513}, {0x050b,0x050b,0x0327,0x0327},
+ {0x050f,0x050f,0x049b,0x049b}, {0x00f8,0x00fc,0x0100,0x0104}, {0x022b,0x022b,0x0423,0x0423}, {0x02ab,0x02ab,0x03a7,0x03a7},
+ {0x01af,0x01af,0x0507,0x0507}, {0x001f,0x001f,0x032b,0x032b}, {0x010c,0x0110,0x0114,0x0118}, {0x049f,0x049f,0x058f,0x058f},
+ {0x0517,0x0517,0x00ab,0x00ab}, {0x0593,0x0593,0x012f,0x012f}, {0x0137,0x0137,0x051b,0x051b}, {0x0120,0x0134,0x0148,0x015c},
+ {0x0124,0x0128,0x012c,0x0130}, {0x01b7,0x01b7,0x058b,0x058b}, {0x0043,0x0043,0x0597,0x0597}, {0x02af,0x02af,0x022d,0x0425},
+ {0x051d,0x04a1,0x0801,0x0691}, {0x0138,0x013c,0x0140,0x0144}, {0x0381,0x068d,0x032d,0x00b5}, {0x0235,0x01b1,0x0689,0x02b5},
+ {0x0521,0x0599,0x0429,0x03a9}, {0x0139,0x0231,0x0585,0x0611}, {0x014c,0x0150,0x0154,0x0158}, {0x00ad,0x060d,0x0685,0x0131},
+ {0x059d,0x070d,0x0615,0x0695}, {0x0239,0x0711,0x03ad,0x01b9}, {0x02b1,0x0335,0x0331,0x0021}, {0x0160,0x0164,0x0168,0x016c},
+ {0x042d,0x0609,0x04a5,0x02b9}, {0x0699,0x0529,0x013d,0x05a1}, {0x0525,0x0339,0x04a9,0x0715}, {0x04ad,0x00b9,0x0709,0x0619},
+ {0x0174,0x0188,0x019c,0x01cc}, {0x0178,0x017c,0x0180,0x0184}, {0x0605,0x0435,0x0401,0x03b5}, {0x061d,0x03b1,0x069d,0x01bd},
+ {0x00b1,0x0719,0x0789,0x02bd}, {0x023d,0x0705,0x05a5,0x0791}, {0x018c,0x0190,0x0194,0x0198}, {0x03b9,0x06a1,0x04b5,0x0621},
+ {0x0795,0x078d,0x05a9,0x052d}, {0x0431,0x033d,0x03bd,0x0721}, {0x00bd,0x071d,0x0025,0x0481}, {0x01a0,0x01a4,0x01a8,0x01b8},
+ {0x06a5,0x0625,0x04b1,0x0439}, {0x06a9,0x04b9,0x0531,0x0799}, {0x079d,0x01ac,0x01b0,0x01b4}, {0x0727,0x0727,0x043f,0x043f},
+ {0x05af,0x05af,0x072f,0x072f}, {0x0787,0x0787,0x062b,0x062b}, {0x01bc,0x01c0,0x01c4,0x01c8}, {0x072b,0x072b,0x05b7,0x05b7},
+ {0x0537,0x0537,0x06af,0x06af}, {0x062f,0x062f,0x07a3,0x07a3}, {0x05bb,0x05bb,0x0637,0x0637}, {0x01d0,0x01e4,0x01f8,0x020c},
+ {0x01d4,0x01d8,0x01dc,0x01e0}, {0x06b3,0x06b3,0x04bf,0x04bf}, {0x053b,0x053b,0x002b,0x002b}, {0x05b3,0x05b3,0x07a7,0x07a7},
+ {0x0503,0x0503,0x0633,0x0633}, {0x01e8,0x01ec,0x01f0,0x01f4}, {0x002f,0x002f,0x0733,0x0733}, {0x07ab,0x07ab,0x06b7,0x06b7},
+ {0x0683,0x0683,0x063b,0x063b}, {0x053f,0x053f,0x05bf,0x05bf}, {0x01fc,0x0200,0x0204,0x0208}, {0x07af,0x07af,0x06bb,0x06bb},
+ {0x0037,0x0037,0x0583,0x0583}, {0x0737,0x0737,0x063f,0x063f}, {0x06bf,0x06bf,0x07b3,0x07b3}, {0x0210,0x0214,0x0218,0x021c},
+ {0x003b,0x003b,0x073b,0x073b}, {0x07b7,0x07b7,0x0033,0x0033}, {0x07bb,0x07bb,0x0701,0x0601}, {0x073d,0x003d,0x0781,0x07bd},
+ {0x0118,0x0117,0x0100,0x0109}, {0x05a5,0x05a1,0x05b7,0x0513}, {0x08f9,0x08ff,0x0821,0x08ff}, {0x084f,0x08ff,0x08bc,0x08ff},
+ {0x0815,0x08ff,0x0837,0x08ff}, {0x080d,0x08ff,0x085f,0x08ff}, {0x084a,0x08ff,0x087d,0x08ff}, {0x08ff,0x08ff,0x08a8,0x08ff},
+ {0x0815,0x08ff,0x083f,0x08ff}, {0x0830,0x08ff,0x0894,0x08ff}, {0x08d4,0x08ff,0x0825,0x08ff}, {0x08ef,0x08ff,0x083f,0x08ff},
+ {0x0809,0x08ff,0x08fc,0x08ff}, {0x0842,0x08ff,0x08b3,0x08ff}, {0x070d,0x07a9,0x060e,0x06e2}, {0x06c7,0x06d0,0x04b2,0x0407}
+};
+
+
+const USHORT HuffmanCodeBook_SCL[65][4] =
+{
+ {0x00f3,0x00f3,0x0004,0x0008}, {0x00ef,0x00ef,0x00f5,0x00e9}, {0x00f9,0x000c,0x0010,0x0014}, {0x00e7,0x00e7,0x00ff,0x00ff},
+ {0x00e1,0x0101,0x00dd,0x0105}, {0x0018,0x001c,0x0020,0x0028}, {0x010b,0x010b,0x00db,0x00db}, {0x010f,0x010f,0x00d5,0x0111},
+ {0x00d1,0x0115,0x00cd,0x0024}, {0x011b,0x011b,0x00cb,0x00cb}, {0x002c,0x0030,0x0034,0x0040}, {0x00c7,0x00c7,0x011f,0x011f},
+ {0x0121,0x00c1,0x0125,0x00bd}, {0x0129,0x00b9,0x0038,0x003c}, {0x0133,0x0133,0x012f,0x012f}, {0x0137,0x0137,0x013b,0x013b},
+ {0x0044,0x0048,0x004c,0x0058}, {0x00b7,0x00b7,0x00af,0x00af}, {0x00b1,0x013d,0x00a9,0x00a5}, {0x0141,0x00a1,0x0050,0x0054},
+ {0x0147,0x0147,0x009f,0x009f}, {0x014b,0x014b,0x009b,0x009b}, {0x005c,0x0060,0x0064,0x0070}, {0x014f,0x014f,0x0095,0x008d},
+ {0x0155,0x0085,0x0091,0x0089}, {0x0151,0x0081,0x0068,0x006c}, {0x015f,0x015f,0x0167,0x0167}, {0x007b,0x007b,0x007f,0x007f},
+ {0x0074,0x0078,0x0080,0x00b0}, {0x0159,0x0075,0x0069,0x006d}, {0x0071,0x0061,0x0161,0x007c}, {0x0067,0x0067,0x005b,0x005b},
+ {0x0084,0x0088,0x008c,0x009c}, {0x005f,0x005f,0x0169,0x0055}, {0x004d,0x000d,0x0005,0x0009}, {0x0001,0x0090,0x0094,0x0098},
+ {0x018b,0x018b,0x018f,0x018f}, {0x0193,0x0193,0x0197,0x0197}, {0x019b,0x019b,0x01d7,0x01d7}, {0x00a0,0x00a4,0x00a8,0x00ac},
+ {0x0187,0x0187,0x016f,0x016f}, {0x0173,0x0173,0x0177,0x0177}, {0x017b,0x017b,0x017f,0x017f}, {0x0183,0x0183,0x01a3,0x01a3},
+ {0x00b4,0x00c8,0x00dc,0x00f0}, {0x00b8,0x00bc,0x00c0,0x00c4}, {0x01bf,0x01bf,0x01c3,0x01c3}, {0x01c7,0x01c7,0x01cb,0x01cb},
+ {0x01cf,0x01cf,0x01d3,0x01d3}, {0x01bb,0x01bb,0x01a7,0x01a7}, {0x00cc,0x00d0,0x00d4,0x00d8}, {0x01ab,0x01ab,0x01af,0x01af},
+ {0x01b3,0x01b3,0x01b7,0x01b7}, {0x01db,0x01db,0x001b,0x001b}, {0x0023,0x0023,0x0027,0x0027}, {0x00e0,0x00e4,0x00e8,0x00ec},
+ {0x002b,0x002b,0x0017,0x0017}, {0x019f,0x019f,0x01e3,0x01e3}, {0x01df,0x01df,0x0013,0x0013}, {0x001f,0x001f,0x003f,0x003f},
+ {0x00f4,0x00f8,0x00fc,0x0100}, {0x0043,0x0043,0x004b,0x004b}, {0x0053,0x0053,0x0047,0x0047}, {0x002f,0x002f,0x0033,0x0033},
+ {0x003b,0x003b,0x0037,0x0037}
+};
+
+
+
+/* .CodeBook = HuffmanCodeBook_x, .Dimension = 4, .numBits = 2, .Offset = 0 */
+const CodeBookDescription AACcodeBookDescriptionTable[13] = {
+ { NULL, 0, 0, 0 },
+ { HuffmanCodeBook_1, 4, 2, 1 },
+ { HuffmanCodeBook_2, 4, 2, 1 },
+ { HuffmanCodeBook_3, 4, 2, 0 },
+ { HuffmanCodeBook_4, 4, 2, 0 },
+ { HuffmanCodeBook_5, 2, 4, 4 },
+ { HuffmanCodeBook_6, 2, 4, 4 },
+ { HuffmanCodeBook_7, 2, 4, 0 },
+ { HuffmanCodeBook_8, 2, 4, 0 },
+ { HuffmanCodeBook_9, 2, 4, 0 },
+ { HuffmanCodeBook_10, 2, 4, 0 },
+ { HuffmanCodeBook_11, 2, 5, 0 },
+ { HuffmanCodeBook_SCL, 1, 8, 60 }
+};
+
+const CodeBookDescription AACcodeBookDescriptionSCL = { HuffmanCodeBook_SCL, 1, 8, 60 };
+
+
+
+/* ********************************************************************************************* */
+/* Table: HuffTree41 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 1). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 4 */
+/* --------------------------------------------------------------------------------------------- */
+/* HuffTree */
+const UINT aHuffTree41[80] = {0x4a0001,0x026002,0x013003,0x021004,0x01c005,0x00b006,0x010007,0x019008,
+ 0x00900e,0x00a03a,0x400528,0x00c037,0x00d03b,0x454404,0x00f04c,0x448408,
+ 0x017011,0x01202e,0x42c40c,0x034014,0x01502c,0x016049,0x410470,0x01804e,
+ 0x414424,0x03201a,0x02001b,0x520418,0x02f01d,0x02a01e,0x01f04d,0x41c474,
+ 0x540420,0x022024,0x04a023,0x428510,0x025029,0x430508,0x02703c,0x028047,
+ 0x50c434,0x438478,0x04802b,0x46443c,0x02d03e,0x4404b0,0x44451c,0x03003f,
+ 0x03104b,0x52444c,0x033039,0x4f0450,0x035041,0x036046,0x4e8458,0x04f038,
+ 0x45c53c,0x4604e0,0x4f8468,0x46c4d4,0x04503d,0x4ac47c,0x518480,0x043040,
+ 0x4844dc,0x042044,0x4884a8,0x4bc48c,0x530490,0x4a4494,0x4984b8,0x49c4c4,
+ 0x5044b4,0x5004c0,0x4d04c8,0x4f44cc,0x4d8538,0x4ec4e4,0x52c4fc,0x514534};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree42 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 2). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 4 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree42[80] = {0x026001,0x014002,0x009003,0x010004,0x01d005,0x00600d,0x007018,0x450008,
+ 0x4e0400,0x02e00a,0x03900b,0x03d00c,0x43c404,0x01b00e,0x00f04f,0x4d8408,
+ 0x023011,0x01203b,0x01a013,0x41440c,0x015020,0x016040,0x025017,0x500410,
+ 0x038019,0x540418,0x41c444,0x02d01c,0x420520,0x01e042,0x03701f,0x4244cc,
+ 0x02a021,0x02204c,0x478428,0x024031,0x42c4dc,0x4304e8,0x027033,0x4a0028,
+ 0x50c029,0x4344a4,0x02c02b,0x470438,0x4404c8,0x4f8448,0x04902f,0x04b030,
+ 0x44c484,0x524032,0x4ec454,0x03e034,0x035046,0x4c4036,0x488458,0x4d445c,
+ 0x460468,0x04e03a,0x51c464,0x03c04a,0x46c514,0x47453c,0x04503f,0x47c4ac,
+ 0x044041,0x510480,0x04304d,0x4e448c,0x490518,0x49449c,0x048047,0x4c0498,
+ 0x4b84a8,0x4b0508,0x4fc4b4,0x4bc504,0x5304d0,0x5344f0,0x4f452c,0x528538};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree43 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 3). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 4 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree43[80] = {0x400001,0x002004,0x00300a,0x46c404,0x00b005,0x00600d,0x034007,0x037008,
+ 0x494009,0x4d8408,0x42440c,0x00c01b,0x490410,0x00e016,0x00f011,0x010014,
+ 0x4144fc,0x01201d,0x020013,0x508418,0x4c0015,0x41c440,0x022017,0x018026,
+ 0x019035,0x03801a,0x420444,0x01c01f,0x430428,0x02101e,0x44842c,0x478434,
+ 0x4b4438,0x45443c,0x02c023,0x039024,0x02503f,0x48844c,0x030027,0x02e028,
+ 0x032029,0x02a041,0x4d402b,0x4504f0,0x04302d,0x4584a8,0x02f03b,0x46045c,
+ 0x03103d,0x464046,0x033044,0x46853c,0x47049c,0x045036,0x4744dc,0x4a047c,
+ 0x500480,0x4ac03a,0x4b8484,0x03c04e,0x48c524,0x03e040,0x4984e8,0x50c4a4,
+ 0x4b0530,0x042047,0x4bc04b,0x4e44c4,0x5184c8,0x52c4cc,0x5204d0,0x04d048,
+ 0x04a049,0x4e004c,0x51c4ec,0x4f4510,0x5284f8,0x50404f,0x514538,0x540534};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree44 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 4). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 4 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree44[80] = {0x001004,0x020002,0x036003,0x490400,0x005008,0x010006,0x01f007,0x404428,
+ 0x00e009,0x01100a,0x00b018,0x01600c,0x03700d,0x408015,0x00f03e,0x40c424,
+ 0x410478,0x022012,0x038013,0x01e014,0x454414,0x448418,0x025017,0x47441c,
+ 0x030019,0x02601a,0x02d01b,0x01c034,0x01d029,0x4204f0,0x4dc42c,0x470430,
+ 0x02103c,0x4a0434,0x02302a,0x440024,0x4384a8,0x43c44c,0x02703a,0x02802c,
+ 0x444524,0x4504e0,0x02b03d,0x458480,0x45c4f4,0x04b02e,0x04f02f,0x460520,
+ 0x042031,0x048032,0x049033,0x514464,0x03504c,0x540468,0x47c46c,0x4844d8,
+ 0x039044,0x4884fc,0x03b045,0x48c53c,0x49449c,0x4b8498,0x03f046,0x041040,
+ 0x4c44a4,0x50c4ac,0x04a043,0x5184b0,0x4e44b4,0x4bc4ec,0x04e047,0x4c04e8,
+ 0x4c8510,0x4cc52c,0x4d0530,0x5044d4,0x53804d,0x5284f8,0x508500,0x51c534};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree21 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 5). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 2 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree21[80] = {0x450001,0x044002,0x042003,0x035004,0x026005,0x022006,0x013007,0x010008,
+ 0x00d009,0x01c00a,0x01f00b,0x01e00c,0x4a0400,0x01b00e,0x03200f,0x47e402,
+ 0x020011,0x01204d,0x40449c,0x017014,0x015019,0x01603f,0x406458,0x01804f,
+ 0x448408,0x04901a,0x40a45a,0x48c40c,0x01d031,0x40e48e,0x490410,0x492412,
+ 0x021030,0x480414,0x033023,0x02402e,0x02503e,0x416482,0x02a027,0x02802c,
+ 0x029040,0x418468,0x02b04a,0x41a486,0x02d048,0x41c484,0x04e02f,0x41e426,
+ 0x420434,0x42249e,0x424494,0x03d034,0x428470,0x039036,0x03703b,0x038041,
+ 0x42a476,0x03a04b,0x42c454,0x03c047,0x42e472,0x430478,0x43246e,0x496436,
+ 0x488438,0x43a466,0x046043,0x43c464,0x04504c,0x43e462,0x460440,0x44245e,
+ 0x45c444,0x46a446,0x44a456,0x47444c,0x45244e,0x46c47c,0x48a47a,0x49a498};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree22 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 6). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 2 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree22[80] = {0x03c001,0x02f002,0x020003,0x01c004,0x00f005,0x00c006,0x016007,0x04d008,
+ 0x00b009,0x01500a,0x400490,0x40e402,0x00d013,0x00e02a,0x40c404,0x019010,
+ 0x011041,0x038012,0x40a406,0x014037,0x40849c,0x4a0410,0x04a017,0x458018,
+ 0x412422,0x02801a,0x01b029,0x480414,0x02401d,0x01e02b,0x48a01f,0x416432,
+ 0x02d021,0x026022,0x023039,0x418468,0x025043,0x48641a,0x027040,0x41c488,
+ 0x41e48c,0x42045a,0x47c424,0x04c02c,0x46e426,0x03602e,0x428478,0x030033,
+ 0x43c031,0x04b032,0x42e42a,0x03403a,0x035048,0x42c442,0x470430,0x494434,
+ 0x43649a,0x45c438,0x04403b,0x43a454,0x04503d,0x03e03f,0x43e464,0x440460,
+ 0x484444,0x049042,0x446448,0x44a456,0x46644c,0x047046,0x44e452,0x450462,
+ 0x47445e,0x46a496,0x49846c,0x472476,0x47a482,0x04e04f,0x47e492,0x48e49e};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree23 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 7). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 2 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree23[63] = {0x400001,0x002003,0x410402,0x004007,0x412005,0x01c006,0x420404,0x00800b,
+ 0x01d009,0x00a01f,0x406026,0x00c012,0x00d00f,0x02700e,0x408440,0x010022,
+ 0x028011,0x45440a,0x013017,0x029014,0x024015,0x01602f,0x43c40c,0x02b018,
+ 0x019033,0x03201a,0x43e01b,0x47040e,0x422414,0x01e025,0x432416,0x020021,
+ 0x418442,0x41a452,0x036023,0x41c446,0x46441e,0x424430,0x426434,0x436428,
+ 0x44442a,0x02e02a,0x45642c,0x03002c,0x02d03b,0x46642e,0x43a438,0x460448,
+ 0x031037,0x47244a,0x45a44c,0x034039,0x038035,0x47844e,0x462450,0x474458,
+ 0x46a45c,0x03a03c,0x45e47a,0x476468,0x03d03e,0x47c46c,0x46e47e};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree24 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 8). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 2 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree24[63] = {0x001006,0x01d002,0x005003,0x424004,0x400420,0x414402,0x00700a,0x008020,
+ 0x00901f,0x404432,0x00b011,0x00c00e,0x00d032,0x406446,0x02300f,0x033010,
+ 0x458408,0x025012,0x013016,0x01402f,0x015038,0x46840a,0x028017,0x01801a,
+ 0x039019,0x40c47a,0x03e01b,0x03b01c,0x40e47e,0x41201e,0x422410,0x416434,
+ 0x02a021,0x02202b,0x418444,0x02c024,0x41a456,0x02d026,0x027034,0x46241c,
+ 0x029036,0x41e45c,0x426031,0x428430,0x45242a,0x03702e,0x42c464,0x03003c,
+ 0x47442e,0x436442,0x438454,0x43a448,0x03503a,0x43c466,0x43e03d,0x44a440,
+ 0x44c472,0x46044e,0x45a450,0x45e470,0x46a476,0x46c478,0x47c46e};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree25 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 9). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 2 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree25[168] = {0x400001,0x002003,0x41a402,0x004007,0x41c005,0x035006,0x434404,0x008010,
+ 0x00900c,0x04a00a,0x42000b,0x44e406,0x03600d,0x03800e,0x05a00f,0x408468,
+ 0x01101a,0x012016,0x039013,0x070014,0x46e015,0x40a440,0x03b017,0x01804d,
+ 0x01904f,0x4b840c,0x01b022,0x01c041,0x03f01d,0x01e020,0x01f05b,0x40e4ee,
+ 0x02107c,0x45c410,0x02302c,0x024028,0x053025,0x026045,0x02707d,0x412522,
+ 0x047029,0x05e02a,0x02b08a,0x526414,0x05602d,0x02e081,0x02f032,0x06e030,
+ 0x031080,0x416544,0x079033,0x034091,0x41852c,0x43641e,0x04b037,0x42246a,
+ 0x43c424,0x04c03a,0x426456,0x03c066,0x03d03e,0x482428,0x45842a,0x040072,
+ 0x42c4ba,0x050042,0x04305c,0x044074,0x42e4be,0x06a046,0x4dc430,0x075048,
+ 0x0490a3,0x44a432,0x450438,0x43a452,0x48443e,0x04e068,0x45a442,0x4d4444,
+ 0x051088,0x052087,0x44648c,0x077054,0x4da055,0x50a448,0x057060,0x06b058,
+ 0x05906d,0x44c4f6,0x46c454,0x45e474,0x06905d,0x460520,0x05f07e,0x462494,
+ 0x061063,0x07f062,0x464496,0x06408b,0x08d065,0x542466,0x067071,0x4d2470,
+ 0x4724ec,0x478476,0x53a47a,0x09b06c,0x47c4ac,0x4f847e,0x06f078,0x510480,
+ 0x48649e,0x4884a0,0x07307b,0x49c48a,0x4a648e,0x098076,0x4904c0,0x4924ea,
+ 0x4c8498,0x07a08e,0x51249a,0x4a24d6,0x5064a4,0x4f24a8,0x4aa4de,0x51e4ae,
+ 0x4b0538,0x082092,0x083085,0x08f084,0x5464b2,0x096086,0x4ce4b4,0x4d04b6,
+ 0x089090,0x4bc508,0x4c253e,0x08c0a4,0x5284c4,0x4e04c6,0x4ca4fa,0x5144cc,
+ 0x4f04d8,0x4e24fc,0x09309c,0x094099,0x095097,0x4e4516,0x4e652e,0x4e84fe,
+ 0x4f450c,0x09a09f,0x500502,0x50450e,0x09d0a0,0x09e0a5,0x518530,0x51a54a,
+ 0x0a70a1,0x0a20a6,0x51c534,0x53c524,0x54052a,0x548532,0x536550,0x54c54e};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree26 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 10). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 2 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree26[168] = {0x006001,0x002013,0x00300f,0x00400d,0x03b005,0x40046e,0x037007,0x00800a,
+ 0x009067,0x402420,0x05600b,0x00c057,0x434404,0x06600e,0x406470,0x03c010,
+ 0x059011,0x06f012,0x49e408,0x014019,0x03f015,0x016044,0x017042,0x079018,
+ 0x4b840a,0x01a01f,0x01b047,0x07c01c,0x08701d,0x06901e,0x44640c,0x020027,
+ 0x04b021,0x02204f,0x023025,0x02406b,0x40e4e0,0x081026,0x528410,0x02802c,
+ 0x06c029,0x08f02a,0x02b078,0x53a412,0x05202d,0x02e033,0x02f031,0x0300a2,
+ 0x4144ce,0x0a6032,0x416534,0x09a034,0x09f035,0x0360a7,0x54e418,0x03a038,
+ 0x436039,0x43841a,0x41c41e,0x42246a,0x05803d,0x03e068,0x424484,0x04005b,
+ 0x04107a,0x42645a,0x043093,0x4d2428,0x05e045,0x046072,0x42a45e,0x048060,
+ 0x073049,0x04a098,0x42c4c4,0x07504c,0x09504d,0x04e09c,0x51042e,0x063050,
+ 0x077051,0x43053c,0x053084,0x065054,0x4e4055,0x4fe432,0x43a454,0x43c46c,
+ 0x43e486,0x07005a,0x4a0440,0x07105c,0x05d07b,0x45c442,0x05f08a,0x476444,
+ 0x07f061,0x06206a,0x448506,0x06408e,0x52644a,0x54444c,0x45644e,0x452450,
+ 0x488458,0x4604ec,0x4624f6,0x50e464,0x08206d,0x0a406e,0x542466,0x4a2468,
+ 0x48a472,0x474089,0x4d8478,0x097074,0x47a508,0x08d076,0x47c4b6,0x51247e,
+ 0x4804fc,0x4bc482,0x48c4a4,0x48e4d4,0x07d07e,0x4904da,0x49208b,0x094080,
+ 0x49450c,0x4964e2,0x09d083,0x52a498,0x085091,0x0a5086,0x4cc49a,0x08808c,
+ 0x4ee49c,0x4a64ba,0x4a84c0,0x4c24aa,0x4ac4f0,0x4ae4d0,0x4ca4b0,0x0900a1,
+ 0x4b24ea,0x092099,0x4b4516,0x4d64be,0x4c650a,0x522096,0x4c8524,0x4dc4f2,
+ 0x4de4f4,0x4e6548,0x09e09b,0x5384e8,0x5204f8,0x4fa53e,0x50051a,0x0a30a0,
+ 0x502536,0x514504,0x51e518,0x54a51c,0x54052c,0x52e546,0x530532,0x54c550};
+
+/* ********************************************************************************************* */
+/* Table: HuffTree27 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the decode tree for spectral data (Codebook 11). */
+/* bit 23 and 11 not used */
+/* bit 22 and 10 determine end value */
+/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */
+/* --------------------------------------------------------------------------------------------- */
+/* input: codeword */
+/* --------------------------------------------------------------------------------------------- */
+/* output: index * 2 */
+/* --------------------------------------------------------------------------------------------- */
+const UINT aHuffTree27[288] = {0x00100d,0x002006,0x003004,0x400424,0x047005,0x402446,0x048007,0x00800a,
+ 0x00904c,0x44a404,0x07400b,0x00c0bb,0x466406,0x00e014,0x00f054,0x04e010,
+ 0x051011,0x0a9012,0x0130bc,0x408464,0x01501f,0x01601a,0x017059,0x0af018,
+ 0x0ca019,0x40a0e4,0x01b05e,0x01c084,0x0bf01d,0x05d01e,0x55a40c,0x020026,
+ 0x021066,0x043022,0x023062,0x02408d,0x025108,0x40e480,0x027030,0x02802c,
+ 0x02906b,0x02a0da,0x06502b,0x4105c8,0x0a402d,0x0ec02e,0x0dd02f,0x532412,
+ 0x06e031,0x032036,0x03303e,0x0fd034,0x0fc035,0x4145b0,0x03703a,0x038117,
+ 0x10d039,0x5ba416,0x10f03b,0x03c041,0x5fa03d,0x41c418,0x10403f,0x04011d,
+ 0x41a5f4,0x11c042,0x41e61c,0x087044,0x0f5045,0x0d9046,0x4204a2,0x640422,
+ 0x04904a,0x426448,0x04b073,0x428468,0x46c04d,0x48a42a,0x04f077,0x076050,
+ 0x42c4b0,0x0520a7,0x096053,0x42e4a8,0x05507d,0x07a056,0x0d4057,0x0df058,
+ 0x442430,0x05a081,0x05b09b,0x05c0e2,0x5b8432,0x4fe434,0x05f09e,0x0e6060,
+ 0x0610d6,0x57c436,0x0cc063,0x112064,0x4384a0,0x43a5ca,0x067089,0x0680b7,
+ 0x0690a2,0x0a106a,0x43c59c,0x09206c,0x06d0ba,0x60643e,0x0d106f,0x0700ee,
+ 0x0de071,0x10b072,0x44056c,0x46a444,0x075094,0x48c44c,0x44e490,0x095078,
+ 0x0ab079,0x4504ce,0x07b097,0x11e07c,0x630452,0x0ac07e,0x07f099,0x080106,
+ 0x4544b8,0x0820b1,0x0830e5,0x4fc456,0x0b3085,0x08609d,0x45853e,0x0880c2,
+ 0x5c045a,0x08a08f,0x08b0ce,0x08c0f7,0x58645c,0x11108e,0x45e5c4,0x0c4090,
+ 0x10a091,0x4604e4,0x0d0093,0x462608,0x48e46e,0x4704b2,0x4d2472,0x0980bd,
+ 0x4f2474,0x0e309a,0x4764aa,0x0be09c,0x47851a,0x47a4de,0x09f0b5,0x0a00c1,
+ 0x50047c,0x57847e,0x0a30c3,0x504482,0x0e90a5,0x0a6100,0x4c8484,0x0a811f,
+ 0x48662a,0x0c70aa,0x488494,0x4924d0,0x0ad0c8,0x0ae0d8,0x496636,0x10e0b0,
+ 0x4f8498,0x0f30b2,0x49a4dc,0x0f20b4,0x53c49c,0x0b60cb,0x49e57a,0x0b80e0,
+ 0x0b9109,0x5e44a4,0x5484a6,0x4ac4ae,0x4b44ca,0x4d64b6,0x4ba5da,0x0c60c0,
+ 0x4bc51e,0x4be556,0x6204c0,0x4c24c4,0x0f80c5,0x5664c6,0x4cc53a,0x4d462c,
+ 0x0f10c9,0x4d8552,0x4da4fa,0x5be4e0,0x0cd0ff,0x5244e2,0x0cf0e8,0x4e6568,
+ 0x59a4e8,0x0f90d2,0x1010d3,0x5ac4ea,0x0d50d7,0x4ec634,0x4ee560,0x4f44f0,
+ 0x4f6638,0x502522,0x0db0dc,0x5065a6,0x508604,0x60050a,0x50c0fb,0x63250e,
+ 0x1130e1,0x5a4510,0x5125fc,0x516514,0x51863e,0x51c536,0x0e70f4,0x55c520,
+ 0x602526,0x0eb0ea,0x5cc528,0x5ea52a,0x1140ed,0x60c52c,0x1020ef,0x0f0119,
+ 0x58e52e,0x530622,0x558534,0x53861e,0x55e540,0x5800f6,0x57e542,0x5445e6,
+ 0x5465e8,0x0fa115,0x54c54a,0x54e60e,0x5ae550,0x1160fe,0x5f0554,0x564562,
+ 0x56a58a,0x56e5ee,0x10310c,0x5705d0,0x107105,0x5725d4,0x57463a,0x5765b4,
+ 0x5825bc,0x5845e2,0x5885de,0x58c592,0x5ce590,0x5945f6,0x63c596,0x11b110,
+ 0x5d8598,0x5c259e,0x5e05a0,0x5a25c6,0x5a860a,0x5aa5ec,0x5b2610,0x11a118,
+ 0x6185b6,0x5f25d2,0x5d6616,0x5dc5f8,0x61a5fe,0x612614,0x62e624,0x626628};
+
+/* get starting addresses of huffman tables into an array [convert codebook into starting address] */
+ /* cb tree */
+const UINT *aHuffTable[MAX_CB] = {aHuffTree41, /* 0 - */ /* use tree 1 as dummy here */
+ aHuffTree41, /* 1 1 */
+ aHuffTree42, /* 2 2 */
+ aHuffTree43, /* 3 3 */
+ aHuffTree44, /* 4 4 */
+ aHuffTree21, /* 5 5 */
+ aHuffTree22, /* 6 6 */
+ aHuffTree23, /* 7 7 */
+ aHuffTree24, /* 8 8 */
+ aHuffTree25, /* 9 9 */
+ aHuffTree26, /* 10 10 */
+ aHuffTree27, /* 11 11 */
+ aHuffTree41, /* 12 - */ /* use tree 1 as dummy here */
+ aHuffTree41, /* 13 - */ /* use tree 1 as dummy here */
+ aHuffTree41, /* 14 - */ /* use tree 1 as dummy here */
+ aHuffTree41, /* 15 - */ /* use tree 1 as dummy here */
+ aHuffTree27, /* 16 11 */
+ aHuffTree27, /* 17 11 */
+ aHuffTree27, /* 18 11 */
+ aHuffTree27, /* 19 11 */
+ aHuffTree27, /* 20 11 */
+ aHuffTree27, /* 21 11 */
+ aHuffTree27, /* 22 11 */
+ aHuffTree27, /* 23 11 */
+ aHuffTree27, /* 24 11 */
+ aHuffTree27, /* 25 11 */
+ aHuffTree27, /* 26 11 */
+ aHuffTree27, /* 27 11 */
+ aHuffTree27, /* 28 11 */
+ aHuffTree27, /* 29 11 */
+ aHuffTree27, /* 30 11 */
+ aHuffTree27}; /* 31 11 */
+
+/*---------------------------------------------------------------------------------------------
+ data-description:
+ The following tables contain the quantized values. Two or four of the quantized values are
+ indexed by the result of the decoding in the decoding tree (see tables above).
+ -------------------------------------------------------------------------------------------- */
+
+/* ********************************************************************************************* */
+/* Table: ValTab41 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the quantized values for codebooks 1-2. */
+/* --------------------------------------------------------------------------------------------- */
+const SCHAR aValTab41[324]={-1,-1,-1,-1,-1,-1,-1,0,-1,-1,-1,1,-1,-1,0,-1,
+ -1,-1,0,0,-1,-1,0,1,-1,-1,1,-1,-1,-1,1,0,
+ -1,-1,1,1,-1,0,-1,-1,-1,0,-1,0,-1,0,-1,1,
+ -1,0,0,-1,-1,0,0,0,-1,0,0,1,-1,0,1,-1,
+ -1,0,1,0,-1,0,1,1,-1,1,-1,-1,-1,1,-1,0,
+ -1,1,-1,1,-1,1,0,-1,-1,1,0,0,-1,1,0,1,
+ -1,1,1,-1,-1,1,1,0,-1,1,1,1,0,-1,-1,-1,
+ 0,-1,-1,0,0,-1,-1,1,0,-1,0,-1,0,-1,0,0,
+ 0,-1,0,1,0,-1,1,-1,0,-1,1,0,0,-1,1,1,
+ 0,0,-1,-1,0,0,-1,0,0,0,-1,1,0,0,0,-1,
+ 0,0,0,0,0,0,0,1,0,0,1,-1,0,0,1,0,
+ 0,0,1,1,0,1,-1,-1,0,1,-1,0,0,1,-1,1,
+ 0,1,0,-1,0,1,0,0,0,1,0,1,0,1,1,-1,
+ 0,1,1,0,0,1,1,1,1,-1,-1,-1,1,-1,-1,0,
+ 1,-1,-1,1,1,-1,0,-1,1,-1,0,0,1,-1,0,1,
+ 1,-1,1,-1,1,-1,1,0,1,-1,1,1,1,0,-1,-1,
+ 1,0,-1,0,1,0,-1,1,1,0,0,-1,1,0,0,0,
+ 1,0,0,1,1,0,1,-1,1,0,1,0,1,0,1,1,
+ 1,1,-1,-1,1,1,-1,0,1,1,-1,1,1,1,0,-1,
+ 1,1,0,0,1,1,0,1,1,1,1,-1,1,1,1,0,
+ 1,1,1,1};
+
+/* ********************************************************************************************* */
+/* Table: ValTab42 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the quantized values for codebooks 3-4. */
+/* --------------------------------------------------------------------------------------------- */
+const SCHAR aValTab42[324]={0,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0,
+ 0,0,1,1,0,0,1,2,0,0,2,0,0,0,2,1,
+ 0,0,2,2,0,1,0,0,0,1,0,1,0,1,0,2,
+ 0,1,1,0,0,1,1,1,0,1,1,2,0,1,2,0,
+ 0,1,2,1,0,1,2,2,0,2,0,0,0,2,0,1,
+ 0,2,0,2,0,2,1,0,0,2,1,1,0,2,1,2,
+ 0,2,2,0,0,2,2,1,0,2,2,2,1,0,0,0,
+ 1,0,0,1,1,0,0,2,1,0,1,0,1,0,1,1,
+ 1,0,1,2,1,0,2,0,1,0,2,1,1,0,2,2,
+ 1,1,0,0,1,1,0,1,1,1,0,2,1,1,1,0,
+ 1,1,1,1,1,1,1,2,1,1,2,0,1,1,2,1,
+ 1,1,2,2,1,2,0,0,1,2,0,1,1,2,0,2,
+ 1,2,1,0,1,2,1,1,1,2,1,2,1,2,2,0,
+ 1,2,2,1,1,2,2,2,2,0,0,0,2,0,0,1,
+ 2,0,0,2,2,0,1,0,2,0,1,1,2,0,1,2,
+ 2,0,2,0,2,0,2,1,2,0,2,2,2,1,0,0,
+ 2,1,0,1,2,1,0,2,2,1,1,0,2,1,1,1,
+ 2,1,1,2,2,1,2,0,2,1,2,1,2,1,2,2,
+ 2,2,0,0,2,2,0,1,2,2,0,2,2,2,1,0,
+ 2,2,1,1,2,2,1,2,2,2,2,0,2,2,2,1,
+ 2,2,2,2};
+
+/* ********************************************************************************************* */
+/* Table: ValTab21 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the quantized values for codebooks 5-6. */
+/* --------------------------------------------------------------------------------------------- */
+const SCHAR aValTab21[162]={-4,-4,-4,-3,-4,-2,-4,-1,-4,0,-4,1,-4,2,-4,3,
+ -4,4,-3,-4,-3,-3,-3,-2,-3,-1,-3,0,-3,1,-3,2,
+ -3,3,-3,4,-2,-4,-2,-3,-2,-2,-2,-1,-2,0,-2,1,
+ -2,2,-2,3,-2,4,-1,-4,-1,-3,-1,-2,-1,-1,-1,0,
+ -1,1,-1,2,-1,3,-1,4,0,-4,0,-3,0,-2,0,-1,
+ 0,0,0,1,0,2,0,3,0,4,1,-4,1,-3,1,-2,
+ 1,-1,1,0,1,1,1,2,1,3,1,4,2,-4,2,-3,
+ 2,-2,2,-1,2,0,2,1,2,2,2,3,2,4,3,-4,
+ 3,-3,3,-2,3,-1,3,0,3,1,3,2,3,3,3,4,
+ 4,-4,4,-3,4,-2,4,-1,4,0,4,1,4,2,4,3,
+ 4,4};
+
+/* ********************************************************************************************* */
+/* Table: ValTab22 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the quantized values for codebooks 7-8. */
+/* --------------------------------------------------------------------------------------------- */
+const SCHAR aValTab22[128]={0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,
+ 1,0,1,1,1,2,1,3,1,4,1,5,1,6,1,7,
+ 2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,
+ 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7,
+ 4,0,4,1,4,2,4,3,4,4,4,5,4,6,4,7,
+ 5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,
+ 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7,
+ 7,0,7,1,7,2,7,3,7,4,7,5,7,6,7,7};
+
+/* ********************************************************************************************* */
+/* Table: ValTab23 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the quantized values for codebooks 9-10. */
+/* --------------------------------------------------------------------------------------------- */
+const SCHAR aValTab23[338]={0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,
+ 0,8,0,9,0,10,0,11,0,12,1,0,1,1,1,2,
+ 1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,
+ 1,11,1,12,2,0,2,1,2,2,2,3,2,4,2,5,
+ 2,6,2,7,2,8,2,9,2,10,2,11,2,12,3,0,
+ 3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8,
+ 3,9,3,10,3,11,3,12,4,0,4,1,4,2,4,3,
+ 4,4,4,5,4,6,4,7,4,8,4,9,4,10,4,11,
+ 4,12,5,0,5,1,5,2,5,3,5,4,5,5,5,6,
+ 5,7,5,8,5,9,5,10,5,11,5,12,6,0,6,1,
+ 6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,
+ 6,10,6,11,6,12,7,0,7,1,7,2,7,3,7,4,
+ 7,5,7,6,7,7,7,8,7,9,7,10,7,11,7,12,
+ 8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,
+ 8,8,8,9,8,10,8,11,8,12,9,0,9,1,9,2,
+ 9,3,9,4,9,5,9,6,9,7,9,8,9,9,9,10,
+ 9,11,9,12,10,0,10,1,10,2,10,3,10,4,10,5,
+ 10,6,10,7,10,8,10,9,10,10,10,11,10,12,11,0,
+ 11,1,11,2,11,3,11,4,11,5,11,6,11,7,11,8,
+ 11,9,11,10,11,11,11,12,12,0,12,1,12,2,12,3,
+ 12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11,
+ 12,12};
+
+/* ********************************************************************************************* */
+/* Table: ValTab24 */
+/* --------------------------------------------------------------------------------------------- */
+/* description: This table contains the quantized values for codebooks 11. */
+/* --------------------------------------------------------------------------------------------- */
+const SCHAR aValTab24[578]={0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,
+ 0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,
+ 0,16,1,0,1,1,1,2,1,3,1,4,1,5,1,6,
+ 1,7,1,8,1,9,1,10,1,11,1,12,1,13,1,14,
+ 1,15,1,16,2,0,2,1,2,2,2,3,2,4,2,5,
+ 2,6,2,7,2,8,2,9,2,10,2,11,2,12,2,13,
+ 2,14,2,15,2,16,3,0,3,1,3,2,3,3,3,4,
+ 3,5,3,6,3,7,3,8,3,9,3,10,3,11,3,12,
+ 3,13,3,14,3,15,3,16,4,0,4,1,4,2,4,3,
+ 4,4,4,5,4,6,4,7,4,8,4,9,4,10,4,11,
+ 4,12,4,13,4,14,4,15,4,16,5,0,5,1,5,2,
+ 5,3,5,4,5,5,5,6,5,7,5,8,5,9,5,10,
+ 5,11,5,12,5,13,5,14,5,15,5,16,6,0,6,1,
+ 6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9,
+ 6,10,6,11,6,12,6,13,6,14,6,15,6,16,7,0,
+ 7,1,7,2,7,3,7,4,7,5,7,6,7,7,7,8,
+ 7,9,7,10,7,11,7,12,7,13,7,14,7,15,7,16,
+ 8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,
+ 8,8,8,9,8,10,8,11,8,12,8,13,8,14,8,15,
+ 8,16,9,0,9,1,9,2,9,3,9,4,9,5,9,6,
+ 9,7,9,8,9,9,9,10,9,11,9,12,9,13,9,14,
+ 9,15,9,16,10,0,10,1,10,2,10,3,10,4,10,5,
+ 10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13,
+ 10,14,10,15,10,16,11,0,11,1,11,2,11,3,11,4,
+ 11,5,11,6,11,7,11,8,11,9,11,10,11,11,11,12,
+ 11,13,11,14,11,15,11,16,12,0,12,1,12,2,12,3,
+ 12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11,
+ 12,12,12,13,12,14,12,15,12,16,13,0,13,1,13,2,
+ 13,3,13,4,13,5,13,6,13,7,13,8,13,9,13,10,
+ 13,11,13,12,13,13,13,14,13,15,13,16,14,0,14,1,
+ 14,2,14,3,14,4,14,5,14,6,14,7,14,8,14,9,
+ 14,10,14,11,14,12,14,13,14,14,14,15,14,16,15,0,
+ 15,1,15,2,15,3,15,4,15,5,15,6,15,7,15,8,
+ 15,9,15,10,15,11,15,12,15,13,15,14,15,15,15,16,
+ 16,0,16,1,16,2,16,3,16,4,16,5,16,6,16,7,
+ 16,8,16,9,16,10,16,11,16,12,16,13,16,14,16,15,
+ 16,16};
+
+ /* cb quant. val table */
+const SCHAR *aQuantTable[] = {aValTab41, /* 0 - */ /* use quant. val talble 1 as dummy here */
+ aValTab41, /* 1 1 */
+ aValTab41, /* 2 1 */
+ aValTab42, /* 3 2 */
+ aValTab42, /* 4 2 */
+ aValTab21, /* 5 3 */
+ aValTab21, /* 6 3 */
+ aValTab22, /* 7 4 */
+ aValTab22, /* 8 4 */
+ aValTab23, /* 9 5 */
+ aValTab23, /* 10 5 */
+ aValTab24, /* 11 6 */
+ aValTab41, /* 12 - */ /* use quant. val talble 1 as dummy here */
+ aValTab41, /* 13 - */ /* use quant. val talble 1 as dummy here */
+ aValTab41, /* 14 - */ /* use quant. val talble 1 as dummy here */
+ aValTab41, /* 15 - */ /* use quant. val talble 1 as dummy here */
+ aValTab24, /* 16 6 */
+ aValTab24, /* 17 6 */
+ aValTab24, /* 18 6 */
+ aValTab24, /* 19 6 */
+ aValTab24, /* 20 6 */
+ aValTab24, /* 21 6 */
+ aValTab24, /* 22 6 */
+ aValTab24, /* 23 6 */
+ aValTab24, /* 24 6 */
+ aValTab24, /* 25 6 */
+ aValTab24, /* 26 6 */
+ aValTab24, /* 27 6 */
+ aValTab24, /* 28 6 */
+ aValTab24, /* 29 6 */
+ aValTab24, /* 30 6 */
+ aValTab24}; /* 31 6 */
+
+/* arrays for HCR_TABLE_INFO structures */
+/* maximum length of codeword in each codebook */
+/* codebook: 0,1, 2,3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 */
+const UCHAR aMaxCwLen[MAX_CB]={0,11,9,20,16,13,11,14,12,17,14,49,0, 0, 0, 0, 14,17,21,21,25,25,29,29,29,29,33,33,33,37,37,41};
+
+/* 11 13 15 17 19 21 23 25 27 39 31 */
+/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */
+const UCHAR aDimCb[MAX_CB] = {2,4,4,4,4,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; /* codebook dimension - zero cb got a dimension of 2 */
+
+/* 11 13 15 17 19 21 23 25 27 39 31 */
+/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */
+const UCHAR aDimCbShift[MAX_CB]={1,2,2,2,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; /* codebook dimension */
+
+/* 1 -> decode sign bits */
+/* 0 -> decode no sign bits 11 13 15 17 19 21 23 25 27 39 31 */
+/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */
+const UCHAR aSignCb[MAX_CB]={0,0,0,1,1,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+
+/* arrays for HCR_CB_PAIRS structures */
+const UCHAR aMinOfCbPair[MAX_CB_PAIRS]={0,1,3,5,7, 9,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,11};
+const UCHAR aMaxOfCbPair[MAX_CB_PAIRS]={0,2,4,6,8,10,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,11};
+
+/* priorities of codebooks */
+const UCHAR aCbPriority[MAX_CB]={0,1,1,2,2,3,3,4,4,5,5,22,0,0,0,0,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21};
+
+const SCHAR aCodebook2StartInt[] = {STOP_THIS_STATE , /* cb 0 */
+ BODY_ONLY , /* cb 1 */
+ BODY_ONLY , /* cb 2 */
+ BODY_SIGN__BODY , /* cb 3 */
+ BODY_SIGN__BODY , /* cb 4 */
+ BODY_ONLY , /* cb 5 */
+ BODY_ONLY , /* cb 6 */
+ BODY_SIGN__BODY , /* cb 7 */
+ BODY_SIGN__BODY , /* cb 8 */
+ BODY_SIGN__BODY , /* cb 9 */
+ BODY_SIGN__BODY , /* cb 10 */
+ BODY_SIGN_ESC__BODY, /* cb 11 */
+ STOP_THIS_STATE , /* cb 12 */
+ STOP_THIS_STATE , /* cb 13 */
+ STOP_THIS_STATE , /* cb 14 */
+ STOP_THIS_STATE , /* cb 15 */
+ BODY_SIGN_ESC__BODY, /* cb 16 */
+ BODY_SIGN_ESC__BODY, /* cb 17 */
+ BODY_SIGN_ESC__BODY, /* cb 18 */
+ BODY_SIGN_ESC__BODY, /* cb 19 */
+ BODY_SIGN_ESC__BODY, /* cb 20 */
+ BODY_SIGN_ESC__BODY, /* cb 21 */
+ BODY_SIGN_ESC__BODY, /* cb 22 */
+ BODY_SIGN_ESC__BODY, /* cb 23 */
+ BODY_SIGN_ESC__BODY, /* cb 24 */
+ BODY_SIGN_ESC__BODY, /* cb 25 */
+ BODY_SIGN_ESC__BODY, /* cb 26 */
+ BODY_SIGN_ESC__BODY, /* cb 27 */
+ BODY_SIGN_ESC__BODY, /* cb 28 */
+ BODY_SIGN_ESC__BODY, /* cb 29 */
+ BODY_SIGN_ESC__BODY, /* cb 30 */
+ BODY_SIGN_ESC__BODY}; /* cb 31 */
+
+const STATEFUNC aStateConstant2State[] = {NULL , /* 0 = STOP_THIS_STATE */
+ Hcr_State_BODY_ONLY , /* 1 = BODY_ONLY */
+ Hcr_State_BODY_SIGN__BODY , /* 2 = BODY_SIGN__BODY */
+ Hcr_State_BODY_SIGN__SIGN , /* 3 = BODY_SIGN__SIGN */
+ Hcr_State_BODY_SIGN_ESC__BODY , /* 4 = BODY_SIGN_ESC__BODY */
+ Hcr_State_BODY_SIGN_ESC__SIGN , /* 5 = BODY_SIGN_ESC__SIGN */
+ Hcr_State_BODY_SIGN_ESC__ESC_PREFIX, /* 6 = BODY_SIGN_ESC__ESC_PREFIX */
+ Hcr_State_BODY_SIGN_ESC__ESC_WORD }; /* 7 = BODY_SIGN_ESC__ESC_WORD */
+
+/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */
+const USHORT aLargestAbsoluteValue[MAX_CB]={0,1,1,2,2,4,4,7,7,12,12,8191, 0, 0, 0, 0,15,31,47,63,95,127,159,191,223,255,319,383,511,767,1023,2047}; /* lav */
+/* CB: 11 13 15 17 19 21 23 25 27 39 31 */
+
+
+/* ------------------------------------------------------------------------------------------
+ description: The table 'HuffTreeRvlcEscape' contains the decode tree for the rvlc
+ escape sequences.
+ bit 23 and 11 not used
+ bit 22 and 10 determine end value --> if set codeword is decoded
+ bit 21-12 and 9-0 (offset to next node) or (index value)
+ The escape sequence is the index value.
+
+ input: codeword
+ output: index
+------------------------------------------------------------------------------------------ */
+const UINT aHuffTreeRvlcEscape[53] = { 0x002001,0x400003,0x401004,0x402005,0x403007,0x404006,0x00a405,0x009008,
+ 0x00b406,0x00c407,0x00d408,0x00e409,0x40b40a,0x40c00f,0x40d010,0x40e011,
+ 0x40f012,0x410013,0x411014,0x412015,0x016413,0x414415,0x017416,0x417018,
+ 0x419019,0x01a418,0x01b41a,0x01c023,0x03201d,0x01e020,0x43501f,0x41b41c,
+ 0x021022,0x41d41e,0x41f420,0x02402b,0x025028,0x026027,0x421422,0x423424,
+ 0x02902a,0x425426,0x427428,0x02c02f,0x02d02e,0x42942a,0x42b42c,0x030031,
+ 0x42d42e,0x42f430,0x033034,0x431432,0x433434 };
+
+/* ------------------------------------------------------------------------------------------
+ description: The table 'HuffTreeRvlc' contains the huffman decoding tree for the RVLC
+ scale factors. The table contains 15 allowed, symmetric codewords and 8
+ forbidden codewords, which are used for error detection.
+
+ usage of bits: bit 23 and 11 not used
+ bit 22 and 10 determine end value --> if set codeword is decoded
+ bit 21-12 and 9-0 (offset to next node within the table) or (index+7).
+ The decoded (index+7) is in the range from 0,1,..,22. If the (index+7)
+ is in the range 15,16,..,22, then a forbidden codeword is decoded.
+
+ input: A single bit from a RVLC scalefactor codeword
+ output: [if codeword is not completely decoded:] offset to next node within table or
+ [if codeword is decoded:] A dpcm value i.e. (index+7) in range from 0,1,..,22.
+ The differential scalefactor (DPCM value) named 'index' is calculated by
+ subtracting 7 from the decoded value (index+7).
+------------------------------------------------------------------------------------------ */
+const UINT aHuffTreeRvlCodewds[22] = { 0x407001,0x002009,0x003406,0x004405,0x005404,0x006403,0x007400,0x008402,
+ 0x411401,0x00a408,0x00c00b,0x00e409,0x01000d,0x40f40a,0x41400f,0x01340b,
+ 0x011015,0x410012,0x41240c,0x416014,0x41540d,0x41340e };
+
+
+
+const FIXP_WTB LowDelaySynthesis512[1536] = {
+/* part 0 */
+WTC(0xdac984c0), WTC(0xdb100080), WTC(0xdb56cd00), WTC(0xdb9dec40), WTC(0xdbe55fc0), WTC(0xdc2d2880), WTC(0xdc754780), WTC(0xdcbdbd80),
+WTC(0xdd068a80), WTC(0xdd4fae80), WTC(0xdd992940), WTC(0xdde2f9c0), WTC(0xde2d1fc0), WTC(0xde779a80), WTC(0xdec26a00), WTC(0xdf0d8e00),
+WTC(0xdf590680), WTC(0xdfa4d540), WTC(0xdff0fc80), WTC(0xe03d7e20), WTC(0xe08a5900), WTC(0xe0d78a20), WTC(0xe1250cc0), WTC(0xe172dcc0),
+WTC(0xe1c0f7a0), WTC(0xe20f59a0), WTC(0xe25dfea0), WTC(0xe2ace400), WTC(0xe2fc0be0), WTC(0xe34b7bc0), WTC(0xe39b3c80), WTC(0xe3eb5260),
+WTC(0xe43bbac0), WTC(0xe48c7160), WTC(0xe4dd7140), WTC(0xe52eb600), WTC(0xe5803c00), WTC(0xe5d1fda0), WTC(0xe623f360), WTC(0xe6761700),
+WTC(0xe6c86400), WTC(0xe71ad500), WTC(0xe76d63e0), WTC(0xe7c00ba0), WTC(0xe812c8e0), WTC(0xe86598e0), WTC(0xe8b878e0), WTC(0xe90b68a0),
+WTC(0xe95e6c40), WTC(0xe9b18ae0), WTC(0xea04ce80), WTC(0xea583ba0), WTC(0xeaabcda0), WTC(0xeaff7ee0), WTC(0xeb5348e0), WTC(0xeba722c0),
+WTC(0xebfb0060), WTC(0xec4ed240), WTC(0xeca28540), WTC(0xecf60c20), WTC(0xed496120), WTC(0xed9c7e80), WTC(0xedef5e40), WTC(0xee41fc00),
+WTC(0xee945600), WTC(0xeee66ac0), WTC(0xef3839a0), WTC(0xef89c0e0), WTC(0xefdafda0), WTC(0xf02bed60), WTC(0xf07c8e80), WTC(0xf0cce000),
+WTC(0xf11ce220), WTC(0xf16c9620), WTC(0xf1bbfe30), WTC(0xf20b19e0), WTC(0xf259e5a0), WTC(0xf2a85dc0), WTC(0xf2f67ed0), WTC(0xf34445b0),
+WTC(0xf391aed0), WTC(0xf3deb590), WTC(0xf42b53e0), WTC(0xf4778140), WTC(0xf4c33190), WTC(0xf50e5660), WTC(0xf558df30), WTC(0xf5a2be50),
+WTC(0xf5ebea10), WTC(0xf6345780), WTC(0xf67bfab0), WTC(0xf6c2cee0), WTC(0xf708d7b0), WTC(0xf74e19c0), WTC(0xf7929a70), WTC(0xf7d66630),
+WTC(0xf8199268), WTC(0xf85c3860), WTC(0xf89e7480), WTC(0xf8e058c0), WTC(0xf921ec08), WTC(0xf9633800), WTC(0xf9a44980), WTC(0xf9e53158),
+WTC(0xfa260158), WTC(0xfa66ca18), WTC(0xfaa79ac0), WTC(0xfae87920), WTC(0xfb295fa0), WTC(0xfb6a42b8), WTC(0xfbab1240), WTC(0xfbebd1c0),
+WTC(0xfc2c9c24), WTC(0xfc6d8d90), WTC(0xfcaec240), WTC(0xfcf05684), WTC(0xfd326a98), WTC(0xfd75254c), WTC(0xfdb8afd4), WTC(0xfdfccdfc),
+WTC(0xfe40d694), WTC(0xfe84161c), WTC(0xfec5cf5a), WTC(0xff04e7fc), WTC(0xff3fdfe3), WTC(0xff751ddf), WTC(0xffa2fb0f), WTC(0xffc87c42),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0xbffb6081), WTC(0xbff22f81), WTC(0xbfe8fc01), WTC(0xbfdfc781), WTC(0xbfd69101), WTC(0xbfcd5a01), WTC(0xbfc42201), WTC(0xbfbae981),
+WTC(0xbfb1b101), WTC(0xbfa87901), WTC(0xbf9f4181), WTC(0xbf960b01), WTC(0xbf8cd481), WTC(0xbf839d81), WTC(0xbf7a6681), WTC(0xbf712f01),
+WTC(0xbf67f801), WTC(0xbf5ec101), WTC(0xbf558b01), WTC(0xbf4c5681), WTC(0xbf432281), WTC(0xbf39ee81), WTC(0xbf30bb01), WTC(0xbf278801),
+WTC(0xbf1e5501), WTC(0xbf152381), WTC(0xbf0bf381), WTC(0xbf02c581), WTC(0xbef99901), WTC(0xbef06d01), WTC(0xbee74281), WTC(0xbede1901),
+WTC(0xbed4f081), WTC(0xbecbca81), WTC(0xbec2a781), WTC(0xbeb98681), WTC(0xbeb06881), WTC(0xbea74c81), WTC(0xbe9e3281), WTC(0xbe951a81),
+WTC(0xbe8c0501), WTC(0xbe82f301), WTC(0xbe79e481), WTC(0xbe70da01), WTC(0xbe67d381), WTC(0xbe5ed081), WTC(0xbe55d001), WTC(0xbe4cd381),
+WTC(0xbe43da81), WTC(0xbe3ae601), WTC(0xbe31f701), WTC(0xbe290d01), WTC(0xbe202801), WTC(0xbe174781), WTC(0xbe0e6c01), WTC(0xbe059481),
+WTC(0xbdfcc301), WTC(0xbdf3f701), WTC(0xbdeb3101), WTC(0xbde27201), WTC(0xbdd9b981), WTC(0xbdd10681), WTC(0xbdc85981), WTC(0xbdbfb281),
+WTC(0xbdb71201), WTC(0xbdae7881), WTC(0xbda5e601), WTC(0xbd9d5b81), WTC(0xbd94d801), WTC(0xbd8c5c01), WTC(0xbd83e681), WTC(0xbd7b7781),
+WTC(0xbd731081), WTC(0xbd6ab101), WTC(0xbd625981), WTC(0xbd5a0b01), WTC(0xbd51c481), WTC(0xbd498601), WTC(0xbd414f01), WTC(0xbd391f81),
+WTC(0xbd30f881), WTC(0xbd28d981), WTC(0xbd20c401), WTC(0xbd18b781), WTC(0xbd10b381), WTC(0xbd08b781), WTC(0xbd00c381), WTC(0xbcf8d781),
+WTC(0xbcf0f381), WTC(0xbce91801), WTC(0xbce14601), WTC(0xbcd97c81), WTC(0xbcd1bb81), WTC(0xbcca0301), WTC(0xbcc25181), WTC(0xbcbaa801),
+WTC(0xbcb30601), WTC(0xbcab6c01), WTC(0xbca3db01), WTC(0xbc9c5281), WTC(0xbc94d201), WTC(0xbc8d5901), WTC(0xbc85e801), WTC(0xbc7e7e01),
+WTC(0xbc771c01), WTC(0xbc6fc101), WTC(0xbc686e01), WTC(0xbc612301), WTC(0xbc59df81), WTC(0xbc52a381), WTC(0xbc4b6e81), WTC(0xbc444081),
+WTC(0xbc3d1801), WTC(0xbc35f501), WTC(0xbc2ed681), WTC(0xbc27bd81), WTC(0xbc20ae01), WTC(0xbc19ab01), WTC(0xbc12b801), WTC(0xbc0bcf81),
+WTC(0xbc04e381), WTC(0xbbfde481), WTC(0xbbf6c601), WTC(0xbbef9b81), WTC(0xbbe89901), WTC(0xbbe1f401), WTC(0xbbdbe201), WTC(0xbbd68c81),
+WTC(0xbbd21281), WTC(0xbbce9181), WTC(0xbbcc2681), WTC(0xbbcaca01), WTC(0xbbca5081), WTC(0xbbca8d01), WTC(0xbbcb5301), WTC(0xbbcc8201),
+WTC(0xbbce0601), WTC(0xbbcfca81), WTC(0xbbd1bd81), WTC(0xbbd3e101), WTC(0xbbd64d01), WTC(0xbbd91b81), WTC(0xbbdc6481), WTC(0xbbe03801),
+WTC(0xbbe49d01), WTC(0xbbe99981), WTC(0xbbef3301), WTC(0xbbf56181), WTC(0xbbfc0f81), WTC(0xbc032601), WTC(0xbc0a8f01), WTC(0xbc123b81),
+WTC(0xbc1a2401), WTC(0xbc224181), WTC(0xbc2a8c81), WTC(0xbc330781), WTC(0xbc3bbc01), WTC(0xbc44b481), WTC(0xbc4dfb81), WTC(0xbc57a301),
+WTC(0xbc61c401), WTC(0xbc6c7781), WTC(0xbc77d601), WTC(0xbc83f201), WTC(0xbc90d481), WTC(0xbc9e8801), WTC(0xbcad1501), WTC(0xbcbc7e01),
+WTC(0xbcccbd01), WTC(0xbcddcc81), WTC(0xbcefa601), WTC(0xbd023f01), WTC(0xbd158801), WTC(0xbd297181), WTC(0xbd3deb81), WTC(0xbd52eb01),
+WTC(0xbd686681), WTC(0xbd7e5581), WTC(0xbd94b001), WTC(0xbdab7181), WTC(0xbdc29a81), WTC(0xbdda2a01), WTC(0xbdf22181), WTC(0xbe0a8581),
+WTC(0xbe236001), WTC(0xbe3cbc01), WTC(0xbe56a381), WTC(0xbe712001), WTC(0xbe8c3781), WTC(0xbea7f301), WTC(0xbec45881), WTC(0xbee17201),
+WTC(0xbeff4801), WTC(0xbf1de601), WTC(0xbf3d5501), WTC(0xbf5d9a81), WTC(0xbf7eb581), WTC(0xbfa0a581), WTC(0xbfc36a01), WTC(0xbfe6ed01),
+WTC(0xc00b04c0), WTC(0xc02f86c0), WTC(0xc0544940), WTC(0xc0792ec0), WTC(0xc09e2640), WTC(0xc0c31f00), WTC(0xc0e80a00), WTC(0xc10cf480),
+WTC(0xc1320940), WTC(0xc15773c0), WTC(0xc17d5f00), WTC(0xc1a3e340), WTC(0xc1cb05c0), WTC(0xc1f2cbc0), WTC(0xc21b3940), WTC(0xc2444b00),
+WTC(0xc26df5c0), WTC(0xc2982d80), WTC(0xc2c2e640), WTC(0xc2ee0a00), WTC(0xc3197940), WTC(0xc34513c0), WTC(0xc370b9c0), WTC(0xc39c4f00),
+WTC(0xc3c7bc00), WTC(0xc3f2e940), WTC(0xc41dc140), WTC(0xc44856c0), WTC(0xc472e640), WTC(0xc49dad80), WTC(0xc4c8e880), WTC(0xc4f4acc0),
+WTC(0xc520e840), WTC(0xc54d8780), WTC(0xc57a76c0), WTC(0xc5a79640), WTC(0xc5d4bac0), WTC(0xc601b880), WTC(0xc62e6580), WTC(0xc65ab600),
+WTC(0xc686bd40), WTC(0xc6b28fc0), WTC(0xc6de41c0), WTC(0xc709de40), WTC(0xc7356640), WTC(0xc760da80), WTC(0xc78c3c40), WTC(0xc7b78640),
+WTC(0xc7e2afc0), WTC(0xc80dae80), WTC(0xc83878c0), WTC(0xc86304c0), WTC(0xc88d4900), WTC(0xc8b73b80), WTC(0xc8e0d280), WTC(0xc90a0440),
+/* part 1 */
+WTC(0xb5212e81), WTC(0xb4959501), WTC(0xb40ab501), WTC(0xb3808d81), WTC(0xb2f71f01), WTC(0xb26e6881), WTC(0xb1e66a01), WTC(0xb15f2381),
+WTC(0xb0d89401), WTC(0xb052bc01), WTC(0xafcd9a81), WTC(0xaf492f01), WTC(0xaec57801), WTC(0xae427481), WTC(0xadc02281), WTC(0xad3e8101),
+WTC(0xacbd9081), WTC(0xac3d5001), WTC(0xabbdc001), WTC(0xab3edf01), WTC(0xaac0ad01), WTC(0xaa432981), WTC(0xa9c65401), WTC(0xa94a2c01),
+WTC(0xa8ceb201), WTC(0xa853e501), WTC(0xa7d9c681), WTC(0xa7605601), WTC(0xa6e79401), WTC(0xa66f8201), WTC(0xa5f81f81), WTC(0xa5816e81),
+WTC(0xa50b6e81), WTC(0xa4962181), WTC(0xa4218801), WTC(0xa3ada281), WTC(0xa33a7201), WTC(0xa2c7f801), WTC(0xa2563501), WTC(0xa1e52a81),
+WTC(0xa174da81), WTC(0xa1054701), WTC(0xa0967201), WTC(0xa0285d81), WTC(0x9fbb0981), WTC(0x9f4e7801), WTC(0x9ee2a901), WTC(0x9e779f81),
+WTC(0x9e0d5e01), WTC(0x9da3e601), WTC(0x9d3b3b81), WTC(0x9cd35f81), WTC(0x9c6c5481), WTC(0x9c061b81), WTC(0x9ba0b701), WTC(0x9b3c2801),
+WTC(0x9ad87081), WTC(0x9a759301), WTC(0x9a139101), WTC(0x99b26c81), WTC(0x99522801), WTC(0x98f2c601), WTC(0x98944901), WTC(0x9836b201),
+WTC(0x97da0481), WTC(0x977e4181), WTC(0x97236b01), WTC(0x96c98381), WTC(0x96708b81), WTC(0x96188501), WTC(0x95c17081), WTC(0x956b4f81),
+WTC(0x95162381), WTC(0x94c1ee01), WTC(0x946eaf81), WTC(0x941c6901), WTC(0x93cb1c81), WTC(0x937acb01), WTC(0x932b7501), WTC(0x92dd1b01),
+WTC(0x928fbe01), WTC(0x92435d01), WTC(0x91f7f981), WTC(0x91ad9281), WTC(0x91642781), WTC(0x911bb981), WTC(0x90d44781), WTC(0x908dd101),
+WTC(0x90485401), WTC(0x9003ce81), WTC(0x8fc03f01), WTC(0x8f7da401), WTC(0x8f3bfb01), WTC(0x8efb4181), WTC(0x8ebb7581), WTC(0x8e7c9301),
+WTC(0x8e3e9481), WTC(0x8e017581), WTC(0x8dc53001), WTC(0x8d89be81), WTC(0x8d4f1b01), WTC(0x8d154081), WTC(0x8cdc2901), WTC(0x8ca3cb01),
+WTC(0x8c6c1b01), WTC(0x8c350d01), WTC(0x8bfe9401), WTC(0x8bc8a401), WTC(0x8b933001), WTC(0x8b5e2c81), WTC(0x8b298b81), WTC(0x8af53e81),
+WTC(0x8ac13381), WTC(0x8a8d5801), WTC(0x8a599a81), WTC(0x8a25f301), WTC(0x89f26101), WTC(0x89bee581), WTC(0x898b8301), WTC(0x89586901),
+WTC(0x8925f101), WTC(0x88f47901), WTC(0x88c45e81), WTC(0x88962981), WTC(0x886a8a81), WTC(0x88423301), WTC(0x881dd301), WTC(0x87fdd781),
+WTC(0x87d0ca81), WTC(0x87c76201), WTC(0x87bcab81), WTC(0x87b0ef01), WTC(0x87a48b01), WTC(0x8797dd81), WTC(0x878b4301), WTC(0x877ede01),
+WTC(0x87729701), WTC(0x87665481), WTC(0x8759fd01), WTC(0x874d8681), WTC(0x8740f681), WTC(0x87345381), WTC(0x8727a381), WTC(0x871ae981),
+WTC(0x870e2301), WTC(0x87014f81), WTC(0x86f46d81), WTC(0x86e77b81), WTC(0x86da7901), WTC(0x86cd6681), WTC(0x86c04381), WTC(0x86b30f01),
+WTC(0x86a5ca81), WTC(0x86987581), WTC(0x868b1001), WTC(0x867d9a81), WTC(0x86701381), WTC(0x86627b01), WTC(0x8654d001), WTC(0x86471281),
+WTC(0x86394301), WTC(0x862b6201), WTC(0x861d7081), WTC(0x860f6e01), WTC(0x86015981), WTC(0x85f33281), WTC(0x85e4f801), WTC(0x85d6a981),
+WTC(0x85c84801), WTC(0x85b9d481), WTC(0x85ab4f01), WTC(0x859cb781), WTC(0x858e0e01), WTC(0x857f5101), WTC(0x85707f81), WTC(0x85619a01),
+WTC(0x8552a181), WTC(0x85439601), WTC(0x85347901), WTC(0x85254a81), WTC(0x85160981), WTC(0x8506b581), WTC(0x84f74e01), WTC(0x84e7d381),
+WTC(0x84d84601), WTC(0x84c8a701), WTC(0x84b8f801), WTC(0x84a93801), WTC(0x84996701), WTC(0x84898481), WTC(0x84798f81), WTC(0x84698881),
+WTC(0x84597081), WTC(0x84494881), WTC(0x84391081), WTC(0x8428ca01), WTC(0x84187401), WTC(0x84080d81), WTC(0x83f79681), WTC(0x83e70f01),
+WTC(0x83d67881), WTC(0x83c5d381), WTC(0x83b52101), WTC(0x83a46181), WTC(0x83939501), WTC(0x8382ba01), WTC(0x8371d081), WTC(0x8360d901),
+WTC(0x834fd481), WTC(0x833ec381), WTC(0x832da781), WTC(0x831c8101), WTC(0x830b4f81), WTC(0x82fa1181), WTC(0x82e8c801), WTC(0x82d77201),
+WTC(0x82c61101), WTC(0x82b4a601), WTC(0x82a33281), WTC(0x8291b601), WTC(0x82803101), WTC(0x826ea201), WTC(0x825d0901), WTC(0x824b6601),
+WTC(0x8239b981), WTC(0x82280581), WTC(0x82164a81), WTC(0x82048881), WTC(0x81f2bf81), WTC(0x81e0ee81), WTC(0x81cf1581), WTC(0x81bd3401),
+WTC(0x81ab4b01), WTC(0x81995c01), WTC(0x81876781), WTC(0x81756d81), WTC(0x81636d81), WTC(0x81516701), WTC(0x813f5981), WTC(0x812d4481),
+WTC(0x811b2981), WTC(0x81090981), WTC(0x80f6e481), WTC(0x80e4bb81), WTC(0x80d28d81), WTC(0x80c05a01), WTC(0x80ae1f81), WTC(0x809bdf01),
+WTC(0x80899881), WTC(0x80774c81), WTC(0x8064fc81), WTC(0x8052a881), WTC(0x80405101), WTC(0x802df701), WTC(0x801b9b01), WTC(0x80093e01),
+WTC(0x0a74b120), WTC(0x0aa08a90), WTC(0x0acd2b80), WTC(0x0afa8860), WTC(0x0b289590), WTC(0x0b574790), WTC(0x0b8692d0), WTC(0x0bb66bb0),
+WTC(0x0be6c6b0), WTC(0x0c179830), WTC(0x0c48d500), WTC(0x0c7a7ad0), WTC(0x0cac9000), WTC(0x0cdf1b60), WTC(0x0d122390), WTC(0x0d45a8f0),
+WTC(0x0d79a5e0), WTC(0x0dae1480), WTC(0x0de2ef30), WTC(0x0e183800), WTC(0x0e4df8c0), WTC(0x0e843b90), WTC(0x0ebb0a20), WTC(0x0ef26430),
+WTC(0x0f2a3fc0), WTC(0x0f629280), WTC(0x0f9b5210), WTC(0x0fd47690), WTC(0x100dfa80), WTC(0x1047d8a0), WTC(0x10820b40), WTC(0x10bc8b80),
+WTC(0x10f75080), WTC(0x11325100), WTC(0x116d84e0), WTC(0x11a8ece0), WTC(0x11e49420), WTC(0x122085a0), WTC(0x125ccbc0), WTC(0x12995a40),
+WTC(0x12d60e80), WTC(0x1312c4c0), WTC(0x134f59e0), WTC(0x138bae60), WTC(0x13c7a740), WTC(0x140329e0), WTC(0x143e1b60), WTC(0x147862a0),
+WTC(0x14b1e840), WTC(0x14ea94c0), WTC(0x152250a0), WTC(0x15590380), WTC(0x158e93e0), WTC(0x15c2e820), WTC(0x15f5e6e0), WTC(0x162779a0),
+WTC(0x16578ca0), WTC(0x16860ca0), WTC(0x16b2e640), WTC(0x16de0b00), WTC(0x17077140), WTC(0x172f0fa0), WTC(0x1754e200), WTC(0x17796080),
+WTC(0x179d7f20), WTC(0x17c23760), WTC(0x17e87da0), WTC(0x1810cc80), WTC(0x183b25a0), WTC(0x18678520), WTC(0x1895e700), WTC(0x18c64540),
+WTC(0x18f89780), WTC(0x192cd560), WTC(0x1962f680), WTC(0x199af2a0), WTC(0x19d4c1e0), WTC(0x1a105ca0), WTC(0x1a4dbae0), WTC(0x1a8cd660),
+WTC(0x1acdaa60), WTC(0x1b103260), WTC(0x1b546940), WTC(0x1b9a4600), WTC(0x1be1bb80), WTC(0x1c2abc60), WTC(0x1c753b80), WTC(0x1cc13860),
+WTC(0x1d0ebe20), WTC(0x1d5dd8c0), WTC(0x1dae9480), WTC(0x1e010060), WTC(0x1e552f40), WTC(0x1eab33e0), WTC(0x1f032060), WTC(0x1f5cfce0),
+WTC(0x1fb8c660), WTC(0x201679c0), WTC(0x207611c0), WTC(0x20d75f00), WTC(0x213a0640), WTC(0x219dab80), WTC(0x2201f480), WTC(0x2266ba80),
+WTC(0x22cc0ac0), WTC(0x2331f4c0), WTC(0x23988940), WTC(0x23ffff40), WTC(0x2468b340), WTC(0x24d30300), WTC(0x253f4900), WTC(0x25ad8980),
+WTC(0x261d72c0), WTC(0x268eaec0), WTC(0x2700e880), WTC(0x2773db40), WTC(0x27e751c0), WTC(0x285b1780), WTC(0x28cefbc0), WTC(0x29431f80),
+WTC(0x29b7f680), WTC(0x2a2df780), WTC(0x2aa59880), WTC(0x2b1f3280), WTC(0x2b9b0140), WTC(0x2c194000), WTC(0x2c9a2540), WTC(0x2d1d8dc0),
+WTC(0x2da2fc40), WTC(0x2e29ee80), WTC(0x2eb1e340), WTC(0x2f3a4e40), WTC(0x2fc29980), WTC(0x304a2ec0), WTC(0x30d07cc0), WTC(0x315566c0),
+WTC(0x31d94480), WTC(0x325c72c0), WTC(0x32df51c0), WTC(0x33628c80), WTC(0x33e71a00), WTC(0x346df400), WTC(0x34f80dc0), WTC(0x3585c640),
+WTC(0x3616e700), WTC(0x36ab3380), WTC(0x37426ac0), WTC(0x37dbe840), WTC(0x3876a340), WTC(0x39118f40), WTC(0x39aba2c0), WTC(0x3a4422c0),
+WTC(0x3adaa200), WTC(0x3b6eb6c0), WTC(0x3bfffd80), WTC(0x3c8e9380), WTC(0x3d1b1780), WTC(0x3da62e00), WTC(0x3e307b00), WTC(0x3eba97c0),
+WTC(0x3f451280), WTC(0x3fd07940), WTC(0x405d577f), WTC(0x40ebf57f), WTC(0x417c59ff), WTC(0x420e897f), WTC(0x42a2857f), WTC(0x4338307f),
+WTC(0x43cf4d7f), WTC(0x44679cff), WTC(0x4500dfff), WTC(0x459ac2ff), WTC(0x4634e2ff), WTC(0x46ced9ff), WTC(0x4768437f), WTC(0x4800d27f),
+WTC(0x489850ff), WTC(0x492e88ff), WTC(0x49c346ff), WTC(0x4a5678ff), WTC(0x4ae82f7f), WTC(0x4b787c7f), WTC(0x4c07717f), WTC(0x4c95337f),
+WTC(0x4d21f77f), WTC(0x4dadf3ff), WTC(0x4e395eff), WTC(0x4ec4657f), WTC(0x4f4f297f), WTC(0x4fd9cd7f), WTC(0x5064737f), WTC(0x50ef3cff),
+WTC(0x517a46ff), WTC(0x5205b0ff), WTC(0x529197ff), WTC(0x531e04ff), WTC(0x53aaeb7f), WTC(0x54383eff), WTC(0x54c5ef7f), WTC(0x5553a8ff),
+WTC(0x55e0d57f), WTC(0x566cda7f), WTC(0x56f720ff), WTC(0x577f4aff), WTC(0x580534ff), WTC(0x5888bd7f), WTC(0x5909c6ff), WTC(0x598890ff),
+WTC(0x5a05b7ff), WTC(0x5a81db7f), WTC(0x5afd99ff), WTC(0x5b794a7f), WTC(0x5bf5007f), WTC(0x5c70cbff), WTC(0x5cecbb7f), WTC(0x5d68c47f),
+WTC(0x5de4c3ff), WTC(0x5e6094ff), WTC(0x5edc127f), WTC(0x5f56fdff), WTC(0x5fd1017f), WTC(0x6049c67f), WTC(0x60c0f67f), WTC(0x613650ff),
+WTC(0x61a9a9ff), WTC(0x621ad77f), WTC(0x6289b37f), WTC(0x62f67fff), WTC(0x6361e87f), WTC(0x63cc9bff), WTC(0x6437457f), WTC(0x64a2247f),
+WTC(0x650d0c7f), WTC(0x6577cc7f), WTC(0x65e2327f), WTC(0x664bf57f), WTC(0x66b4b5ff), WTC(0x671c137f), WTC(0x6781afff), WTC(0x67e579ff),
+WTC(0x6847abff), WTC(0x68a882ff), WTC(0x69083bff), WTC(0x6966fbff), WTC(0x69c4cfff), WTC(0x6a21c57f), WTC(0x6a7de87f), WTC(0x6ad9377f),
+WTC(0x6b33a5ff), WTC(0x6b8d257f), WTC(0x6be5a8ff), WTC(0x6c3d20ff), WTC(0x6c9380ff), WTC(0x6ce8ba7f), WTC(0x6d3cbfff), WTC(0x6d8f827f),
+/* part 2 */
+WTC(0xad98b481), WTC(0xaead9d01), WTC(0xafbfc381), WTC(0xb0cf4d01), WTC(0xb1dc5f81), WTC(0xb2e72081), WTC(0xb3efb501), WTC(0xb4f64381),
+WTC(0xb5faf101), WTC(0xb6fde401), WTC(0xb7ff4001), WTC(0xb8ff1601), WTC(0xb9fd6181), WTC(0xbafa1d01), WTC(0xbbf54401), WTC(0xbceed101),
+WTC(0xbde6c081), WTC(0xbedd0e81), WTC(0xbfd1b701), WTC(0xc0c4b440), WTC(0xc1b5ffc0), WTC(0xc2a59340), WTC(0xc3936780), WTC(0xc47f78c0),
+WTC(0xc569c600), WTC(0xc6524d40), WTC(0xc7390dc0), WTC(0xc81e04c0), WTC(0xc9012e00), WTC(0xc9e28540), WTC(0xcac20700), WTC(0xcb9fb1c0),
+WTC(0xcc7b8640), WTC(0xcd558600), WTC(0xce2db200), WTC(0xcf0409c0), WTC(0xcfd88a40), WTC(0xd0ab3080), WTC(0xd17bfa00), WTC(0xd24ae640),
+WTC(0xd317f7c0), WTC(0xd3e33080), WTC(0xd4ac9340), WTC(0xd5741f40), WTC(0xd639d2c0), WTC(0xd6fdab00), WTC(0xd7bfa5c0), WTC(0xd87fc300),
+WTC(0xd93e0600), WTC(0xd9fa7180), WTC(0xdab50900), WTC(0xdb6dccc0), WTC(0xdc24ba80), WTC(0xdcd9d000), WTC(0xdd8d0b80), WTC(0xde3e6dc0),
+WTC(0xdeedf9c0), WTC(0xdf9bb340), WTC(0xe0479e20), WTC(0xe0f1bac0), WTC(0xe19a07e0), WTC(0xe2408380), WTC(0xe2e52c00), WTC(0xe38802e0),
+WTC(0xe4290c00), WTC(0xe4c84c20), WTC(0xe565c760), WTC(0xe6017f20), WTC(0xe69b7240), WTC(0xe7339f60), WTC(0xe7ca0500), WTC(0xe85ea480),
+WTC(0xe8f18180), WTC(0xe9829fc0), WTC(0xea1202e0), WTC(0xea9fab80), WTC(0xeb2b9700), WTC(0xebb5c2a0), WTC(0xec3e2bc0), WTC(0xecc4d300),
+WTC(0xed49bc80), WTC(0xedccec60), WTC(0xee4e66a0), WTC(0xeece2d80), WTC(0xef4c41e0), WTC(0xefc8a480), WTC(0xf0435610), WTC(0xf0bc5c60),
+WTC(0xf133c230), WTC(0xf1a99270), WTC(0xf21dd7b0), WTC(0xf29097e0), WTC(0xf301d3d0), WTC(0xf3718c20), WTC(0xf3dfc180), WTC(0xf44c7100),
+WTC(0xf4b79480), WTC(0xf52125b0), WTC(0xf5891df0), WTC(0xf5ef6fe0), WTC(0xf6540730), WTC(0xf6b6cf50), WTC(0xf717b490), WTC(0xf776b9a0),
+WTC(0xf7d3f720), WTC(0xf82f86e8), WTC(0xf8898260), WTC(0xf8e1fc50), WTC(0xf93900f0), WTC(0xf98e9c28), WTC(0xf9e2d940), WTC(0xfa35b4a0),
+WTC(0xfa871bd8), WTC(0xfad6fbd0), WTC(0xfb254250), WTC(0xfb71f0c0), WTC(0xfbbd1c28), WTC(0xfc06da60), WTC(0xfc4f40a4), WTC(0xfc965500),
+WTC(0xfcdc0e5c), WTC(0xfd2062f4), WTC(0xfd6348d0), WTC(0xfda4b1b8), WTC(0xfde48b2c), WTC(0xfe22c280), WTC(0xfe5f462a), WTC(0xfe9a1f2e),
+WTC(0xfed3711c), WTC(0xff0b60ac), WTC(0xff4212dd), WTC(0xff77b344), WTC(0xffac7407), WTC(0xffe08796), WTC(0x00141e37), WTC(0x00473665),
+WTC(0x00799cd0), WTC(0x00ab1bff), WTC(0x00db7d8b), WTC(0x010a75ea), WTC(0x0137a46e), WTC(0x0162a77a), WTC(0x018b20ac), WTC(0x01b0fb7a),
+WTC(0x01d46d3c), WTC(0x01f5ae7c), WTC(0x0214f91c), WTC(0x0232a5cc), WTC(0x024f2c04), WTC(0x026b048c), WTC(0x0286a628), WTC(0x02a25808),
+WTC(0x02be31c0), WTC(0x02da48e0), WTC(0x02f6b09c), WTC(0x031345dc), WTC(0x032faf50), WTC(0x034b9148), WTC(0x036690e8), WTC(0x0380658c),
+WTC(0x0398d8e4), WTC(0x03afb568), WTC(0x03c4c6e0), WTC(0x03d7f770), WTC(0x03e94f9c), WTC(0x03f8d938), WTC(0x04069ee8), WTC(0x0412bef8),
+WTC(0x041d6b30), WTC(0x0426d638), WTC(0x042f3288), WTC(0x0436ad98), WTC(0x043d6fd0), WTC(0x0443a170), WTC(0x04496a40), WTC(0x044ee728),
+WTC(0x04542a40), WTC(0x04594520), WTC(0x045e4890), WTC(0x04633210), WTC(0x0467ebe8), WTC(0x046c5f80), WTC(0x04707630), WTC(0x047417f0),
+WTC(0x04772b58), WTC(0x047996e8), WTC(0x047b4140), WTC(0x047c12a0), WTC(0x047bf520), WTC(0x047ad2e0), WTC(0x04789690), WTC(0x047539c8),
+WTC(0x0470c4b8), WTC(0x046b4058), WTC(0x0464b600), WTC(0x045d3a08), WTC(0x0454ebc8), WTC(0x044beb00), WTC(0x04425798), WTC(0x043853b0),
+WTC(0x042e0398), WTC(0x04238bd8), WTC(0x04190f98), WTC(0x040e9670), WTC(0x04040c18), WTC(0x03f95b30), WTC(0x03ee6e20), WTC(0x03e32b64),
+WTC(0x03d77598), WTC(0x03cb2f24), WTC(0x03be3b18), WTC(0x03b08b18), WTC(0x03a21f64), WTC(0x0392f8d4), WTC(0x038318e0), WTC(0x03728e94),
+WTC(0x03617694), WTC(0x034fee18), WTC(0x033e11f4), WTC(0x032bf530), WTC(0x0319a114), WTC(0x03071e80), WTC(0x02f475f4), WTC(0x02e1a7c0),
+WTC(0x02ceac04), WTC(0x02bb7a84), WTC(0x02a80af0), WTC(0x029452b0), WTC(0x028044e0), WTC(0x026bd488), WTC(0x0256f558), WTC(0x0241a940),
+WTC(0x022c0084), WTC(0x02160c08), WTC(0x01ffdc5a), WTC(0x01e97ad2), WTC(0x01d2e982), WTC(0x01bc2a2a), WTC(0x01a53e8c), WTC(0x018e2860),
+WTC(0x0176e94c), WTC(0x015f82fa), WTC(0x0147f70e), WTC(0x013046c2), WTC(0x011872e8), WTC(0x01007c4a), WTC(0x00e863cf), WTC(0x00d02c81),
+WTC(0x00b7db94), WTC(0x009f7651), WTC(0x00870204), WTC(0x006e83f8), WTC(0x00560176), WTC(0x003d7fcb), WTC(0x0025043f), WTC(0x000c941f),
+WTC(0xd65574c0), WTC(0xd5ebc100), WTC(0xd582d080), WTC(0xd51a9cc0), WTC(0xd4b31f80), WTC(0xd44c5280), WTC(0xd3e62f80), WTC(0xd380b040),
+WTC(0xd31bce40), WTC(0xd2b78380), WTC(0xd253ca40), WTC(0xd1f0acc0), WTC(0xd18e4580), WTC(0xd12caf40), WTC(0xd0cc0400), WTC(0xd06c40c0),
+WTC(0xd00d4740), WTC(0xcfaef6c0), WTC(0xcf513140), WTC(0xcef3fa80), WTC(0xce977a40), WTC(0xce3bd980), WTC(0xcde13f40), WTC(0xcd87a880),
+WTC(0xcd2ee800), WTC(0xccd6cf00), WTC(0xcc7f2f40), WTC(0xcc27e880), WTC(0xcbd0ea00), WTC(0xcb7a2380), WTC(0xcb238380), WTC(0xcaccee80),
+WTC(0xca763ec0), WTC(0xca1f4d00), WTC(0xc9c7f480), WTC(0xc9703b40), WTC(0xc9185200), WTC(0xc8c06b00), WTC(0xc868b4c0), WTC(0xc81100c0),
+WTC(0xc7b8c280), WTC(0xc75f6a40), WTC(0xc7046900), WTC(0xc6a74340), WTC(0xc6479300), WTC(0xc5e4f200), WTC(0xc57efac0), WTC(0xc5154880),
+WTC(0xc4a77780), WTC(0xc4352440), WTC(0xc3bdeac0), WTC(0xc3416740), WTC(0xc2bf33c0), WTC(0xc236eb40), WTC(0xc1a82900), WTC(0xc11290c0),
+WTC(0xc075cf00), WTC(0xbfd19081), WTC(0xbf258401), WTC(0xbe716d81), WTC(0xbdb52b81), WTC(0xbcf09a81), WTC(0xbc23af81), WTC(0xbb505c01),
+WTC(0xba7a9081), WTC(0xb9a65281), WTC(0xb8d79301), WTC(0xb8104c01), WTC(0xb7508181), WTC(0xb6982201), WTC(0xb5e71b01), WTC(0xb53d5b01),
+WTC(0xb49ad081), WTC(0xb3ff6901), WTC(0xb36b1301), WTC(0xb2ddbd01), WTC(0xb2575481), WTC(0xb1d7c801), WTC(0xb15f0601), WTC(0xb0ecfc01),
+WTC(0xb0819881), WTC(0xb01cca01), WTC(0xafbe7e01), WTC(0xaf66a301), WTC(0xaf152701), WTC(0xaec9f881), WTC(0xae850601), WTC(0xae463c81),
+WTC(0xae0d8b01), WTC(0xaddae001), WTC(0xadae2881), WTC(0xad875381), WTC(0xad664f81), WTC(0xad4b0981), WTC(0xad357081), WTC(0xad257301),
+WTC(0xad1afe01), WTC(0xad160081), WTC(0xad166901), WTC(0xad1c2481), WTC(0xad272201), WTC(0xad374f81), WTC(0xad4c9b01), WTC(0xad66f381),
+WTC(0xad864601), WTC(0xadaa8101), WTC(0xadd39301), WTC(0xae016a01), WTC(0xae33f481), WTC(0xae6b2001), WTC(0xaea6db01), WTC(0xaee71381),
+WTC(0xaf2bb801), WTC(0xaf74b681), WTC(0xafc1fd01), WTC(0xb0137a01), WTC(0xb0691b81), WTC(0xb0c2cf81), WTC(0xb1208481), WTC(0xb1822881),
+WTC(0xb1e7a981), WTC(0xb250f601), WTC(0xb2bdfc01), WTC(0xb32eaa01), WTC(0xb3a2ed01), WTC(0xb41ab481), WTC(0xb495ee01), WTC(0xb5148801),
+WTC(0xb5967081), WTC(0xb61b9581), WTC(0xb6a3e581), WTC(0xb72f4e01), WTC(0xb7bdbe01), WTC(0xb84f2381), WTC(0xb8e36c81), WTC(0xb97a8701),
+WTC(0xba146101), WTC(0xbab0e981), WTC(0xbb500d81), WTC(0xbbf1bc81), WTC(0xbc95e381), WTC(0xbd3c7181), WTC(0xbde55481), WTC(0xbe907a01),
+WTC(0xbf3dd101), WTC(0xbfed4701), WTC(0xc09ecac0), WTC(0xc1524a00), WTC(0xc207b300), WTC(0xc2bef440), WTC(0xc377fb80), WTC(0xc432b700),
+WTC(0xc4ef1500), WTC(0xc5ad03c0), WTC(0xc66c7140), WTC(0xc72d4bc0), WTC(0xc7ef8180), WTC(0xc8b30080), WTC(0xc977b700), WTC(0xca3d9340),
+WTC(0xcb048340), WTC(0xcbcc7540), WTC(0xcc955740), WTC(0xcd5f17c0), WTC(0xce29a480), WTC(0xcef4ec00), WTC(0xcfc0dc80), WTC(0xd08d63c0),
+WTC(0xd15a7040), WTC(0xd227f000), WTC(0xd2f5d140), WTC(0xd3c40240), WTC(0xd4927100), WTC(0xd5610b80), WTC(0xd62fc080), WTC(0xd6fe7dc0),
+WTC(0xd7cd3140), WTC(0xd89bc980), WTC(0xd96a34c0), WTC(0xda3860c0), WTC(0xdb063c00), WTC(0xdbd3b480), WTC(0xdca0b880), WTC(0xdd6d3640),
+WTC(0xde391bc0), WTC(0xdf045740), WTC(0xdfced6c0), WTC(0xe09888c0), WTC(0xe1615b20), WTC(0xe2293c20), WTC(0xe2f01a00), WTC(0xe3b5e2c0),
+WTC(0xe47a84c0), WTC(0xe53dee00), WTC(0xe6000cc0), WTC(0xe6c0cf20), WTC(0xe7802360), WTC(0xe83df7a0), WTC(0xe8fa39e0), WTC(0xe9b4d880),
+WTC(0xea6dc1a0), WTC(0xeb24e360), WTC(0xebda2be0), WTC(0xec8d8960), WTC(0xed3eea20), WTC(0xedee3c00), WTC(0xee9b6d80), WTC(0xef466ca0),
+WTC(0xefef2780), WTC(0xf0958c50), WTC(0xf1398950), WTC(0xf1db0ca0), WTC(0xf27a0470), WTC(0xf3165ed0), WTC(0xf3b00a10), WTC(0xf446f440),
+WTC(0xf4db0b90), WTC(0xf56c3e30), WTC(0xf5fa7a50), WTC(0xf685ae10), WTC(0xf70dc7a0), WTC(0xf792b520), WTC(0xf81464c8), WTC(0xf892c4c0),
+WTC(0xf90dc330), WTC(0xf9854e40), WTC(0xf9f95418), WTC(0xfa69c2f0), WTC(0xfad688e8), WTC(0xfb3f9428), WTC(0xfba4d2e8), WTC(0xfc063344),
+WTC(0xfc63a370), WTC(0xfcbd1194), WTC(0xfd126bdc), WTC(0xfd63a06c), WTC(0xfdb09d78), WTC(0xfdf95124), WTC(0xfe3da99e), WTC(0xfe7d950e),
+WTC(0xfeb901a2), WTC(0xfeefdd80), WTC(0xff2216d7), WTC(0xff4f9bcf), WTC(0xff785a93), WTC(0xff9c414e), WTC(0xffbb3e2b), WTC(0xffd53f54),
+WTC(0xffea32f4), WTC(0xfffa0735), WTC(0x0004aa43), WTC(0x000a0a47), WTC(0x000a156c), WTC(0x0004b9de), WTC(0xfff9e5c5), WTC(0xffe9874e)
+};
+
+
+const FIXP_WTB LowDelaySynthesis480[1440] = {
+
+WTC(0xdad2e6c0), WTC(0xdb1da900), WTC(0xdb68ce40), WTC(0xdbb45840), WTC(0xdc004940), WTC(0xdc4ca280), WTC(0xdc996500), WTC(0xdce69140),
+WTC(0xdd342780), WTC(0xdd822700), WTC(0xddd08a80), WTC(0xde1f4d00), WTC(0xde6e6ec0), WTC(0xdebdec40), WTC(0xdf0dba80), WTC(0xdf5dd540),
+WTC(0xdfae3cc0), WTC(0xdfff0500), WTC(0xe0505140), WTC(0xe0a22980), WTC(0xe0f488e0), WTC(0xe1476180), WTC(0xe19aa480), WTC(0xe1ee4d80),
+WTC(0xe2425400), WTC(0xe29689a0), WTC(0xe2eacd60), WTC(0xe33f2420), WTC(0xe393a300), WTC(0xe3e87f20), WTC(0xe43dcee0), WTC(0xe4938a80),
+WTC(0xe4e9b0a0), WTC(0xe5404300), WTC(0xe5973e60), WTC(0xe5ee9b80), WTC(0xe64649e0), WTC(0xe69e37e0), WTC(0xe6f65ec0), WTC(0xe74eb6c0),
+WTC(0xe7a73000), WTC(0xe7ffbe40), WTC(0xe8585ee0), WTC(0xe8b10740), WTC(0xe9099c40), WTC(0xe96214e0), WTC(0xe9ba79a0), WTC(0xea12e7c0),
+WTC(0xea6b89c0), WTC(0xeac46580), WTC(0xeb1d7260), WTC(0xeb76b620), WTC(0xebd036c0), WTC(0xec29e520), WTC(0xec83aa60), WTC(0xecdd5a00),
+WTC(0xed36d500), WTC(0xed901540), WTC(0xede91160), WTC(0xee41bc20), WTC(0xee9a0ee0), WTC(0xeef20860), WTC(0xef49a7e0), WTC(0xefa0ec00),
+WTC(0xeff7d1c0), WTC(0xf04e56b0), WTC(0xf0a476e0), WTC(0xf0fa2f60), WTC(0xf14f80e0), WTC(0xf1a46e10), WTC(0xf1f8fe80), WTC(0xf24d34a0),
+WTC(0xf2a10bb0), WTC(0xf2f48210), WTC(0xf3479cc0), WTC(0xf39a5be0), WTC(0xf3ecb8f0), WTC(0xf43eafa0), WTC(0xf4903b50), WTC(0xf4e14e80),
+WTC(0xf531d6a0), WTC(0xf581bc10), WTC(0xf5d0e9c0), WTC(0xf61f5250), WTC(0xf66ce6e0), WTC(0xf6b99330), WTC(0xf7054eb0), WTC(0xf7501f20),
+WTC(0xf79a0750), WTC(0xf7e30700), WTC(0xf82b2fc0), WTC(0xf872a138), WTC(0xf8b97f18), WTC(0xf8ffe668), WTC(0xf945e538), WTC(0xf98b8860),
+WTC(0xf9d0f380), WTC(0xfa165148), WTC(0xfa5bb8a8), WTC(0xfaa13df8), WTC(0xfae6fb00), WTC(0xfb2cf8c8), WTC(0xfb732a80), WTC(0xfbb97910),
+WTC(0xfbffcd10), WTC(0xfc463478), WTC(0xfc8cd3fc), WTC(0xfcd3be5c), WTC(0xfd1afa90), WTC(0xfd62aa84), WTC(0xfdab0288), WTC(0xfdf404b4),
+WTC(0xfe3d3006), WTC(0xfe85b20e), WTC(0xfecca4cc), WTC(0xff10d559), WTC(0xff50579b), WTC(0xff8a40d2), WTC(0xffb7d86e), WTC(0xffef6bbb),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000),
+WTC(0xbff67a01), WTC(0xbfecaa81), WTC(0xbfe2d901), WTC(0xbfd90601), WTC(0xbfcf3181), WTC(0xbfc55c81), WTC(0xbfbb8701), WTC(0xbfb1b101),
+WTC(0xbfa7dc01), WTC(0xbf9e0701), WTC(0xbf943301), WTC(0xbf8a5f81), WTC(0xbf808b81), WTC(0xbf76b701), WTC(0xbf6ce201), WTC(0xbf630d81),
+WTC(0xbf593a01), WTC(0xbf4f6801), WTC(0xbf459681), WTC(0xbf3bc601), WTC(0xbf31f501), WTC(0xbf282501), WTC(0xbf1e5501), WTC(0xbf148681),
+WTC(0xbf0aba01), WTC(0xbf00ef81), WTC(0xbef72681), WTC(0xbeed5f01), WTC(0xbee39801), WTC(0xbed9d281), WTC(0xbed00f81), WTC(0xbec64e81),
+WTC(0xbebc9181), WTC(0xbeb2d681), WTC(0xbea91f01), WTC(0xbe9f6901), WTC(0xbe95b581), WTC(0xbe8c0501), WTC(0xbe825801), WTC(0xbe78b001),
+WTC(0xbe6f0c01), WTC(0xbe656c01), WTC(0xbe5bd001), WTC(0xbe523781), WTC(0xbe48a301), WTC(0xbe3f1381), WTC(0xbe358901), WTC(0xbe2c0501),
+WTC(0xbe228681), WTC(0xbe190d81), WTC(0xbe0f9a01), WTC(0xbe062b81), WTC(0xbdfcc301), WTC(0xbdf36101), WTC(0xbdea0681), WTC(0xbde0b301),
+WTC(0xbdd76701), WTC(0xbdce2181), WTC(0xbdc4e301), WTC(0xbdbbab01), WTC(0xbdb27b01), WTC(0xbda95301), WTC(0xbda03381), WTC(0xbd971c81),
+WTC(0xbd8e0e01), WTC(0xbd850701), WTC(0xbd7c0781), WTC(0xbd731081), WTC(0xbd6a2201), WTC(0xbd613d81), WTC(0xbd586281), WTC(0xbd4f9101),
+WTC(0xbd46c801), WTC(0xbd3e0801), WTC(0xbd355081), WTC(0xbd2ca281), WTC(0xbd23ff01), WTC(0xbd1b6501), WTC(0xbd12d581), WTC(0xbd0a4f81),
+WTC(0xbd01d281), WTC(0xbcf95e81), WTC(0xbcf0f381), WTC(0xbce89281), WTC(0xbce03b81), WTC(0xbcd7ef01), WTC(0xbccfac01), WTC(0xbcc77181),
+WTC(0xbcbf4001), WTC(0xbcb71701), WTC(0xbcaef701), WTC(0xbca6e101), WTC(0xbc9ed481), WTC(0xbc96d101), WTC(0xbc8ed701), WTC(0xbc86e581),
+WTC(0xbc7efc81), WTC(0xbc771c01), WTC(0xbc6f4401), WTC(0xbc677501), WTC(0xbc5fae81), WTC(0xbc57f101), WTC(0xbc503b81), WTC(0xbc488e81),
+WTC(0xbc40e881), WTC(0xbc394901), WTC(0xbc31af01), WTC(0xbc2a1a81), WTC(0xbc228f01), WTC(0xbc1b1081), WTC(0xbc13a481), WTC(0xbc0c4581),
+WTC(0xbc04e381), WTC(0xbbfd6c01), WTC(0xbbf5d181), WTC(0xbbee2f81), WTC(0xbbe6c801), WTC(0xbbdfdb81), WTC(0xbbd9a781), WTC(0xbbd45881),
+WTC(0xbbd01301), WTC(0xbbccfc81), WTC(0xbbcb2281), WTC(0xbbca5d01), WTC(0xbbca7481), WTC(0xbbcb3201), WTC(0xbbcc6b01), WTC(0xbbce0601),
+WTC(0xbbcfea81), WTC(0xbbd20301), WTC(0xbbd45601), WTC(0xbbd70201), WTC(0xbbda2501), WTC(0xbbdddb01), WTC(0xbbe23281), WTC(0xbbe73201),
+WTC(0xbbece281), WTC(0xbbf34281), WTC(0xbbfa3c01), WTC(0xbc01b381), WTC(0xbc098d81), WTC(0xbc11b681), WTC(0xbc1a2401), WTC(0xbc22cd81),
+WTC(0xbc2bab01), WTC(0xbc34c081), WTC(0xbc3e1981), WTC(0xbc47c281), WTC(0xbc51cb01), WTC(0xbc5c4c81), WTC(0xbc676501), WTC(0xbc733401),
+WTC(0xbc7fd301), WTC(0xbc8d5101), WTC(0xbc9bb901), WTC(0xbcab1781), WTC(0xbcbb7001), WTC(0xbcccbd01), WTC(0xbcdef701), WTC(0xbcf21601),
+WTC(0xbd060c81), WTC(0xbd1ac801), WTC(0xbd303581), WTC(0xbd464281), WTC(0xbd5ce281), WTC(0xbd740b81), WTC(0xbd8bb281), WTC(0xbda3d081),
+WTC(0xbdbc6381), WTC(0xbdd56b81), WTC(0xbdeee981), WTC(0xbe08e181), WTC(0xbe236001), WTC(0xbe3e7201), WTC(0xbe5a2301), WTC(0xbe767e81),
+WTC(0xbe938c81), WTC(0xbeb15701), WTC(0xbecfe601), WTC(0xbeef4601), WTC(0xbf0f8301), WTC(0xbf30a901), WTC(0xbf52c101), WTC(0xbf75cc81),
+WTC(0xbf99cb01), WTC(0xbfbebb81), WTC(0xbfe48981), WTC(0xc00b04c0), WTC(0xc031f880), WTC(0xc0593340), WTC(0xc0809280), WTC(0xc0a802c0),
+WTC(0xc0cf6ec0), WTC(0xc0f6cc00), WTC(0xc11e3a80), WTC(0xc145f040), WTC(0xc16e22c0), WTC(0xc196fb00), WTC(0xc1c08680), WTC(0xc1eaca00),
+WTC(0xc215cbc0), WTC(0xc2418940), WTC(0xc26df5c0), WTC(0xc29b02c0), WTC(0xc2c8a140), WTC(0xc2f6b500), WTC(0xc3251740), WTC(0xc353a0c0),
+WTC(0xc3822c00), WTC(0xc3b09940), WTC(0xc3deccc0), WTC(0xc40ca800), WTC(0xc43a28c0), WTC(0xc4678a00), WTC(0xc4951780), WTC(0xc4c31d00),
+WTC(0xc4f1bdc0), WTC(0xc520e840), WTC(0xc5508440), WTC(0xc5807900), WTC(0xc5b09e80), WTC(0xc5e0bfc0), WTC(0xc610a740), WTC(0xc64029c0),
+WTC(0xc66f49c0), WTC(0xc69e2180), WTC(0xc6ccca40), WTC(0xc6fb5700), WTC(0xc729cc80), WTC(0xc7582b40), WTC(0xc7867480), WTC(0xc7b4a480),
+WTC(0xc7e2afc0), WTC(0xc8108a80), WTC(0xc83e28c0), WTC(0xc86b7f00), WTC(0xc8988100), WTC(0xc8c52340), WTC(0xc8f15980), WTC(0xc91d1840),
+WTC(0xb4d6a381), WTC(0xb4422b81), WTC(0xb3ae8601), WTC(0xb31bb301), WTC(0xb289b181), WTC(0xb1f88181), WTC(0xb1682281), WTC(0xb0d89401),
+WTC(0xb049d601), WTC(0xafbbe801), WTC(0xaf2ec901), WTC(0xaea27681), WTC(0xae16f001), WTC(0xad8c3301), WTC(0xad023f01), WTC(0xac791401),
+WTC(0xabf0b181), WTC(0xab691681), WTC(0xaae24301), WTC(0xaa5c3601), WTC(0xa9d6ef01), WTC(0xa9526d81), WTC(0xa8ceb201), WTC(0xa84bbb81),
+WTC(0xa7c98b01), WTC(0xa7482101), WTC(0xa6c77e01), WTC(0xa647a301), WTC(0xa5c89001), WTC(0xa54a4701), WTC(0xa4ccc901), WTC(0xa4501601),
+WTC(0xa3d43001), WTC(0xa3591801), WTC(0xa2dece81), WTC(0xa2655581), WTC(0xa1ecae01), WTC(0xa174da81), WTC(0xa0fddd81), WTC(0xa087b981),
+WTC(0xa0127081), WTC(0x9f9e0301), WTC(0x9f2a7281), WTC(0x9eb7c101), WTC(0x9e45f081), WTC(0x9dd50481), WTC(0x9d650081), WTC(0x9cf5e701),
+WTC(0x9c87ba81), WTC(0x9c1a7c81), WTC(0x9bae2f81), WTC(0x9b42d581), WTC(0x9ad87081), WTC(0x9a6f0381), WTC(0x9a069001), WTC(0x999f1981),
+WTC(0x9938a281), WTC(0x98d32d81), WTC(0x986ebd81), WTC(0x980b5501), WTC(0x97a8f681), WTC(0x9747a481), WTC(0x96e76101), WTC(0x96882e01),
+WTC(0x962a0c81), WTC(0x95ccff01), WTC(0x95710601), WTC(0x95162381), WTC(0x94bc5981), WTC(0x9463a881), WTC(0x940c1281), WTC(0x93b59901),
+WTC(0x93603d01), WTC(0x930bff81), WTC(0x92b8e101), WTC(0x9266e281), WTC(0x92160301), WTC(0x91c64301), WTC(0x9177a301), WTC(0x912a2201),
+WTC(0x90ddc001), WTC(0x90927b81), WTC(0x90485401), WTC(0x8fff4601), WTC(0x8fb74f81), WTC(0x8f706f01), WTC(0x8f2aa101), WTC(0x8ee5e301),
+WTC(0x8ea23201), WTC(0x8e5f8881), WTC(0x8e1de001), WTC(0x8ddd3201), WTC(0x8d9d7781), WTC(0x8d5eaa01), WTC(0x8d20c301), WTC(0x8ce3ba81),
+WTC(0x8ca78781), WTC(0x8c6c1b01), WTC(0x8c316681), WTC(0x8bf75b01), WTC(0x8bbde981), WTC(0x8b850281), WTC(0x8b4c9701), WTC(0x8b149701),
+WTC(0x8adcee01), WTC(0x8aa58681), WTC(0x8a6e4a01), WTC(0x8a372881), WTC(0x8a001f01), WTC(0x89c92f81), WTC(0x89925a81), WTC(0x895bcd01),
+WTC(0x8925f101), WTC(0x88f13801), WTC(0x88be1681), WTC(0x888d3181), WTC(0x885f8481), WTC(0x88353501), WTC(0x88124281), WTC(0x87e73d81),
+WTC(0x87d4ac81), WTC(0x87cb5101), WTC(0x87c05e81), WTC(0x87b42481), WTC(0x87a70e81), WTC(0x87998f01), WTC(0x878c1881), WTC(0x877ede01),
+WTC(0x8771c601), WTC(0x8764b101), WTC(0x87578181), WTC(0x874a2f01), WTC(0x873cc201), WTC(0x872f4201), WTC(0x8721b481), WTC(0x87141b01),
+WTC(0x87067281), WTC(0x86f8ba81), WTC(0x86eaf081), WTC(0x86dd1481), WTC(0x86cf2601), WTC(0x86c12401), WTC(0x86b30f01), WTC(0x86a4e781),
+WTC(0x8696ad01), WTC(0x86886001), WTC(0x867a0081), WTC(0x866b8d81), WTC(0x865d0581), WTC(0x864e6901), WTC(0x863fb701), WTC(0x8630f181),
+WTC(0x86221801), WTC(0x86132c01), WTC(0x86042c01), WTC(0x85f51681), WTC(0x85e5eb81), WTC(0x85d6a981), WTC(0x85c75201), WTC(0x85b7e601),
+WTC(0x85a86581), WTC(0x8598d081), WTC(0x85892681), WTC(0x85796601), WTC(0x85698e81), WTC(0x8559a081), WTC(0x85499d01), WTC(0x85398481),
+WTC(0x85295881), WTC(0x85191801), WTC(0x8508c181), WTC(0x84f85581), WTC(0x84e7d381), WTC(0x84d73c01), WTC(0x84c69101), WTC(0x84b5d301),
+WTC(0x84a50201), WTC(0x84941d81), WTC(0x84832481), WTC(0x84721701), WTC(0x8460f581), WTC(0x844fc081), WTC(0x843e7a81), WTC(0x842d2281),
+WTC(0x841bb981), WTC(0x840a3e81), WTC(0x83f8b001), WTC(0x83e70f01), WTC(0x83d55d01), WTC(0x83c39a81), WTC(0x83b1c881), WTC(0x839fe801),
+WTC(0x838df801), WTC(0x837bf801), WTC(0x8369e781), WTC(0x8357c701), WTC(0x83459881), WTC(0x83335c81), WTC(0x83211501), WTC(0x830ec081),
+WTC(0x82fc5f01), WTC(0x82e9ef01), WTC(0x82d77201), WTC(0x82c4e801), WTC(0x82b25301), WTC(0x829fb401), WTC(0x828d0b01), WTC(0x827a5801),
+WTC(0x82679901), WTC(0x8254cf01), WTC(0x8241fa01), WTC(0x822f1b01), WTC(0x821c3401), WTC(0x82094581), WTC(0x81f64f01), WTC(0x81e34f81),
+WTC(0x81d04681), WTC(0x81bd3401), WTC(0x81aa1981), WTC(0x8196f781), WTC(0x8183cf81), WTC(0x8170a181), WTC(0x815d6c01), WTC(0x814a2f81),
+WTC(0x8136ea01), WTC(0x81239d81), WTC(0x81104a01), WTC(0x80fcf181), WTC(0x80e99401), WTC(0x80d63101), WTC(0x80c2c781), WTC(0x80af5701),
+WTC(0x809bdf01), WTC(0x80886081), WTC(0x8074dc01), WTC(0x80615281), WTC(0x804dc481), WTC(0x803a3381), WTC(0x80269f81), WTC(0x80130981),
+WTC(0x0a608220), WTC(0x0a8ee7d0), WTC(0x0abe35c0), WTC(0x0aee5de0), WTC(0x0b1f5230), WTC(0x0b5104a0), WTC(0x0b836720), WTC(0x0bb66bb0),
+WTC(0x0bea0440), WTC(0x0c1e22c0), WTC(0x0c52ba70), WTC(0x0c87ca90), WTC(0x0cbd5ba0), WTC(0x0cf375e0), WTC(0x0d2a1f50), WTC(0x0d615480),
+WTC(0x0d990e40), WTC(0x0dd14500), WTC(0x0e09f730), WTC(0x0e432e90), WTC(0x0e7cf790), WTC(0x0eb75e50), WTC(0x0ef26430), WTC(0x0f2dfd70),
+WTC(0x0f6a1d70), WTC(0x0fa6b7e0), WTC(0x0fe3c3d0), WTC(0x10213ac0), WTC(0x105f1640), WTC(0x109d4f20), WTC(0x10dbdb80), WTC(0x111ab0c0),
+WTC(0x1159c360), WTC(0x11990fc0), WTC(0x11d8a060), WTC(0x121882c0), WTC(0x1258c480), WTC(0x12995a40), WTC(0x12da1b00), WTC(0x131adb60),
+WTC(0x135b70c0), WTC(0x139bb680), WTC(0x13db8c00), WTC(0x141ad080), WTC(0x14596460), WTC(0x149729e0), WTC(0x14d404e0), WTC(0x150fd8e0),
+WTC(0x154a88c0), WTC(0x1583f5e0), WTC(0x15bc0120), WTC(0x15f28ba0), WTC(0x162779a0), WTC(0x165ab300), WTC(0x168c2040), WTC(0x16bbaa80),
+WTC(0x16e94120), WTC(0x1714d9e0), WTC(0x173e6440), WTC(0x17660680), WTC(0x178ca020), WTC(0x17b36400), WTC(0x17db84e0), WTC(0x1805d920),
+WTC(0x18328400), WTC(0x18617cc0), WTC(0x1892bfa0), WTC(0x18c64540), WTC(0x18fc0400), WTC(0x1933f140), WTC(0x196e0320), WTC(0x19aa2fc0),
+WTC(0x19e86d80), WTC(0x1a28b2e0), WTC(0x1a6af700), WTC(0x1aaf3320), WTC(0x1af56180), WTC(0x1b3d7ce0), WTC(0x1b877c40), WTC(0x1bd350c0),
+WTC(0x1c20ea40), WTC(0x1c703840), WTC(0x1cc13860), WTC(0x1d13f760), WTC(0x1d688420), WTC(0x1dbeed40), WTC(0x1e174660), WTC(0x1e71a640),
+WTC(0x1ece2400), WTC(0x1f2cd220), WTC(0x1f8db3c0), WTC(0x1ff0c3e0), WTC(0x20560080), WTC(0x20bd46c0), WTC(0x21263400), WTC(0x21905740),
+WTC(0x21fb4100), WTC(0x2266ba80), WTC(0x22d2d140), WTC(0x233f9780), WTC(0x23ad25c0), WTC(0x241bc800), WTC(0x248bf040), WTC(0x24fe1380),
+WTC(0x25728180), WTC(0x25e90a00), WTC(0x26614080), WTC(0x26dabdc0), WTC(0x27552540), WTC(0x27d03200), WTC(0x284ba580), WTC(0x28c740c0),
+WTC(0x29431f80), WTC(0x29bfc9c0), WTC(0x2a3dd080), WTC(0x2abdc000), WTC(0x2b3ffd00), WTC(0x2bc4cd80), WTC(0x2c4c7d40), WTC(0x2cd72ec0),
+WTC(0x2d647f80), WTC(0x2df3cd80), WTC(0x2e847d80), WTC(0x2f15ea40), WTC(0x2fa760c0), WTC(0x30382b80), WTC(0x30c79440), WTC(0x315566c0),
+WTC(0x31e20800), WTC(0x326de7c0), WTC(0x32f98200), WTC(0x3385ba00), WTC(0x3413bec0), WTC(0x34a4c480), WTC(0x3539bf00), WTC(0x35d2c4c0),
+WTC(0x366f8340), WTC(0x370fb800), WTC(0x37b2cf80), WTC(0x3857a480), WTC(0x38fcee80), WTC(0x39a16840), WTC(0x3a4422c0), WTC(0x3ae495c0),
+WTC(0x3b824000), WTC(0x3c1cb500), WTC(0x3cb438c0), WTC(0x3d4994c0), WTC(0x3ddd8f40), WTC(0x3e70ec00), WTC(0x3f045e40), WTC(0x3f989080),
+WTC(0x402e32ff), WTC(0x40c5c07f), WTC(0x415f547f), WTC(0x41faf07f), WTC(0x4298997f), WTC(0x4338307f), WTC(0x43d96bff), WTC(0x447bffff),
+WTC(0x451f9cff), WTC(0x45c3daff), WTC(0x46683eff), WTC(0x470c4cff), WTC(0x47af93ff), WTC(0x4851c3ff), WTC(0x48f29d7f), WTC(0x4991de7f),
+WTC(0x4a2f5e7f), WTC(0x4acb287f), WTC(0x4b65537f), WTC(0x4bfdf37f), WTC(0x4c95337f), WTC(0x4d2b51ff), WTC(0x4dc091ff), WTC(0x4e5533ff),
+WTC(0x4ee96b7f), WTC(0x4f7d61ff), WTC(0x501140ff), WTC(0x50a5317f), WTC(0x51395a7f), WTC(0x51cddf7f), WTC(0x5262e6ff), WTC(0x52f885ff),
+WTC(0x538eb47f), WTC(0x542560ff), WTC(0x54bc7b7f), WTC(0x5553a8ff), WTC(0x55ea35ff), WTC(0x567f66ff), WTC(0x5712897f), WTC(0x57a33a7f),
+WTC(0x583152ff), WTC(0x58bca5ff), WTC(0x594530ff), WTC(0x59cb79ff), WTC(0x5a5047ff), WTC(0x5ad45eff), WTC(0x5b584e7f), WTC(0x5bdc417f),
+WTC(0x5c60487f), WTC(0x5ce476ff), WTC(0x5d68c47f), WTC(0x5ded06ff), WTC(0x5e7111ff), WTC(0x5ef4b5ff), WTC(0x5f77a17f), WTC(0x5ff96aff),
+WTC(0x6079a7ff), WTC(0x60f7f7ff), WTC(0x617417ff), WTC(0x61edd87f), WTC(0x6264ffff), WTC(0x62d9a6ff), WTC(0x634c817f), WTC(0x63be657f),
+WTC(0x6430277f), WTC(0x64a2247f), WTC(0x65142bff), WTC(0x6586027f), WTC(0x65f7697f), WTC(0x666801ff), WTC(0x66d756ff), WTC(0x6744f0ff),
+WTC(0x67b0787f), WTC(0x681a077f), WTC(0x6881ebff), WTC(0x68e8707f), WTC(0x694dceff), WTC(0x69b21e7f), WTC(0x6a156cff), WTC(0x6a77ca7f),
+WTC(0x6ad9377f), WTC(0x6b39a4ff), WTC(0x6b9901ff), WTC(0x6bf73cff), WTC(0x6c54457f), WTC(0x6cb00aff), WTC(0x6d0a7bff), WTC(0x6d6387ff),
+WTC(0xae2cbe01), WTC(0xaf526d01), WTC(0xb0751201), WTC(0xb194da81), WTC(0xb2b1f401), WTC(0xb3cc8d01), WTC(0xb4e4d201), WTC(0xb5faf101),
+WTC(0xb70f1881), WTC(0xb8217301), WTC(0xb9321181), WTC(0xba40ee01), WTC(0xbb4e0201), WTC(0xbc594781), WTC(0xbd62b881), WTC(0xbe6a5181),
+WTC(0xbf700d01), WTC(0xc073e4c0), WTC(0xc175d240), WTC(0xc275cc80), WTC(0xc373cb80), WTC(0xc46fca00), WTC(0xc569c600), WTC(0xc661bdc0),
+WTC(0xc757af80), WTC(0xc84b9840), WTC(0xc93d7300), WTC(0xca2d3a40), WTC(0xcb1aea40), WTC(0xcc068280), WTC(0xccf00480), WTC(0xcdd77200),
+WTC(0xcebccb40), WTC(0xcfa00d80), WTC(0xd0813540), WTC(0xd1603f00), WTC(0xd23d2980), WTC(0xd317f7c0), WTC(0xd3f0ac40), WTC(0xd4c74980),
+WTC(0xd59bcf80), WTC(0xd66e3b00), WTC(0xd73e8900), WTC(0xd80cb740), WTC(0xd8d8c7c0), WTC(0xd9a2be00), WTC(0xda6a9e40), WTC(0xdb306a40),
+WTC(0xdbf42080), WTC(0xdcb5be80), WTC(0xdd754140), WTC(0xde32a900), WTC(0xdeedf9c0), WTC(0xdfa737c0), WTC(0xe05e6740), WTC(0xe1138900),
+WTC(0xe1c69ac0), WTC(0xe2779a40), WTC(0xe3268680), WTC(0xe3d36260), WTC(0xe47e33a0), WTC(0xe526ff80), WTC(0xe5cdc960), WTC(0xe6729100),
+WTC(0xe7155460), WTC(0xe7b611c0), WTC(0xe854ca20), WTC(0xe8f18180), WTC(0xe98c3ca0), WTC(0xea24ffe0), WTC(0xeabbcb20), WTC(0xeb509b60),
+WTC(0xebe36d00), WTC(0xec743e00), WTC(0xed0310e0), WTC(0xed8feaa0), WTC(0xee1ad060), WTC(0xeea3c640), WTC(0xef2acd60), WTC(0xefafe6a0),
+WTC(0xf03312f0), WTC(0xf0b45800), WTC(0xf133c230), WTC(0xf1b15ef0), WTC(0xf22d3af0), WTC(0xf2a75c80), WTC(0xf31fc460), WTC(0xf39673b0),
+WTC(0xf40b6a00), WTC(0xf47ea230), WTC(0xf4f01450), WTC(0xf55fb930), WTC(0xf5cd84c0), WTC(0xf6396090), WTC(0xf6a333e0), WTC(0xf70ae540),
+WTC(0xf7707260), WTC(0xf7d3f720), WTC(0xf83592f0), WTC(0xf8956450), WTC(0xf8f38120), WTC(0xf94ff7c8), WTC(0xf9aad740), WTC(0xfa042920),
+WTC(0xfa5be110), WTC(0xfab1e778), WTC(0xfb062478), WTC(0xfb588d78), WTC(0xfba93530), WTC(0xfbf836c8), WTC(0xfc45ace0), WTC(0xfc91a294),
+WTC(0xfcdc0e5c), WTC(0xfd24e438), WTC(0xfd6c17dc), WTC(0xfdb19758), WTC(0xfdf54c3c), WTC(0xfe371ef8), WTC(0xfe7701aa), WTC(0xfeb50d62),
+WTC(0xfef1700a), WTC(0xff2c5574), WTC(0xff65ee7b), WTC(0xff9e75de), WTC(0xffd62863), WTC(0x000d4401), WTC(0x0043d345), WTC(0x00799cd0),
+WTC(0x00ae5f49), WTC(0x00e1d7a4), WTC(0x0113a6f2), WTC(0x0143575c), WTC(0x01707024), WTC(0x019a9346), WTC(0x01c1cf08), WTC(0x01e66c12),
+WTC(0x0208ac48), WTC(0x0228e868), WTC(0x0247a6c8), WTC(0x02657aa0), WTC(0x0282f710), WTC(0x02a07e50), WTC(0x02be31c0), WTC(0x02dc2b30),
+WTC(0x02fa7f34), WTC(0x0318fb10), WTC(0x03372fdc), WTC(0x0354ae54), WTC(0x03710d18), WTC(0x038bfdb4), WTC(0x03a54084), WTC(0x03bc92b8),
+WTC(0x03d1c710), WTC(0x03e4dd20), WTC(0x03f5e25c), WTC(0x0404e218), WTC(0x0411fc30), WTC(0x041d6b30), WTC(0x04276cd0), WTC(0x04303e00),
+WTC(0x04381528), WTC(0x043f2310), WTC(0x04459908), WTC(0x044ba430), WTC(0x045161f8), WTC(0x0456e6f8), WTC(0x045c49a8), WTC(0x046192f8),
+WTC(0x0466af40), WTC(0x046b8240), WTC(0x046ff0d8), WTC(0x0473de18), WTC(0x04772b58), WTC(0x0479b9a0), WTC(0x047b6a30), WTC(0x047c2088),
+WTC(0x047bc230), WTC(0x047a3418), WTC(0x04776098), WTC(0x04734790), WTC(0x046df4c0), WTC(0x04677220), WTC(0x045fd1b0), WTC(0x04573588),
+WTC(0x044dc4b8), WTC(0x0443a5b8), WTC(0x04390160), WTC(0x042e0398), WTC(0x0422d8c0), WTC(0x0417aa30), WTC(0x040c7ce0), WTC(0x040136e0),
+WTC(0x03f5beb0), WTC(0x03e9f8ec), WTC(0x03ddc484), WTC(0x03d0fd9c), WTC(0x03c37fa0), WTC(0x03b53014), WTC(0x03a60a18), WTC(0x03960f88),
+WTC(0x03854110), WTC(0x0373ad9c), WTC(0x03617694), WTC(0x034ebf9c), WTC(0x033bab30), WTC(0x03284ef0), WTC(0x0314b598), WTC(0x0300ea54),
+WTC(0x02ecf524), WTC(0x02d8d210), WTC(0x02c476ac), WTC(0x02afd940), WTC(0x029aee4c), WTC(0x0285a6f4), WTC(0x026ff398), WTC(0x0259c448),
+WTC(0x024317cc), WTC(0x022c0084), WTC(0x02149310), WTC(0x01fce334), WTC(0x01e4fb24), WTC(0x01ccdd0a), WTC(0x01b48b20), WTC(0x019c077e),
+WTC(0x01835432), WTC(0x016a733c), WTC(0x015166a6), WTC(0x0138302e), WTC(0x011ed0f6), WTC(0x010549f8), WTC(0x00eb9c25), WTC(0x00d1caa6),
+WTC(0x00b7db94), WTC(0x009dd560), WTC(0x0083be75), WTC(0x00699d41), WTC(0x004f782f), WTC(0x003555ab), WTC(0x001b3c21), WTC(0x000131fe),
+WTC(0xd61cfc40), WTC(0xd5acb340), WTC(0xd53d4400), WTC(0xd4cea6c0), WTC(0xd460d440), WTC(0xd3f3c440), WTC(0xd3876f80), WTC(0xd31bce40),
+WTC(0xd2b0d900), WTC(0xd2468980), WTC(0xd1dcef00), WTC(0xd17429c0), WTC(0xd10c5b80), WTC(0xd0a59b80), WTC(0xd03fd780), WTC(0xcfdae780),
+WTC(0xcf76a380), WTC(0xcf12fac0), WTC(0xceb01100), WTC(0xce4e18c0), WTC(0xcded4440), WTC(0xcd8d9a40), WTC(0xcd2ee800), WTC(0xccd0f440),
+WTC(0xcc738780), WTC(0xcc167d40), WTC(0xcbb9c180), WTC(0xcb5d4040), WTC(0xcb00e240), WTC(0xcaa48000), WTC(0xca47eac0), WTC(0xc9eaf1c0),
+WTC(0xc98d8100), WTC(0xc92fc580), WTC(0xc8d1fc80), WTC(0xc8746480), WTC(0xc816dc40), WTC(0xc7b8c280), WTC(0xc7596800), WTC(0xc6f81f80),
+WTC(0xc6945740), WTC(0xc62d93c0), WTC(0xc5c358c0), WTC(0xc5552b80), WTC(0xc4e29240), WTC(0xc46b1440), WTC(0xc3ee3840), WTC(0xc36b8500),
+WTC(0xc2e28040), WTC(0xc252ae80), WTC(0xc1bb9540), WTC(0xc11cc200), WTC(0xc075cf00), WTC(0xbfc65781), WTC(0xbf0df881), WTC(0xbe4c6f01),
+WTC(0xbd819401), WTC(0xbcad2d01), WTC(0xbbcfb981), WTC(0xbaeca681), WTC(0xba08e781), WTC(0xb9297081), WTC(0xb851e081), WTC(0xb782ed01),
+WTC(0xb6bc6a81), WTC(0xb5fe4981), WTC(0xb5487281), WTC(0xb49ad081), WTC(0xb3f54d81), WTC(0xb357d401), WTC(0xb2c24e01), WTC(0xb234a681),
+WTC(0xb1aec701), WTC(0xb1309b01), WTC(0xb0ba0c01), WTC(0xb04b0481), WTC(0xafe36f01), WTC(0xaf833601), WTC(0xaf2a4381), WTC(0xaed88201),
+WTC(0xae8ddb81), WTC(0xae4a3b81), WTC(0xae0d8b01), WTC(0xadd7b581), WTC(0xada8a481), WTC(0xad804281), WTC(0xad5e7a81), WTC(0xad433601),
+WTC(0xad2e6001), WTC(0xad1fe281), WTC(0xad17a801), WTC(0xad159a81), WTC(0xad19a501), WTC(0xad23b101), WTC(0xad33aa01), WTC(0xad497981),
+WTC(0xad650a01), WTC(0xad864601), WTC(0xadad1781), WTC(0xadd96981), WTC(0xae0b2601), WTC(0xae423781), WTC(0xae7e8801), WTC(0xaec00201),
+WTC(0xaf069081), WTC(0xaf521c81), WTC(0xafa29201), WTC(0xaff7da01), WTC(0xb051df01), WTC(0xb0b08c81), WTC(0xb113cb81), WTC(0xb17b8701),
+WTC(0xb1e7a981), WTC(0xb2581d81), WTC(0xb2cccc81), WTC(0xb345a181), WTC(0xb3c28701), WTC(0xb4436681), WTC(0xb4c82b81), WTC(0xb550bf81),
+WTC(0xb5dd0d01), WTC(0xb66cff01), WTC(0xb7007f01), WTC(0xb7977781), WTC(0xb831d381), WTC(0xb8cf7d01), WTC(0xb9705e01), WTC(0xba146101),
+WTC(0xbabb7081), WTC(0xbb657781), WTC(0xbc125f01), WTC(0xbcc21281), WTC(0xbd747b81), WTC(0xbe298581), WTC(0xbee11981), WTC(0xbf9b2301),
+WTC(0xc0578b80), WTC(0xc1163dc0), WTC(0xc1d72400), WTC(0xc29a28c0), WTC(0xc35f3640), WTC(0xc42636c0), WTC(0xc4ef1500), WTC(0xc5b9bb00),
+WTC(0xc6861340), WTC(0xc7540840), WTC(0xc8238400), WTC(0xc8f47100), WTC(0xc9c6b9c0), WTC(0xca9a4840), WTC(0xcb6f0780), WTC(0xcc44e140),
+WTC(0xcd1bc000), WTC(0xcdf38e00), WTC(0xcecc3600), WTC(0xcfa5a240), WTC(0xd07fbcc0), WTC(0xd15a7040), WTC(0xd235a6c0), WTC(0xd3114b00),
+WTC(0xd3ed4740), WTC(0xd4c98580), WTC(0xd5a5f080), WTC(0xd6827280), WTC(0xd75ef600), WTC(0xd83b6500), WTC(0xd917aa00), WTC(0xd9f3af80),
+WTC(0xdacf5fc0), WTC(0xdbaaa540), WTC(0xdc856a00), WTC(0xdd5f98c0), WTC(0xde391bc0), WTC(0xdf11dd40), WTC(0xdfe9c780), WTC(0xe0c0c540),
+WTC(0xe196c080), WTC(0xe26ba3c0), WTC(0xe33f5960), WTC(0xe411cba0), WTC(0xe4e2e500), WTC(0xe5b28fc0), WTC(0xe680b640), WTC(0xe74d42e0),
+WTC(0xe8181fe0), WTC(0xe8e137e0), WTC(0xe9a87500), WTC(0xea6dc1a0), WTC(0xeb310820), WTC(0xebf23300), WTC(0xecb12c60), WTC(0xed6ddee0),
+WTC(0xee2834a0), WTC(0xeee01800), WTC(0xef957380), WTC(0xf0483160), WTC(0xf0f83c00), WTC(0xf1a57db0), WTC(0xf24fe0f0), WTC(0xf2f74ff0),
+WTC(0xf39bb530), WTC(0xf43cfaf0), WTC(0xf4db0b90), WTC(0xf575d180), WTC(0xf60d3700), WTC(0xf6a12680), WTC(0xf7318a50), WTC(0xf7be4cc0),
+WTC(0xf8475850), WTC(0xf8cc9738), WTC(0xf94df3e0), WTC(0xf9cb58a8), WTC(0xfa44afe0), WTC(0xfab9e3e8), WTC(0xfb2adf20), WTC(0xfb978be8),
+WTC(0xfbffd488), WTC(0xfc63a370), WTC(0xfcc2e2f0), WTC(0xfd1d7d64), WTC(0xfd735d2c), WTC(0xfdc46c9c), WTC(0xfe109618), WTC(0xfe57c3f4),
+WTC(0xfe99e090), WTC(0xfed6d644), WTC(0xff0e8f6e), WTC(0xff40f667), WTC(0xff6df58c), WTC(0xff957738), WTC(0xffb765c5), WTC(0xffd3ab90),
+WTC(0xffea32f4), WTC(0xfffae64c), WTC(0x0005aff3), WTC(0x000a7a44), WTC(0x00092f9c), WTC(0x0001ba54), WTC(0xfff404ca), WTC(0xffdff957)
+};
+
+
+
+
+/*
+ * TNS_MAX_BANDS
+ * entry for each sampling rate
+ * 1 long window
+ * 2 SHORT window
+*/
+const UCHAR tns_max_bands_tbl[13][2] =
+{
+ { 31, 9 }, /* 96000 */
+ { 31, 9 }, /* 88200 */
+ { 34, 10 }, /* 64000 */
+ { 40, 14 }, /* 48000 */
+ { 42, 14 }, /* 44100 */
+ { 51, 14 }, /* 32000 */
+ { 46, 14 }, /* 24000 */
+ { 46, 14 }, /* 22050 */
+ { 42, 14 }, /* 16000 */
+ { 42, 14 }, /* 12000 */
+ { 42, 14 }, /* 11025 */
+ { 39, 14 }, /* 8000 */
+ { 39, 14 }, /* 7350 */
+};
+
+/* TNS_MAX_BANDS for low delay. The array index is sampleRateIndex-3 */
+const UCHAR tns_max_bands_tbl_480[5] = {
+ 31, /* 48000 */
+ 32, /* 44100 */
+ 37, /* 32000 */
+ 30, /* 24000 */
+ 30 /* 22050 */
+};
+const UCHAR tns_max_bands_tbl_512[5] = {
+ 31, /* 48000 */
+ 32, /* 44100 */
+ 37, /* 32000 */
+ 31, /* 24000 */
+ 31 /* 22050 */
+};
+
+#define TCC(x) (FIXP_DBL(x))
+
+const FIXP_TCC FDKaacDec_tnsCoeff3 [8] =
+{
+ TCC(0x81f1d1d4), TCC(0x9126146c), TCC(0xadb922c4), TCC(0xd438af1f),
+ TCC(0x00000000), TCC(0x3789809b), TCC(0x64130dd4), TCC(0x7cca7016)
+};
+const FIXP_TCC FDKaacDec_tnsCoeff4 [16] =
+{
+ TCC(0x808bc842), TCC(0x84e2e58c), TCC(0x8d6b49d1), TCC(0x99da920a),
+ TCC(0xa9c45713), TCC(0xbc9ddeb9), TCC(0xd1c2d51b), TCC(0xe87ae53d),
+ TCC(0x00000000), TCC(0x1a9cd9b6), TCC(0x340ff254), TCC(0x4b3c8c29),
+ TCC(0x5f1f5ebb), TCC(0x6ed9ebba), TCC(0x79bc385f), TCC(0x7f4c7e5b)
+};
+
+/* MPEG like mapping (no change). */
+const UCHAR channelMappingTablePassthrough[8][8] =
+{
+ { 0, 1,255,255,255,255,255,255}, /* mono / PS */
+ { 0, 1,255,255,255,255,255,255}, /* stereo */
+ { 0, 1, 2,255,255,255,255,255}, /* 3ch */
+ { 0, 1, 2, 3,255,255,255,255}, /* 4ch */
+ { 0, 1, 2, 3, 4,255,255,255}, /* 5ch */
+ { 0, 1, 2, 3, 4, 5,255,255}, /* 5.1ch */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
+ { 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1ch */
+};
+
+/* WAV file like mapping (from MPEG mapping). */
+const UCHAR channelMappingTableWAV[8][8] =
+{
+ { 0, 1,255,255,255,255,255,255}, /* mono / PS */
+ { 0, 1,255,255,255,255,255,255}, /* stereo */
+ { 2, 0, 1,255,255,255,255,255}, /* 3ch */
+ { 2, 0, 1, 3,255,255,255,255}, /* 4ch */
+ { 2, 0, 1, 3, 4,255,255,255}, /* 5ch */
+ { 2, 0, 1, 4, 5, 3,255,255}, /* 5.1ch */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
+ { 2, 0, 1, 6, 7, 4, 5, 3} /* 7.1ch */
+};
+
+/* Lookup tables for elements in ER bitstream */
+const MP4_ELEMENT_ID elementsTab[8][7] =
+{
+ {ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE }, /* 1 channel */
+ {ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE } /* 2 channels */
+ ,
+ {ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE,ID_NONE }, /* 3 channels */
+ {ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 4 channels */
+ {ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 5 channels */
+ {ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE }, /* 6 channels */
+ {ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END} /* 8 channels */
+};
+
+/*! Random sign bit used for concealment
+*/
+const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16] = {
+/*
+ sign bits of FDK_sbrDecoder_sbr_randomPhase[] entries:
+ LSB ........... MSB -> MSB ... LSB
+*/
+/* 1001 0111 0011 1100 -> */ 0x3ce9,
+/* 0100 0111 0111 1011 -> */ 0xdee2,
+/* 0001 1100 1110 1011 -> */ 0xd738,
+/* 0001 0011 0110 1001 -> */ 0x96c8,
+/* 0101 0011 1101 0000 -> */ 0x0bca,
+/* 0001 0001 1111 0100 -> */ 0x2f88,
+/* 1110 1100 1110 1101 -> */ 0xb737,
+/* 0010 1010 1011 1001 -> */ 0x9d54,
+/* 0111 1100 0110 1010 -> */ 0x563e,
+/* 1101 0111 0010 0101 -> */ 0xa4eb,
+/* 0001 0101 1011 1100 -> */ 0x3da8,
+/* 0101 0111 1001 1011 -> */ 0xd9ea,
+/* 1101 0100 0101 0101 -> */ 0xaa2b,
+/* 1000 1001 0100 0011 -> */ 0xc291,
+/* 1100 1111 1010 1100 -> */ 0x35f3,
+/* 1100 1010 1110 0010 -> */ 0x4753,
+/* 0110 0001 1010 1000 -> */ 0x1586,
+/* 0011 0101 1111 1100 -> */ 0x3fac,
+/* 0001 0110 1010 0001 -> */ 0x8568,
+/* 0010 1101 0111 0010 -> */ 0x4eb4,
+/* 1101 1010 0100 1001 -> */ 0x925b,
+/* 1100 1001 0000 1110 -> */ 0x7093,
+/* 1000 1100 0110 1010 -> */ 0x5631,
+/* 0000 1000 0110 1101 -> */ 0xb610,
+/* 1000 0001 1111 1011 -> */ 0xdf81,
+/* 1111 0011 0100 0111 -> */ 0xe2cf,
+/* 1000 0001 0010 1010 -> */ 0x5481,
+/* 1101 0101 1100 1111 -> */ 0xf3ab,
+/* 0110 0001 0110 1000 -> */ 0x1686,
+/* 0011 0011 1100 0110 -> */ 0x63cc,
+/* 0011 0111 0101 0110 -> */ 0x6aec,
+/* 1011 0001 1010 0010 -> */ 0x458d
+};
+
diff --git a/libAACdec/src/aac_rom.h b/libAACdec/src/aac_rom.h
new file mode 100644
index 0000000..313b813
--- /dev/null
+++ b/libAACdec/src/aac_rom.h
@@ -0,0 +1,125 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: Definition of constant tables
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef AAC_ROM_H
+#define AAC_ROM_H
+
+#include "common_fix.h"
+#include "FDK_audio.h"
+#include "aacdec_hcr_types.h"
+#include "aacdec_hcrs.h"
+
+#define AAC_NF_NO_RANDOM_VAL 512 /*!< Size of random number array for noise floor */
+
+#define INV_QUANT_TABLESIZE 256
+
+extern const FIXP_DBL InverseQuantTable [INV_QUANT_TABLESIZE + 1] ;
+extern const FIXP_DBL MantissaTable [4][14] ;
+extern const SCHAR ExponentTable [4][14] ;
+
+#define NUM_LD_COEF_512 1536
+#define NUM_LD_COEF_480 1440
+/* Window table partition exponents. */
+#define WTS0 (1)
+#define WTS1 (0)
+#define WTS2 (-2)
+extern const FIXP_WTB LowDelaySynthesis512[1536];
+extern const FIXP_WTB LowDelaySynthesis480[1440];
+
+typedef struct {
+ const SHORT *sfbOffsetLong;
+ const SHORT *sfbOffsetShort;
+ UCHAR numberOfSfbLong;
+ UCHAR numberOfSfbShort;
+} SFB_INFO;
+
+extern const SFB_INFO sfbOffsetTables[5][16];
+
+/* Huffman tables */
+enum {
+ HuffmanBits = 2,
+ HuffmanEntries = (1 << HuffmanBits)
+};
+
+typedef struct
+{
+ const USHORT (*CodeBook)[HuffmanEntries];
+ UCHAR Dimension;
+ UCHAR numBits;
+ UCHAR Offset;
+} CodeBookDescription;
+
+extern const CodeBookDescription AACcodeBookDescriptionTable[13];
+extern const CodeBookDescription AACcodeBookDescriptionSCL;
+
+
+extern const STATEFUNC aStateConstant2State[];
+
+extern const SCHAR aCodebook2StartInt[];
+
+extern const UCHAR aMinOfCbPair[];
+extern const UCHAR aMaxOfCbPair[];
+
+extern const UCHAR aMaxCwLen[];
+extern const UCHAR aDimCb[];
+extern const UCHAR aDimCbShift[];
+extern const UCHAR aSignCb[];
+extern const UCHAR aCbPriority[];
+
+extern const UINT *aHuffTable[];
+extern const SCHAR *aQuantTable[];
+
+extern const USHORT aLargestAbsoluteValue[];
+
+extern const UINT aHuffTreeRvlcEscape[];
+extern const UINT aHuffTreeRvlCodewds[];
+
+
+extern const UCHAR tns_max_bands_tbl[13][2];
+
+extern const UCHAR tns_max_bands_tbl_480[5];
+extern const UCHAR tns_max_bands_tbl_512[5];
+
+#define FIXP_TCC FIXP_DBL
+
+extern const FIXP_TCC FDKaacDec_tnsCoeff3[8];
+extern const FIXP_TCC FDKaacDec_tnsCoeff4[16];
+
+extern const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16];
+
+extern const FIXP_DBL pow2_div24minus1[47];
+extern const int offsetTab[2][16];
+
+/* Channel mapping indices for time domain I/O. First dimension is channel count-1. */
+extern const UCHAR channelMappingTablePassthrough[8][8];
+extern const UCHAR channelMappingTableWAV[8][8];
+
+/* Lookup tables for elements in ER bitstream */
+extern const MP4_ELEMENT_ID elementsTab[8][7];
+
+#endif /* #ifndef AAC_ROM_H */
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
new file mode 100644
index 0000000..58abea2
--- /dev/null
+++ b/libAACdec/src/aacdec_drc.cpp
@@ -0,0 +1,997 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Christian Griebel
+ Description: Dynamic range control (DRC) decoder tool for AAC
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "aacdec_drc.h"
+
+
+#include "channelinfo.h"
+#include "aac_rom.h"
+
+ #include "sbrdecoder.h"
+
+/*
+ * Dynamic Range Control
+ */
+
+/* For parameter conversion */
+#define DRC_PARAMETER_BITS ( 7 )
+#define DRC_MAX_QUANT_STEPS ( 1<<DRC_PARAMETER_BITS )
+#define DRC_MAX_QUANT_FACTOR ( DRC_MAX_QUANT_STEPS-1 )
+#define DRC_PARAM_QUANT_STEP ( FL2FXCONST_DBL(1.0f/(float)DRC_MAX_QUANT_STEPS) )
+#define DRC_PARAM_SCALE ( 1 )
+
+#define MAX_REFERENCE_LEVEL ( 127 )
+
+ #define DVB_ANC_DATA_SYNC_BYTE ( 0xBC ) /* DVB ancillary data sync byte. */
+
+/*!
+ \brief Initialize DRC information
+
+ \self Handle of DRC info
+
+ \return none
+*/
+void aacDecoder_drcInit (
+ HANDLE_AAC_DRC self )
+{
+ CDrcParams *pParams;
+
+ if (self == NULL) {
+ return;
+ }
+
+ /* init control fields */
+ self->enable = 0;
+ self->numThreads = 0;
+ self->digitalNorm = 0;
+
+ /* init params */
+ pParams = &self->params;
+ pParams->bsDelayEnable = 0;
+ pParams->cut = FL2FXCONST_DBL(0.0f);
+ pParams->boost = FL2FXCONST_DBL(0.0f);
+ pParams->targetRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
+ pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
+
+ /* initial program ref level = target ref level */
+ self->progRefLevel = pParams->targetRefLevel;
+}
+
+
+/*!
+ \brief Initialize DRC control data for one channel
+
+ \self Handle of DRC info
+
+ \return none
+*/
+void aacDecoder_drcInitChannelData (
+ CDrcChannelData *pDrcChData )
+{
+ if (pDrcChData != NULL) {
+ pDrcChData->expiryCount = 0;
+ pDrcChData->numBands = 1;
+ pDrcChData->bandTop[0] = (1024 >> 2) - 1;
+ pDrcChData->drcValue[0] = 0;
+ pDrcChData->drcInterpolationScheme = 0;
+ }
+}
+
+
+/*!
+ \brief Set one single DRC parameter
+
+ \self Handle of DRC info.
+ \param Parameter to be set.
+ \value Value to be set.
+
+ \return an error code.
+*/
+AAC_DECODER_ERROR aacDecoder_drcSetParam (
+ HANDLE_AAC_DRC self,
+ AACDEC_DRC_PARAM param,
+ INT value )
+{
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+
+ switch (param)
+ {
+ case DRC_CUT_SCALE:
+ /* set attenuation scale factor */
+ if ( (value < 0)
+ || (value > DRC_MAX_QUANT_FACTOR) ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.cut = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)(value+1));
+ break;
+ case DRC_BOOST_SCALE:
+ /* set boost factor */
+ if ( (value < 0)
+ || (value > DRC_MAX_QUANT_FACTOR) ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.boost = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)(value+1));
+ break;
+ case TARGET_REF_LEVEL:
+ if ( value > MAX_REFERENCE_LEVEL
+ || value < -MAX_REFERENCE_LEVEL ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ if (value < 0) {
+ self->digitalNorm = 0;
+ }
+ else {
+ /* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */
+ self->digitalNorm = 1;
+ self->progRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
+ self->params.targetRefLevel = value;
+ }
+ break;
+ case APPLY_HEAVY_COMPRESSION:
+ if (value < 0 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.applyHeavyCompression = (UCHAR)value;
+ break;
+ case DRC_BS_DELAY:
+ if (value < 0 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.bsDelayEnable = value;
+ break;
+ case DRC_DATA_EXPIRY_FRAME:
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->params.expiryFrame = (UINT)value;
+ break;
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ } /* switch(param) */
+
+ /* switch on/off processing */
+ self->enable = ( (self->params.boost > (FIXP_DBL)0)
+ || (self->params.cut > (FIXP_DBL)0)
+ || (self->params.applyHeavyCompression != 0)
+ || (self->digitalNorm == 1) );
+
+
+ return ErrorStatus;
+}
+
+
+static int parseExcludedChannels( UINT *excludedChnsMask,
+ HANDLE_FDK_BITSTREAM bs )
+{
+ UINT excludeMask = 0;
+ UINT i, j;
+ int bitCnt = 9;
+
+ for (i = 0, j = 1; i < 7; i++, j<<=1) {
+ if (FDKreadBits(bs,1)) {
+ excludeMask |= j;
+ }
+ }
+
+ /* additional_excluded_chns */
+ while (FDKreadBits(bs,1)) {
+ for (i = 0; i < 7; i++, j<<=1) {
+ if (FDKreadBits(bs,1)) {
+ excludeMask |= j;
+ }
+ }
+ bitCnt += 9;
+ FDK_ASSERT(j < (UINT)-1);
+ }
+
+ *excludedChnsMask = excludeMask;
+
+ return (bitCnt);
+}
+
+
+/*!
+ \brief Save DRC payload bitstream position
+
+ \self Handle of DRC info
+ \bs Handle of FDK bitstream
+
+ \return The number of DRC payload bits
+*/
+int aacDecoder_drcMarkPayload (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM bs,
+ AACDEC_DRC_PAYLOAD_TYPE type )
+{
+ UINT bsStartPos;
+ int i, numBands = 1, bitCnt = 0;
+
+ if (self == NULL) {
+ return 0;
+ }
+
+ bsStartPos = FDKgetValidBits(bs);
+
+ switch (type) {
+ case MPEG_DRC_EXT_DATA:
+ {
+ bitCnt = 4;
+
+ if (FDKreadBits(bs,1)) { /* pce_tag_present */
+ FDKreadBits(bs,8); /* pce_instance_tag + drc_tag_reserved_bits */
+ bitCnt+=8;
+ }
+
+ if (FDKreadBits(bs,1)) { /* excluded_chns_present */
+ FDKreadBits(bs,7); /* exclude mask [0..7] */
+ bitCnt+=8;
+ while (FDKreadBits(bs,1)) { /* additional_excluded_chns */
+ FDKreadBits(bs,7); /* exclude mask [x..y] */
+ bitCnt+=8;
+ }
+ }
+
+ if (FDKreadBits(bs,1)) { /* drc_bands_present */
+ numBands += FDKreadBits(bs, 4); /* drc_band_incr */
+ FDKreadBits(bs,4); /* reserved */
+ bitCnt+=8;
+ for (i = 0; i < numBands; i++) {
+ FDKreadBits(bs,8); /* drc_band_top[i] */
+ bitCnt+=8;
+ }
+ }
+
+ if (FDKreadBits(bs,1)) { /* prog_ref_level_present */
+ FDKreadBits(bs,8); /* prog_ref_level + prog_ref_level_reserved_bits */
+ bitCnt+=8;
+ }
+
+ for (i = 0; i < numBands; i++) {
+ FDKreadBits(bs,8); /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */
+ bitCnt+=8;
+ }
+
+ if ( (self->numPayloads < MAX_DRC_THREADS)
+ && ((INT)FDKgetValidBits(bs) >= 0) )
+ {
+ self->drcPayloadPosition[self->numPayloads++] = bsStartPos;
+ }
+ }
+ break;
+
+ case DVB_DRC_ANC_DATA:
+ /* check sync word */
+ if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE)
+ {
+ int dmxLevelsPresent, compressionPresent;
+ int coarseGrainTcPresent, fineGrainTcPresent;
+
+ bitCnt+=8;
+
+ /* bs_info field */
+ FDKreadBits(bs, 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */
+ bitCnt+=8;
+
+ /* Evaluate ancillary_data_status */
+ FDKreadBits(bs, 3); /* reserved, set to 0 */
+ dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
+ FDKreadBits(bs, 1); /* reserved, set to 0 */
+ compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
+ coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
+ fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
+ bitCnt+=8;
+
+ /* MPEG4 downmixing levels */
+ if (dmxLevelsPresent) {
+ FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
+ bitCnt+=8;
+ }
+ /* audio coding mode and compression status */
+ if (compressionPresent) {
+ FDKreadBits(bs, 16); /* audio_coding_mode, Compression_value */
+ bitCnt+=16;
+ }
+ /* coarse grain timecode */
+ if (coarseGrainTcPresent) {
+ FDKreadBits(bs, 16); /* coarse_grain_timecode */
+ bitCnt+=16;
+ }
+ /* fine grain timecode */
+ if (fineGrainTcPresent) {
+ FDKreadBits(bs, 16); /* fine_grain_timecode */
+ bitCnt+=16;
+ }
+ if ( !self->dvbAncDataAvailable
+ && ((INT)FDKgetValidBits(bs) >= 0) )
+ {
+ self->dvbAncDataPosition = bsStartPos;
+ self->dvbAncDataAvailable = 1;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return (bitCnt);
+}
+
+
+/*!
+ \brief Parse DRC parameters from bitstream
+
+ \bs Handle of FDK bitstream (in)
+ \pDrcBs Pointer to DRC payload data container (out)
+ \payloadPosition Bitstream position of MPEG DRC data junk (in)
+
+ \return Number of bits read (0 in case of a parse error)
+*/
+static int aacDecoder_drcParse (
+ HANDLE_FDK_BITSTREAM bs,
+ CDrcPayload *pDrcBs,
+ UINT payloadPosition )
+{
+ int i, numBands, bitCnt = 4;
+
+ /* Move to the beginning of the DRC payload field */
+ FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
+
+ /* pce_tag_present */
+ if (FDKreadBits(bs,1))
+ {
+ pDrcBs->pceInstanceTag = FDKreadBits(bs, 4); /* pce_instance_tag */
+ /* only one program supported */
+ FDKreadBits(bs, 4); /* drc_tag_reserved_bits */
+ bitCnt += 8;
+ } else {
+ pDrcBs->pceInstanceTag = -1; /* not present */
+ }
+
+ if (FDKreadBits(bs,1)) { /* excluded_chns_present */
+ /* get excluded_chn_mask */
+ bitCnt += parseExcludedChannels(&pDrcBs->excludedChnsMask, bs);
+ } else {
+ pDrcBs->excludedChnsMask = 0;
+ }
+
+ numBands = 1;
+ if (FDKreadBits(bs,1)) /* drc_bands_present */
+ {
+ /* get band_incr */
+ numBands += FDKreadBits(bs, 4); /* drc_band_incr */
+ pDrcBs->channelData.drcInterpolationScheme = FDKreadBits(bs, 4); /* drc_interpolation_scheme */
+ bitCnt += 8;
+ /* band_top */
+ for (i = 0; i < numBands; i++)
+ {
+ pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8); /* drc_band_top[i] */
+ bitCnt += 8;
+ }
+ }
+ else {
+ pDrcBs->channelData.bandTop[0] = 255;
+ }
+
+ pDrcBs->channelData.numBands = numBands;
+
+ if (FDKreadBits(bs,1)) /* prog_ref_level_present */
+ {
+ pDrcBs->progRefLevel = FDKreadBits(bs, 7); /* prog_ref_level */
+ FDKreadBits(bs, 1); /* prog_ref_level_reserved_bits */
+ bitCnt += 8;
+ } else {
+ pDrcBs->progRefLevel = -1;
+ }
+
+ for (i = 0; i < numBands; i++)
+ {
+ pDrcBs->channelData.drcValue[i] = FDKreadBits(bs, 1) << 7; /* dyn_rng_sgn[i] */
+ pDrcBs->channelData.drcValue[i] |= FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */
+ bitCnt += 8;
+ }
+
+ /* Set DRC payload type */
+ pDrcBs->type = MPEG_DRC_EXT_DATA;
+
+ return (bitCnt);
+}
+
+
+/*!
+ \brief Parse heavy compression value transported in DSEs of DVB streams with MPEG-4 content.
+
+ \bs Handle of FDK bitstream (in)
+ \pDrcBs Pointer to DRC payload data container (out)
+ \payloadPosition Bitstream position of DVB ancillary data junk
+
+ \return Number of bits read (0 in case of a parse error)
+*/
+#define DVB_COMPRESSION_SCALE ( 8 ) /* 48,164 dB */
+
+static int aacDecoder_drcReadCompression (
+ HANDLE_FDK_BITSTREAM bs,
+ CDrcPayload *pDrcBs,
+ UINT payloadPosition )
+{
+ int bitCnt = 0;
+ int dmxLevelsPresent, compressionPresent;
+ int coarseGrainTcPresent, fineGrainTcPresent;
+
+ /* Move to the beginning of the DRC payload field */
+ FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
+
+ /* Sanity checks */
+ if ( FDKgetValidBits(bs) < 24 ) {
+ return 0;
+ }
+
+ /* Check sync word */
+ if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) {
+ return 0;
+ }
+
+ /* Evaluate bs_info field */
+ if (FDKreadBits(bs, 2) != 3) { /* mpeg_audio_type */
+ /* No MPEG-4 audio data */
+ return 0;
+ }
+ FDKreadBits(bs, 2); /* dolby_surround_mode */
+ FDKreadBits(bs, 2); /* presentation_mode */
+ if (FDKreadBits(bs, 2) != 0) { /* reserved, set to 0 */
+ return 0;
+ }
+
+ /* Evaluate ancillary_data_status */
+ if (FDKreadBits(bs, 3) != 0) { /* reserved, set to 0 */
+ return 0;
+ }
+ dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
+ if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
+ return 0;
+ }
+ compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
+ coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
+ fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
+ bitCnt += 24;
+
+ if (dmxLevelsPresent) {
+ FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
+ bitCnt += 8;
+ }
+
+ /* audio_coding_mode_and_compression_status */
+ if (compressionPresent)
+ {
+ UCHAR compressionOn, compressionValue;
+
+ /* audio_coding_mode */
+ if ( FDKreadBits(bs, 7) != 0 ) { /* The reserved bits shall be set to "0". */
+ return 0;
+ }
+ compressionOn = (UCHAR)FDKreadBits(bs, 1); /* compression_on */
+ compressionValue = (UCHAR)FDKreadBits(bs, 8); /* Compression_value */
+ bitCnt += 16;
+
+ if ( compressionOn ) {
+ /* A compression value is available so store the data just like MPEG DRC data */
+ pDrcBs->channelData.drcValue[0] = compressionValue;
+ pDrcBs->channelData.numBands = 1; /* one value for all bands */
+ pDrcBs->pceInstanceTag = -1; /* not present */
+ pDrcBs->progRefLevel = -1; /* not present */
+ } else {
+ /* No compression value available */
+ /* CAUTION: It is not clearly defined by standard how to react in this situation. */
+ pDrcBs->channelData.drcValue[0] = 0x7F; /* 0dB */
+ pDrcBs->channelData.bandTop[0] = 0;
+
+ /* If compression_on field is set to "0" the compression_value field shall be "0000 0000". */
+ if (compressionValue != 0) {
+ return 0;
+ }
+ }
+ /* Set DRC payload type now because the payload seems to be correct. */
+ pDrcBs->type = DVB_DRC_ANC_DATA;
+ }
+
+ /* Read timecodes if available just to get the right amount of bits. */
+ if (coarseGrainTcPresent) {
+ FDKreadBits(bs, 16); /* coarse_grain_timecode */
+ bitCnt += 16;
+ }
+ if (fineGrainTcPresent) {
+ FDKreadBits(bs, 16); /* fine_grain_timecode */
+ bitCnt += 16;
+ }
+
+ return (bitCnt);
+}
+
+
+/*
+ * Prepare DRC processing
+ */
+static int aacDecoder_drcExtractAndMap (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
+ int validChannels )
+{
+ CDrcPayload threadBs[MAX_DRC_THREADS];
+ CDrcPayload *validThreadBs[MAX_DRC_THREADS];
+ UINT backupBsPosition;
+ int i, thread, validThreads = 0;
+ int numExcludedChns[MAX_DRC_THREADS];
+
+ self->numThreads = 0;
+ backupBsPosition = FDKgetValidBits(hBs);
+
+ for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; i++) {
+ int bitsParsed;
+
+ /* Init payload data chunk. The memclear is very important because it initializes
+ the most values. Without it the module wouldn't work properly or crash. */
+ FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
+ threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;
+
+ /* Extract payload */
+ bitsParsed = aacDecoder_drcParse( hBs,
+ &threadBs[self->numThreads],
+ self->drcPayloadPosition[i] );
+ if (bitsParsed > 0) {
+ self->numThreads++;
+ }
+ }
+ self->numPayloads = 0;
+
+ if (self->dvbAncDataAvailable)
+ { /* Append a DVB heavy compression payload thread if available. */
+ int bitsParsed;
+
+ /* Init payload data chunk. The memclear is very important because it initializes
+ the most values. Without it the module wouldn't work properly or crash. */
+ FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
+ threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;
+
+ /* Extract payload */
+ bitsParsed = aacDecoder_drcReadCompression( hBs,
+ &threadBs[self->numThreads],
+ self->dvbAncDataPosition );
+ if (bitsParsed > 0) {
+ self->numThreads++;
+ }
+ }
+ self->dvbAncDataAvailable = 0;
+
+ /* Reset the bitbufffer */
+ FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - backupBsPosition);
+
+ /* calculate number of valid bits in excl_chn_mask */
+
+ /* coupling channels not supported */
+
+ /* check for valid threads */
+ for (thread = 0; thread < self->numThreads; thread++) {
+ CDrcPayload *pThreadBs = &threadBs[thread];
+ int numExclChns = 0;
+
+ switch (pThreadBs->type) {
+ default:
+ continue;
+ case MPEG_DRC_EXT_DATA:
+ case DVB_DRC_ANC_DATA:
+ break;
+ }
+
+ if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */
+ if (pThreadBs->pceInstanceTag != pceInstanceTag) {
+ continue; /* don't accept */
+ }
+ }
+
+ /* calculate number of excluded channels */
+ if (pThreadBs->excludedChnsMask > 0) {
+ INT exclMask = pThreadBs->excludedChnsMask;
+ int ch;
+ for (ch = 0; ch < validChannels; ch++) {
+ numExclChns += exclMask & 0x1;
+ exclMask >>= 1;
+ }
+ }
+ if (numExclChns < validChannels) {
+ validThreadBs[validThreads] = pThreadBs;
+ numExcludedChns[validThreads] = numExclChns;
+ validThreads++;
+ }
+ }
+
+ if (validThreads > 1) {
+ int ch;
+
+ /* check consistency of excl_chn_mask amongst valid DRC threads */
+ for (ch = 0; ch < validChannels; ch++) {
+ int present = 0;
+
+ for (thread = 0; thread < validThreads; thread++) {
+ CDrcPayload *pThreadBs = validThreadBs[thread];
+
+
+ /* thread applies to this channel */
+ if ( (pThreadBs->type == MPEG_DRC_EXT_DATA)
+ && ( (numExcludedChns[thread] == 0)
+ || (!(pThreadBs->excludedChnsMask & (1<<ch))) ) ) {
+ present++;
+ }
+ }
+
+
+ if (present > 1) {
+ return -1;
+ }
+ }
+ }
+
+ /* map DRC bitstream information onto DRC channel information */
+ for (thread = 0; thread < validThreads; thread++)
+ {
+ CDrcPayload *pThreadBs = validThreadBs[thread];
+ INT exclMask = pThreadBs->excludedChnsMask;
+ int ch;
+
+ /* last progRefLevel transmitted is the one that is used
+ * (but it should really only be transmitted once per block!)
+ */
+ if (pThreadBs->progRefLevel >= 0) {
+ self->progRefLevel = pThreadBs->progRefLevel;
+ }
+
+ /* SCE, CPE and LFE */
+ for (ch = 0; ch < validChannels; ch++) {
+ int mapedChannel = channelMapping[ch];
+
+ if ( ((exclMask & (1<<mapedChannel)) == 0)
+ && ( ( self->params.applyHeavyCompression && (pThreadBs->type == DVB_DRC_ANC_DATA))
+ || (!self->params.applyHeavyCompression && (pThreadBs->type == MPEG_DRC_EXT_DATA)) )
+ ) {
+ /* copy thread to channel */
+ pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
+ }
+ }
+ /* CCEs not supported by now */
+ }
+
+ return 0;
+}
+
+
+void aacDecoder_drcApply (
+ HANDLE_AAC_DRC self,
+ void *pSbrDec,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CDrcChannelData *pDrcChData,
+ int ch, /* needed only for SBR */
+ int aacFrameSize,
+ int bSbrPresent )
+{
+ int band, top, bin, numBands;
+ int bottom = 0;
+
+ FIXP_DBL max_mantissa;
+ INT max_exponent;
+
+ FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.0f);
+ INT norm_exponent = 0;
+
+ FIXP_DBL fact_mantissa[MAX_DRC_BANDS];
+ INT fact_exponent[MAX_DRC_BANDS];
+
+ CDrcParams *pParams = &self->params;
+
+ FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+ SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
+
+ int winSeq = pIcsInfo->WindowSequence;
+
+ /* Increment and check expiry counter */
+ if ( (pParams->expiryFrame > 0)
+ && (++pDrcChData->expiryCount > pParams->expiryFrame) )
+ { /* The DRC data is too old, so delete it. */
+ aacDecoder_drcInitChannelData( pDrcChData );
+ }
+
+ if (!self->enable) {
+ sbrDecoder_drcDisable( (HANDLE_SBRDECODER)pSbrDec, ch );
+ return;
+ }
+
+ numBands = pDrcChData->numBands;
+ top = FDKmax(0, numBands-1);
+
+ pDrcChData->bandTop[0] = fixMin(pDrcChData->bandTop[0], (aacFrameSize >> 2) - 1);
+
+ /* If program reference normalization is done in the digital domain,
+ modify factor to perform normalization. prog_ref_level can
+ alternatively be passed to the system for modification of the level in
+ the analog domain. Analog level modification avoids problems with
+ reduced DAC SNR (if signal is attenuated) or clipping (if signal is
+ boosted) */
+
+ if (self->digitalNorm == 1)
+ {
+ /* 0.5^((targetRefLevel - progRefLevel)/24) */
+ norm_mantissa = fLdPow(
+ FL2FXCONST_DBL(-1.0), /* log2(0.5) */
+ 0,
+ (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f/24.0)>>3) * (INT)(pParams->targetRefLevel-self->progRefLevel)),
+ 3,
+ &norm_exponent );
+ }
+ else {
+ norm_mantissa = FL2FXCONST_DBL(0.5f);
+ norm_exponent = 1;
+ }
+
+
+ /* calc scale factors */
+ for (band = 0; band < numBands; band++)
+ {
+ UCHAR drcVal = pDrcChData->drcValue[band];
+ top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize);
+
+ if ( pParams->applyHeavyCompression ) {
+ INT compressionFactorVal_e;
+ int valX = drcVal >> 4;
+ int valY = drcVal & 0x0F;
+
+ /* calculate the unscaled heavy compression factor.
+ compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB
+ range: -48.166 dB to 48.164 dB */
+ if ( drcVal != 0x7F ) {
+ fact_mantissa[band] =
+ fPowInt( FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */
+ 0,
+ valY,
+ &compressionFactorVal_e );
+
+ /* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */
+ fact_mantissa[band] = fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]);
+
+ fact_exponent[band] = DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e;
+ }
+ else {
+ fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
+ fact_exponent[band] = 1;
+ }
+ } else
+ {
+ /* apply the scaled dynamic range control words to factor.
+ * if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0
+ * then there is no dynamic range compression
+ *
+ * if pDrcChData->drcSgn[band] is
+ * 1 then gain is < 1 : factor = 2^(-self->cut * pDrcChData->drcMag[band] / 24)
+ * 0 then gain is > 1 : factor = 2^( self->boost * pDrcChData->drcMag[band] / 24)
+ */
+
+ if ((drcVal&0x7F) > 0) {
+ FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost;
+
+ fact_mantissa[band] =
+ f2Pow( (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f/192.0f), tParamVal) * (drcVal&0x7F)),
+ 3+DRC_PARAM_SCALE,
+ &fact_exponent[band] );
+ }
+ else {
+ fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
+ fact_exponent[band] = 1;
+ }
+ }
+
+ fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa);
+ fact_exponent[band] += norm_exponent;
+
+
+ bottom = top;
+
+ } /* end loop over bands */
+
+
+ /* normalizations */
+ {
+ int res;
+
+ max_mantissa = FL2FXCONST_DBL(0.0f);
+ max_exponent = 0;
+ for (band = 0; band < numBands; band++) {
+ max_mantissa = fixMax(max_mantissa, fact_mantissa[band]);
+ max_exponent = fixMax(max_exponent, fact_exponent[band]);
+ }
+
+ /* left shift factors to gain accurancy */
+ res = CntLeadingZeros(max_mantissa) - 1;
+
+ /* above topmost DRC band gain factor is 1 */
+ if (((pDrcChData->bandTop[numBands-1]+1)<<2) < aacFrameSize) res = 0;
+
+ if (res > 0) {
+ res = fixMin(res, max_exponent);
+ max_exponent -= res;
+
+ for (band = 0; band < numBands; band++) {
+ fact_mantissa[band] <<= res;
+ fact_exponent[band] -= res;
+ }
+ }
+
+ /* normalize magnitudes to one scale factor */
+ for (band = 0; band < numBands; band++) {
+ if (fact_exponent[band] < max_exponent) {
+ fact_mantissa[band] >>= max_exponent - fact_exponent[band];
+ }
+ }
+ }
+
+ /* apply factor to spectral lines
+ * short blocks must take care that bands fall on
+ * block boundaries!
+ */
+ if (!bSbrPresent)
+ {
+ bottom = 0;
+
+ for (band = 0; band < numBands; band++)
+ {
+ top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize); /* ... * DRC_BAND_MULT; */
+
+ for (bin = bottom; bin < top; bin++) {
+ pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact_mantissa[band]);
+ }
+
+ bottom = top;
+ }
+
+ /* above topmost DRC band gain factor is 1 */
+ if (max_exponent > 0) {
+ FIXP_DBL fact = FL2FXCONST_DBL(0.5f) >> (max_exponent - 1);
+
+ for (bin = top; bin < aacFrameSize; bin++) {
+ pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact);
+ }
+ }
+
+ /* adjust scaling */
+ pSpecScale[0] += max_exponent;
+
+ if (winSeq == EightShortSequence) {
+ int win;
+ for (win = 1; win < 8; win++) {
+ pSpecScale[win] += max_exponent;
+ }
+ }
+ }
+ else {
+ HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec;
+
+ /* feed factors into SBR decoder for application in QMF domain. */
+ sbrDecoder_drcFeedChannel (
+ hSbrDecoder,
+ ch,
+ pDrcChData->numBands,
+ fact_mantissa,
+ max_exponent,
+ pDrcChData->drcInterpolationScheme,
+ winSeq,
+ pDrcChData->bandTop
+ );
+ }
+
+ return;
+}
+
+
+/*
+ * Prepare DRC processing
+ */
+int aacDecoder_drcProlog (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
+ int validChannels )
+{
+ int err = 0;
+
+ if (self == NULL) {
+ return -1;
+ }
+
+ if (!self->params.bsDelayEnable)
+ {
+ err = aacDecoder_drcExtractAndMap (
+ self,
+ hBs,
+ pAacDecoderStaticChannelInfo,
+ pceInstanceTag,
+ channelMapping,
+ validChannels );
+ }
+
+ return err;
+}
+
+
+/*
+ * Finalize DRC processing
+ */
+int aacDecoder_drcEpilog (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
+ int validChannels )
+{
+ int err = 0;
+
+ if (self == NULL) {
+ return -1;
+ }
+
+ if (self->params.bsDelayEnable)
+ {
+ err = aacDecoder_drcExtractAndMap (
+ self,
+ hBs,
+ pAacDecoderStaticChannelInfo,
+ pceInstanceTag,
+ channelMapping,
+ validChannels );
+ }
+
+ return err;
+}
+
diff --git a/libAACdec/src/aacdec_drc.h b/libAACdec/src/aacdec_drc.h
new file mode 100644
index 0000000..c48a720
--- /dev/null
+++ b/libAACdec/src/aacdec_drc.h
@@ -0,0 +1,105 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Christian Griebel
+ Description: Dynamic range control (DRC) decoder tool for AAC
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef AACDEC_DRC_H
+#define AACDEC_DRC_H
+
+#include "tp_data.h" /* for program config element support */
+
+
+#include "aacdec_drc_types.h"
+#include "channel.h"
+#include "FDK_bitstream.h"
+
+#define AACDEC_DRC_DEFAULT_REF_LEVEL ( 108 ) /* -27 dB below full scale (typical for movies) */
+#define AACDEC_DRC_DFLT_EXPIRY_FRAMES ( 40 ) /* Default DRC data expiry time in AAC frames */
+#define MAX_SBR_SYN_CHAN ( 64 )
+#define MAX_SBR_COLS ( 32 )
+
+
+/**
+ * \brief DRC module setting parameters
+ */
+typedef enum
+{
+ DRC_CUT_SCALE = 0,
+ DRC_BOOST_SCALE,
+ TARGET_REF_LEVEL,
+ DRC_BS_DELAY,
+ DRC_DATA_EXPIRY_FRAME,
+ APPLY_HEAVY_COMPRESSION
+
+} AACDEC_DRC_PARAM;
+
+
+/**
+ * \brief DRC module interface functions
+ */
+void aacDecoder_drcInit (
+ HANDLE_AAC_DRC self );
+
+void aacDecoder_drcInitChannelData (
+ CDrcChannelData *pDrcChannel );
+
+AAC_DECODER_ERROR aacDecoder_drcSetParam (
+ HANDLE_AAC_DRC self,
+ AACDEC_DRC_PARAM param,
+ INT value );
+
+int aacDecoder_drcMarkPayload (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ AACDEC_DRC_PAYLOAD_TYPE type );
+
+int aacDecoder_drcProlog (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[],
+ int numChannels );
+
+void aacDecoder_drcApply (
+ HANDLE_AAC_DRC self,
+ void *pSbrDec,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CDrcChannelData *pDrcDat,
+ int ch,
+ int aacFrameSize,
+ int bSbrPresent );
+
+int aacDecoder_drcEpilog (
+ HANDLE_AAC_DRC self,
+ HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ UCHAR pceInstanceTag,
+ UCHAR channelMapping[],
+ int validChannels );
+
+
+#endif /* AACDEC_DRC_H */
diff --git a/libAACdec/src/aacdec_drc_types.h b/libAACdec/src/aacdec_drc_types.h
new file mode 100644
index 0000000..20a593b
--- /dev/null
+++ b/libAACdec/src/aacdec_drc_types.h
@@ -0,0 +1,104 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2010)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Christian Griebel
+ Description: Dynamic range control (DRC) global data types
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef AACDEC_DRC_TYPES_H
+#define AACDEC_DRC_TYPES_H
+
+
+
+#include "common_fix.h"
+
+ #define MAX_DRC_THREADS ( 3 ) /* Heavy compression value is handled just like MPEG DRC data */
+#define MAX_DRC_BANDS ( 16 ) /* 2^LEN_DRC_BAND_INCR (LEN_DRC_BAND_INCR = 4) */
+
+/**
+ * \brief DRC module global data types
+ */
+typedef enum
+{
+ UNKNOWN_PAYLOAD = 0,
+ MPEG_DRC_EXT_DATA,
+ DVB_DRC_ANC_DATA
+
+} AACDEC_DRC_PAYLOAD_TYPE;
+
+typedef struct
+{
+ UINT expiryCount;
+ UINT numBands;
+ USHORT bandTop[MAX_DRC_BANDS];
+ SHORT drcInterpolationScheme;
+ UCHAR drcValue[MAX_DRC_BANDS];
+
+} CDrcChannelData;
+
+typedef struct
+{
+ AACDEC_DRC_PAYLOAD_TYPE type;
+ UINT excludedChnsMask;
+ SCHAR progRefLevel;
+ SCHAR pceInstanceTag;
+
+ CDrcChannelData channelData;
+
+} CDrcPayload;
+
+typedef struct
+{
+ FIXP_DBL cut;
+ FIXP_DBL boost;
+
+ UINT expiryFrame;
+ SCHAR targetRefLevel;
+ UCHAR bsDelayEnable;
+ UCHAR applyHeavyCompression;
+
+} CDrcParams;
+
+
+typedef struct
+{
+ CDrcParams params; /* Module parameters that can be set by user (via SetParam API function) */
+
+ UCHAR enable; /* Switch that controls dynamic range processing */
+ UCHAR digitalNorm; /* Switch to en-/disable reference level normalization in digital domain */
+
+ USHORT numPayloads; /* The number of DRC data payload elements found within frame */
+ USHORT numThreads; /* The number of DRC data threads extracted from the found payload elements */
+ SCHAR progRefLevel; /* Program reference level for all channels */
+
+ UCHAR dvbAncDataAvailable; /* Flag that indicates whether DVB ancillary data is present or not */
+ UINT dvbAncDataPosition; /* Used to store the DVB ancillary data payload position in the bitstream (only one per frame) */
+ UINT drcPayloadPosition[MAX_DRC_THREADS]; /* Used to store the DRC payload positions in the bitstream */
+
+} CDrcInfo;
+
+typedef CDrcInfo *HANDLE_AAC_DRC;
+
+#endif /* AACDEC_DRC_TYPES_H */
+
diff --git a/libAACdec/src/aacdec_hcr.cpp b/libAACdec/src/aacdec_hcr.cpp
new file mode 100644
index 0000000..09dca79
--- /dev/null
+++ b/libAACdec/src/aacdec_hcr.cpp
@@ -0,0 +1,1529 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: HCR Decoder: HCR initialization, preprocess HCR sideinfo,
+ decode priority codewords (PCWs)
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#include "aacdec_hcr.h"
+
+
+
+#include "aacdec_hcr_types.h"
+#include "aacdec_hcr_bit.h"
+#include "aacdec_hcrs.h"
+#include "aac_ram.h"
+#include "aac_rom.h"
+#include "channel.h"
+#include "block.h"
+
+#include "aacdecoder.h" /* for ID_CPE, ID_SCE ... */
+#include "FDK_bitstream.h"
+
+extern int mlFileChCurr;
+
+static void errDetectorInHcrSideinfoShrt(SCHAR cb,
+ SHORT numLine,
+ UINT *errorWord);
+
+static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword,
+ SHORT lengthOfReorderedSpectralData,
+ UINT *errorWord);
+
+static void HcrCalcNumCodeword (H_HCR_INFO pHcr);
+static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr);
+static void HcrPrepareSegmentationGrid (H_HCR_INFO pHcr);
+static void HcrExtendedSectionInfo (H_HCR_INFO pHcr);
+
+static void DeriveNumberOfExtendedSortedSectionsInSets(UINT numSegment,
+ USHORT *pNumExtendedSortedCodewordInSection,
+ int numExtendedSortedCodewordInSectionIdx,
+ USHORT *pNumExtendedSortedSectionsInSets,
+ int numExtendedSortedSectionsInSetsIdx);
+
+static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs,
+ INT quantSpecCoef,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ );
+
+static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs,
+ UINT codebookDim,
+ const SCHAR *pQuantVal,
+ FIXP_DBL *pQuantSpecCoef,
+ int *quantSpecCoefIdx,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ );
+
+static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs,
+ const UINT *pCurrentTree,
+ const SCHAR *pQuantValBase,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ );
+
+static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr);
+
+static void HcrReorderQuantizedSpectralCoefficients(
+ H_HCR_INFO pHcr,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo
+ );
+
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment,
+ H_HCR_INFO pHcr,
+ PCW_TYPE kind,
+ FIXP_DBL *qsc_base_of_cw,
+ UCHAR dimension);
+#endif
+
+#if CHECK_SEGMENTATION_FINAL
+static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr);
+#endif
+
+/*---------------------------------------------------------------------------------------------
+ description: Check if codebook and numSect are within allowed range (short only)
+-------------------------------------------------------------------------------------------- */
+static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine,UINT* errorWord)
+{
+
+
+
+ if ( cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL ) {
+ *errorWord |= CB_OUT_OF_RANGE_SHORT_BLOCK;
+ }
+ if ( numLine < 0 || numLine > 1024 ) {
+ *errorWord |= LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Check both HCR lengths
+-------------------------------------------------------------------------------------------- */
+static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword,
+ SHORT lengthOfReorderedSpectralData,
+ UINT *errorWord)
+{
+ if ( lengthOfReorderedSpectralData < lengthOfLongestCodeword ) {
+ *errorWord |= HCR_SI_LENGTHS_FAILURE;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Decode (and adapt if necessary) the two HCR sideinfo components:
+ 'reordered_spectral_data_length' and 'longest_codeword_length'
+-------------------------------------------------------------------------------------------- */
+
+void CHcr_Read(HANDLE_FDK_BITSTREAM bs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo)
+{
+ INT globalHcrType = getHcrType(&pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo);
+ SHORT lengOfReorderedSpectralData;
+ SCHAR lengOfLongestCodeword;
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = 0;
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = 0;
+
+
+
+ /* ------- SI-Value No 1 ------- */
+ lengOfReorderedSpectralData = FDKreadBits(bs,14) + ERROR_LORSD;
+ if ( globalHcrType == ID_CPE ) {
+ if ((lengOfReorderedSpectralData >= 0) && (lengOfReorderedSpectralData <= CPE_TOP_LENGTH)) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = lengOfReorderedSpectralData; /* the decoded value is within range */
+ }
+ else {
+ if (lengOfReorderedSpectralData > CPE_TOP_LENGTH) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = CPE_TOP_LENGTH; /* use valid maximum */
+ }
+ }
+ }
+ else if (globalHcrType == ID_SCE || globalHcrType == ID_LFE || globalHcrType == ID_CCE ) {
+ if ((lengOfReorderedSpectralData >= 0) && (lengOfReorderedSpectralData <= SCE_TOP_LENGTH)) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = lengOfReorderedSpectralData; /* the decoded value is within range */
+ }
+ else {
+ if (lengOfReorderedSpectralData > SCE_TOP_LENGTH) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = SCE_TOP_LENGTH; /* use valid maximum */
+ }
+ }
+ }
+
+ /* ------- SI-Value No 2 ------- */
+ lengOfLongestCodeword = FDKreadBits(bs,6) + ERROR_LOLC;
+ if ((lengOfLongestCodeword >= 0) && (lengOfLongestCodeword <= LEN_OF_LONGEST_CW_TOP_LENGTH)) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = lengOfLongestCodeword; /* the decoded value is within range */
+ }
+ else {
+ if (lengOfLongestCodeword > LEN_OF_LONGEST_CW_TOP_LENGTH) {
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = LEN_OF_LONGEST_CW_TOP_LENGTH; /* use valid maximum */
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Sets up HCR ROM-Tables
+-------------------------------------------------------------------------------------------- */
+
+void HcrInitRom(H_HCR_INFO pHcr)
+{
+ pHcr->cbPairs.pMinOfCbPair = aMinOfCbPair;
+ pHcr->cbPairs.pMaxOfCbPair = aMaxOfCbPair;
+
+ pHcr->tableInfo.pMaxCwLength = aMaxCwLen;
+ pHcr->tableInfo.pCbDimension = aDimCb;
+ pHcr->tableInfo.pCbDimShift = aDimCbShift;
+ pHcr->tableInfo.pCbSign = aSignCb;
+ pHcr->tableInfo.pCbPriority = aCbPriority;
+ pHcr->tableInfo.pLargestAbsVal = aLargestAbsoluteValue;
+}
+
+/*---------------------------------------------------------------------------------------------
+ description: Set up HCR - must be called before every call to HcrDecoder().
+ For short block a sorting algorithm is applied to get the SI in the order
+ that HCR could assemble the qsc's as if it is a long block.
+-----------------------------------------------------------------------------------------------
+ return: error log
+-------------------------------------------------------------------------------------------- */
+
+UINT HcrInit(H_HCR_INFO pHcr,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+ SHORT *pNumLinesInSec;
+ UCHAR *pCodeBk;
+ SHORT numSection;
+ SCHAR cb;
+ int numLine;
+ int i;
+
+ pHcr->decInOut.lengthOfReorderedSpectralData = pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData;
+ pHcr->decInOut.lengthOfLongestCodeword = pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword;
+ pHcr->decInOut.pQuantizedSpectralCoefficientsBase = pAacDecoderChannelInfo->pSpectralCoefficient;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx = 0;
+ pHcr->decInOut.pCodebook = pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr;
+ pHcr->decInOut.pNumLineInSect = pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr;
+ pHcr->decInOut.numSection = pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection;
+ pHcr->decInOut.errorLog = 0;
+ pHcr->nonPcwSideinfo.pResultBase = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
+
+ FDKsyncCache(bs);
+ pHcr->decInOut.bitstreamIndex = FDKgetBitCnt(bs);
+
+ if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) /* short block */
+ {
+ SHORT band;
+ SHORT maxBand;
+ SCHAR group;
+ SCHAR winGroupLen;
+ SCHAR window;
+ SCHAR numUnitInBand;
+ SCHAR cntUnitInBand;
+ SCHAR groupWin;
+ SCHAR cb_prev;
+
+ UCHAR *pCodeBook;
+ const SHORT *BandOffsets;
+ SCHAR numOfGroups;
+
+
+ pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; /* in */
+ pNumLinesInSec = pHcr->decInOut.pNumLineInSect; /* out */
+ pCodeBk = pHcr->decInOut.pCodebook; /* out */
+ BandOffsets = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); /* aux */
+ numOfGroups = GetWindowGroups(pIcsInfo);
+
+ numLine = 0;
+ numSection = 0;
+ cb = pCodeBook[0];
+ cb_prev = pCodeBook[0];
+
+ /* convert HCR-sideinfo into a unitwise manner: When the cb changes, a new section starts */
+
+ *pCodeBk++ = cb_prev;
+
+ maxBand = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ for (band = 0; band < maxBand; band++) { /* from low to high sfbs i.e. from low to high frequencies */
+ numUnitInBand = ((BandOffsets[band+1] - BandOffsets[band]) >> FOUR_LOG_DIV_TWO_LOG); /* get the number of units in current sfb */
+ for (cntUnitInBand = numUnitInBand; cntUnitInBand != 0; cntUnitInBand-- ) { /* for every unit in the band */
+ for (window = 0, group = 0; group < numOfGroups; group++) {
+ winGroupLen = GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group);
+ for (groupWin = winGroupLen; groupWin != 0; groupWin--, window++) {
+ cb = pCodeBook[group * 16 + band];
+ if (cb != cb_prev) {
+#if CHECK_VALID_HCR_INPUT /* short-block 1 of 2 */
+ errDetectorInHcrSideinfoShrt(cb,numLine,&pHcr->decInOut.errorLog );
+ if (pHcr->decInOut.errorLog != 0 ) {
+ return ( pHcr->decInOut.errorLog );
+ }
+#endif
+ *pCodeBk++ = cb;
+ *pNumLinesInSec++ = numLine;
+ numSection++;
+
+ cb_prev = cb;
+ numLine = LINES_PER_UNIT;
+ }
+ else {
+ numLine += LINES_PER_UNIT;
+ }
+ }
+ }
+ }
+ }
+
+ numSection++;
+
+#if CHECK_VALID_HCR_INPUT /* short-block 2 of 2 */
+ errDetectorInHcrSideinfoShrt(cb,numLine,&pHcr->decInOut.errorLog );
+ if ( numSection <= 0 || numSection > 1024/2 ) {
+ pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK;
+ }
+ errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword,
+ pHcr->decInOut.lengthOfReorderedSpectralData,
+ &pHcr->decInOut.errorLog);
+ if (pHcr->decInOut.errorLog != 0 ) {
+ return ( pHcr->decInOut.errorLog );
+ }
+#endif
+
+ *pCodeBk = cb;
+ *pNumLinesInSec = numLine;
+ pHcr->decInOut.numSection = numSection;
+
+ } else /* end short block prepare SI */
+ { /* long block */
+#if CHECK_VALID_HCR_INPUT /* long-block 1 of 1 */
+ errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword,
+ pHcr->decInOut.lengthOfReorderedSpectralData,
+ &pHcr->decInOut.errorLog);
+ numSection = pHcr->decInOut.numSection;
+ pNumLinesInSec = pHcr->decInOut.pNumLineInSect;
+ pCodeBk = pHcr->decInOut.pCodebook;
+ if ( numSection <= 0 || numSection > 64 ) {
+ pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_LONG_BLOCK;
+ numSection = 0;
+ }
+
+ for ( i = numSection; i != 0; i-- )
+ {
+ cb = *pCodeBk++;
+
+ if ( cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL ) {
+ pHcr->decInOut.errorLog |= CB_OUT_OF_RANGE_LONG_BLOCK;
+ }
+
+ numLine = *pNumLinesInSec++;
+ /* FDK_ASSERT(numLine > 0); */
+
+ if ( (numLine <= 0) || (numLine > 1024) ) {
+ pHcr->decInOut.errorLog |= LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK;
+ }
+ }
+ if (pHcr->decInOut.errorLog != 0 ) {
+ return ( pHcr->decInOut.errorLog );
+ }
+#endif /* CHECK_VALID_HCR_INPUT */
+ }
+
+ pCodeBk = pHcr->decInOut.pCodebook;
+ for ( i = 0; i < numSection; i++ ) {
+ if (
+ (*pCodeBk == NOISE_HCB) ||
+ (*pCodeBk == INTENSITY_HCB2) ||
+ (*pCodeBk == INTENSITY_HCB))
+ {
+ *pCodeBk = 0;
+ }
+ pCodeBk++;
+ }
+
+ /* HCR-sideinfo-input is complete and seems to be valid */
+
+
+
+ return ( pHcr->decInOut.errorLog );
+}
+
+
+
+
+#if USE_HCR_DUMMY
+
+/*---------------------------------------------------------------------------------------------
+
+ description: This HCR - dummy - function writes only a dirac-sequence in output buffer
+
+-------------------------------------------------------------------------------------------- */
+UINT HcrDecoder(H_HCR_INFO pHcr,
+ const CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ for (SHORT i=0; i < 1024; i++ ) {
+ pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = FL2FXCONST_DBL(0.0f);
+ if ( i % 30 == 0) {
+ pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = (FIXP_DBL)HCR_DIRAC;
+ }
+ }
+ return 0;
+}
+
+#else /* USE_HCR_DUMMY */
+
+/*---------------------------------------------------------------------------------------------
+ description: This function decodes the codewords of the spectral coefficients from the
+ bitstream according to the HCR algorithm and stores the quantized spectral
+ coefficients in correct order in the output buffer.
+-------------------------------------------------------------------------------------------- */
+
+UINT HcrDecoder(H_HCR_INFO pHcr,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ int pTmp1, pTmp2, pTmp3, pTmp4;
+#if DETECT_TOO_LONG_CW_READS
+ int pTmp5;
+#endif
+
+ INT bitCntOffst;
+ UINT saveBitCnt = FDKgetBitCnt(bs); /* save bitstream position */
+
+ HcrCalcNumCodeword(pHcr);
+
+ HcrSortCodebookAndNumCodewordInSection(pHcr);
+
+ HcrPrepareSegmentationGrid(pHcr);
+
+ HcrExtendedSectionInfo(pHcr);
+
+ if (( pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK ) != 0 ) {
+ return ( pHcr->decInOut.errorLog ); /* sideinfo is massively corrupt, return from HCR without having decoded anything */
+ }
+
+ DeriveNumberOfExtendedSortedSectionsInSets(pHcr->segmentInfo.numSegment,
+ pHcr->sectionInfo.pNumExtendedSortedCodewordInSection,
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx,
+ pHcr->sectionInfo.pNumExtendedSortedSectionsInSets,
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx);
+
+ /* store */
+ pTmp1 = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx;
+ pTmp2 = pHcr->sectionInfo.extendedSortedCodebookIdx;
+ pTmp3 = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx;
+ pTmp4 = pHcr->decInOut.quantizedSpectralCoefficientsIdx;
+#if DETECT_TOO_LONG_CW_READS
+ pTmp5 = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx;
+#endif
+
+ /* ------- decode meaningful PCWs ------ */
+ DecodePCWs(bs, pHcr);
+
+ if (( pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK ) == 0 ) {
+ /* ------ decode the non-PCWs -------- */
+ DecodeNonPCWs(bs, pHcr);
+ }
+
+
+#if CHECK_SEGMENTATION_FINAL
+ errDetectWithinSegmentationFinal(pHcr);
+#endif
+
+ /* restore */
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = pTmp1;
+ pHcr->sectionInfo.extendedSortedCodebookIdx = pTmp2;
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = pTmp3;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx = pTmp4;
+#if DETECT_TOO_LONG_CW_READS
+ pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = pTmp5;
+#endif
+
+ HcrReorderQuantizedSpectralCoefficients(pHcr, pAacDecoderChannelInfo, pSamplingRateInfo);
+
+ /* restore bitstream position */
+ bitCntOffst = saveBitCnt - FDKgetBitCnt(bs);
+ if( bitCntOffst ) {
+ FDKpushBiDirectional(bs, bitCntOffst);
+ }
+
+ return ( pHcr->decInOut.errorLog );
+}
+
+
+#endif /* USE_HCR_DUMMY */
+
+
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function reorders the quantized spectral coefficients sectionwise for
+ long- and short-blocks and compares to the LAV (Largest Absolute Value of
+ the current codebook) -- a counter is incremented if there is an error
+ detected.
+ Additional for short-blocks a unit-based-deinterleaving is applied.
+ Moreover (for short blocks) the scaling is derived (compare plain huffman
+ decoder).
+-------------------------------------------------------------------------------------------- */
+
+static void HcrReorderQuantizedSpectralCoefficients(
+ H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo
+ )
+{
+ INT qsc;
+ UINT abs_qsc;
+ UINT i,j;
+ USHORT numSpectralValuesInSection;
+ FIXP_DBL *pTeVa;
+ USHORT lavErrorCnt = 0;
+
+ UINT numSection = pHcr->decInOut.numSection;
+ SPECTRAL_PTR pQuantizedSpectralCoefficientsBase = pHcr->decInOut.pQuantizedSpectralCoefficientsBase;
+ FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase);
+ const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift;
+ const USHORT *pLargestAbsVal = pHcr->tableInfo.pLargestAbsVal;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection;
+ USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset;
+ FIXP_DBL *pTempValues = pHcr->segmentInfo.pTempValues;
+ FIXP_DBL *pBak = pHcr->segmentInfo.pTempValues;
+
+ FDKmemclear(pTempValues,1024*sizeof(FIXP_DBL));
+
+ /* long and short: check if decoded huffman-values (quantized spectral coefficients) are within range */
+ for ( i=numSection; i != 0; i-- ) {
+ numSpectralValuesInSection = *pNumSortedCodewordInSection++ << pCbDimShift[*pSortedCodebook];
+ pTeVa = &pTempValues[*pReorderOffset++];
+ for( j = numSpectralValuesInSection; j != 0; j-- ) {
+ qsc = *pQuantizedSpectralCoefficients++;
+ abs_qsc = FDKabs(qsc);
+#if VALID_LAV_ERROR_TRIGGER
+ if ( abs_qsc <= pLargestAbsVal[*pSortedCodebook] ) {
+ *pTeVa++ = (FIXP_DBL)qsc; /* the qsc value is within range */
+ }
+ else { /* line is too high .. */
+ if ( abs_qsc == Q_VALUE_INVALID ) { /* .. because of previous marking --> dont set LAV flag (would be confusing), just copy out the already marked value */
+ *pTeVa++ = (FIXP_DBL) qsc;
+ }
+ else { /* .. because a too high value was decoded for this cb --> set LAV flag */
+ *pTeVa++ = (FIXP_DBL) Q_VALUE_INVALID;
+ lavErrorCnt += 1;
+ }
+ }
+#else
+ if ( abs_qsc <= pLargestAbsVal[*pSortedCodebook] ) {
+ *pTeVa++ = qsc;
+ }
+ else {
+ *pTeVa++ = Q_VALUE_INVALID;
+ lavErrorCnt += 1;
+ }
+#endif
+ }
+ pSortedCodebook++;
+ }
+
+ if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo))
+ {
+ FIXP_DBL *pOut;
+ FIXP_DBL locMax;
+ FIXP_DBL tmp;
+ SCHAR groupoffset;
+ SCHAR group;
+ SCHAR band;
+ SCHAR groupwin;
+ SCHAR window;
+ SCHAR numWinGroup;
+ SHORT interm;
+ SCHAR numSfbTransm;
+ SCHAR winGroupLen;
+ SHORT index;
+ INT msb;
+ INT lsb;
+
+ SHORT *pScaleFacHcr = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ SHORT *pSfbSclHcr = pAacDecoderChannelInfo->pDynData->aSfbScale;
+ const SHORT *BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+
+ pBak = pHcr->segmentInfo.pTempValues;
+ /* deinterleave unitwise for short blocks */
+ for ( window = 0; window < (8); window++ ) {
+ pOut = SPEC(pQuantizedSpectralCoefficientsBase, window, pAacDecoderChannelInfo->granuleLength);
+ for ( i=0; i < (LINES_PER_UNIT_GROUP); i++ ) {
+ pTeVa = pBak + (window << FOUR_LOG_DIV_TWO_LOG) + i * 32; /* distance of lines between unit groups has to be constant for every framelength (32)! */
+ for ( j=(LINES_PER_UNIT); j != 0; j-- ) {
+ *pOut++ = *pTeVa++;
+ }
+ }
+ }
+
+ /* short blocks only */
+ /* derive global scaling-value for every sfb and every window (as it is done in plain-huffman-decoder at short blocks) */
+ groupoffset = 0;
+
+ numWinGroup = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+ numSfbTransm = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+
+ for (group = 0; group < numWinGroup; group++) {
+ winGroupLen = GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group);
+ for (band = 0; band < numSfbTransm; band++) {
+ interm = group * 16 + band;
+ msb = pScaleFacHcr[interm] >> 2;
+ lsb = pScaleFacHcr[interm] & 3;
+ for (groupwin = 0; groupwin < winGroupLen; groupwin++) {
+ window = groupoffset + groupwin;
+ pBak = SPEC(pQuantizedSpectralCoefficientsBase, window, pAacDecoderChannelInfo->granuleLength);
+ locMax = FL2FXCONST_DBL(0.0f);
+ for (index = BandOffsets[band]; index < BandOffsets[band+1]; index += LINES_PER_UNIT) {
+ pTeVa = &pBak[index];
+ for ( i = LINES_PER_UNIT; i != 0; i --) {
+ tmp = (*pTeVa < FL2FXCONST_DBL(0.0f))? -*pTeVa++ : *pTeVa++;
+ locMax = fixMax(tmp,locMax);
+ }
+ }
+ if ( fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE ) {
+ locMax = (FIXP_DBL)MAX_QUANTIZED_VALUE;
+ }
+ pSfbSclHcr[window*16+band] = msb - GetScaleFromValue(locMax, lsb); /* save global scale maxima in this sfb */
+ }
+ }
+ groupoffset += GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group);
+ }
+ } else
+ {
+ /* copy straight for long-blocks */
+ pQuantizedSpectralCoefficients = SPEC_LONG(pQuantizedSpectralCoefficientsBase);
+ for ( i = 1024; i != 0; i-- ) {
+ *pQuantizedSpectralCoefficients++ = *pBak++;
+ }
+ }
+
+ if ( lavErrorCnt != 0 ) {
+ pHcr->decInOut.errorLog |= LAV_VIOLATION;
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the number of codewords
+ for each section (numCodewordInSection) and the number of codewords
+ for all sections (numCodeword).
+ For zero and intensity codebooks a entry is also done in the variable
+ numCodewordInSection. It is assumed that the codebook is a two tuples
+ codebook. This is needed later for the calculation of the base addresses
+ for the reordering of the quantize spectral coefficients at the end of the
+ hcr tool.
+ The variable numCodeword contain the number of codewords which are really
+ in the bitstream. Zero or intensity codebooks does not increase the
+ variable numCodewords.
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static void HcrCalcNumCodeword(H_HCR_INFO pHcr)
+{
+ int hcrSection;
+ UINT numCodeword;
+
+ UINT numSection = pHcr->decInOut.numSection;
+ UCHAR *pCodebook = pHcr->decInOut.pCodebook;
+ SHORT *pNumLineInSection = pHcr->decInOut.pNumLineInSect;
+ const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift;
+ USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection;
+
+ numCodeword = 0;
+ for ( hcrSection = numSection; hcrSection != 0; hcrSection-- ) {
+ *pNumCodewordInSection = *pNumLineInSection++ >> pCbDimShift[*pCodebook];
+ if ( *pCodebook != 0 ) {
+ numCodeword += *pNumCodewordInSection;
+ }
+ pNumCodewordInSection++;
+ pCodebook++;
+ }
+ pHcr->sectionInfo.numCodeword = numCodeword;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the number
+ of sorted codebooks and sorts the codebooks and the numCodewordInSection
+ according to the priority.
+-------------------------------------------------------------------------------------------- */
+
+static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr)
+{
+
+ UINT i,j,k;
+ UCHAR temp;
+ UINT counter;
+ UINT startOffset;
+ UINT numZeroSection;
+ UCHAR *pDest;
+ UINT numSectionDec;
+
+ UINT numSection = pHcr->decInOut.numSection;
+ UCHAR *pCodebook = pHcr->decInOut.pCodebook;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection;
+ USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection;
+ UCHAR *pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch;
+ USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset;
+ const UCHAR *pCbPriority = pHcr->tableInfo.pCbPriority;
+ const UCHAR *pMinOfCbPair = pHcr->cbPairs.pMinOfCbPair;
+ const UCHAR *pMaxOfCbPair = pHcr->cbPairs.pMaxOfCbPair;
+ const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift;
+
+ UINT searchStart = 0;
+
+ /* calculate *pNumSortedSection and store the priorities in array pSortedCdebook */
+ pDest = pSortedCodebook;
+ numZeroSection = 0;
+ for ( i=numSection; i != 0; i-- ) {
+ if ( pCbPriority[*pCodebook] == 0 ) {
+ numZeroSection += 1;
+ }
+ *pDest++ = pCbPriority[*pCodebook++];
+ }
+ pHcr->sectionInfo.numSortedSection = numSection - numZeroSection; /* numSortedSection contains no zero or intensity section */
+ pCodebook = pHcr->decInOut.pCodebook;
+
+ /* sort priorities of the codebooks in array pSortedCdebook[] */
+ numSectionDec = numSection - 1;
+ if ( numSectionDec > 0 ) {
+ counter = numSectionDec;
+ for ( j=numSectionDec; j != 0; j-- ) {
+ for ( i=0; i < counter; i++ ) {
+ /* swap priorities */
+ if ( pSortedCodebook[i+1] > pSortedCodebook[i] ) {
+ temp = pSortedCodebook[i];
+ pSortedCodebook[i] = pSortedCodebook[i+1];
+ pSortedCodebook[i+1] = temp;
+ }
+ }
+ counter -= 1;
+ }
+ }
+
+ /* clear codebookSwitch array */
+ for ( i = numSection; i != 0; i--) {
+ *pCodebookSwitch++ = 0;
+ }
+ pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch;
+
+ /* sort sectionCodebooks and numCodwordsInSection and calculate pReorderOffst[j] */
+ for ( j = 0; j < numSection; j++ ) {
+ for ( i = searchStart; i < numSection; i++ ) {
+ if ( pCodebookSwitch[i] == 0 && ( pMinOfCbPair[pSortedCodebook[j]] == pCodebook[i] || pMaxOfCbPair[pSortedCodebook[j]] == pCodebook[i] )) {
+ pCodebookSwitch[i] = 1;
+ pSortedCodebook[j] = pCodebook[i]; /* sort codebook */
+ pNumSortedCodewordInSection[j] = pNumCodewordInSection[i]; /* sort NumCodewordInSection */
+
+ startOffset = 0;
+ for ( k = 0; k < i; k++ ) { /* make entry in pReorderOffst */
+ startOffset += pNumCodewordInSection[k] << pCbDimShift[pCodebook[k]];
+ }
+ pReorderOffset[j] = startOffset; /* offset for reordering the codewords */
+
+ if(i == searchStart) {
+ UINT k = i;
+ while(pCodebookSwitch[k++] == 1) searchStart++;
+ }
+ break;
+ }
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the segmentation, which includes numSegment,
+ leftStartOfSegment, rightStartOfSegment and remainingBitsInSegment.
+ The segmentation could be visualized a as kind of 'overlay-grid' for the
+ bitstream-block holding the HCR-encoded quantized-spectral-coefficients.
+-------------------------------------------------------------------------------------------- */
+
+static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr)
+{
+ USHORT i,j;
+ USHORT numSegment = 0;
+ USHORT segmentStart = 0;
+ UCHAR segmentWidth;
+ UCHAR lastSegmentWidth;
+ UCHAR sortedCodebook;
+ UCHAR endFlag = 0;
+ USHORT intermediateResult;
+
+ SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword;
+ SHORT lengthOfReorderedSpectralData = pHcr->decInOut.lengthOfReorderedSpectralData;
+ UINT numSortedSection = pHcr->sectionInfo.numSortedSection;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection;
+ USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ USHORT bitstreamIndex = pHcr->decInOut.bitstreamIndex;
+ const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength;
+
+ for ( i=numSortedSection; i != 0; i-- ) {
+ sortedCodebook = *pSortedCodebook++;
+ segmentWidth = FDKmin(pMaxCwLength[sortedCodebook],lengthOfLongestCodeword);
+
+ for ( j = *pNumSortedCodewordInSection; j != 0 ; j-- ) {
+ /* width allows a new segment */
+ intermediateResult = bitstreamIndex + segmentStart;
+ if ( (segmentStart + segmentWidth) <= lengthOfReorderedSpectralData ) {
+ /* store segment start, segment length and increment the number of segments */
+ *pLeftStartOfSegment++ = intermediateResult;
+ *pRightStartOfSegment++ = intermediateResult + segmentWidth - 1;
+ *pRemainingBitsInSegment++ = segmentWidth;
+ segmentStart += segmentWidth;
+ numSegment += 1;
+ }
+ /* width does not allow a new segment */
+ else {
+ /* correct the last segment length */
+ pLeftStartOfSegment--;
+ pRightStartOfSegment--;
+ pRemainingBitsInSegment--;
+ segmentStart = *pLeftStartOfSegment - bitstreamIndex;
+
+ lastSegmentWidth = lengthOfReorderedSpectralData - segmentStart;
+ *pRemainingBitsInSegment = lastSegmentWidth;
+ *pRightStartOfSegment = bitstreamIndex + segmentStart + lastSegmentWidth - 1;
+ endFlag = 1;
+ break;
+ }
+ }
+ pNumSortedCodewordInSection++;
+ if (endFlag != 0) {
+ break;
+ }
+ }
+ pHcr->segmentInfo.numSegment = numSegment;
+
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function adapts the sorted section boundaries to the boundaries of
+ segmentation. If the section lengths does not fit completely into the
+ current segment, the section is spitted into two so called 'extended
+ sections'. The extended-section-info (pNumExtendedSortedCodewordInSectin
+ and pExtendedSortedCodebook) is updated in this case.
+
+-------------------------------------------------------------------------------------------- */
+
+static void HcrExtendedSectionInfo(H_HCR_INFO pHcr)
+{
+ UINT srtSecCnt = 0; /* counter for sorted sections */
+ UINT xSrtScCnt = 0; /* counter for extended sorted sections */
+ UINT remainNumCwInSortSec;
+ UINT inSegmentRemainNumCW;
+
+ UINT numSortedSection = pHcr->sectionInfo.numSortedSection;
+ UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook;
+ USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection;
+ UCHAR *pExtendedSortedCoBo = pHcr->sectionInfo.pExtendedSortedCodebook;
+ USHORT *pNumExtSortCwInSect = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection;
+ UINT numSegment = pHcr->segmentInfo.numSegment;
+#if DETECT_TOO_LONG_CW_READS
+ UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec;
+ SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword;
+ const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength;
+#endif
+
+ remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt];
+ inSegmentRemainNumCW = numSegment;
+
+ while (srtSecCnt < numSortedSection) {
+ if (inSegmentRemainNumCW < remainNumCwInSortSec) {
+
+ pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW;
+ pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt];
+
+ remainNumCwInSortSec -= inSegmentRemainNumCW;
+ inSegmentRemainNumCW = numSegment;
+ /* data of a sorted section was not integrated in extended sorted section */
+ }
+ else if (inSegmentRemainNumCW == remainNumCwInSortSec) {
+ pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW;
+ pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt];
+
+ srtSecCnt++;
+ remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt];
+ inSegmentRemainNumCW = numSegment;
+ /* data of a sorted section was integrated in extended sorted section */
+ }
+ else { /* inSegmentRemainNumCW > remainNumCwInSortSec */
+ pNumExtSortCwInSect[xSrtScCnt] = remainNumCwInSortSec;
+ pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt];
+
+
+ inSegmentRemainNumCW -= remainNumCwInSortSec;
+ srtSecCnt++;
+ remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt];
+ /* data of a sorted section was integrated in extended sorted section */
+ }
+#if DETECT_TOO_LONG_CW_READS
+ pMaxLenOfCbInExtSrtSec[xSrtScCnt] = FDKmin(pMaxCwLength[pExtendedSortedCoBo[xSrtScCnt]],lengthOfLongestCodeword);
+#endif
+
+
+
+ xSrtScCnt += 1;
+
+ if ( xSrtScCnt >= (MAX_SFB_HCR + MAX_HCR_SETS) ) {
+ pHcr->decInOut.errorLog |= EXTENDED_SORTED_COUNTER_OVERFLOW;
+ return;
+ }
+
+ }
+ pNumExtSortCwInSect[xSrtScCnt] = 0;
+
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function calculates the number of extended sorted sections which
+ belong to the sets. Each set from set 0 (one and only set for the PCWs)
+ till to the last set gets a entry in the array to which
+ 'pNumExtendedSortedSectinsInSets' points to.
+
+ Calculation: The entrys in pNumExtendedSortedCodewordInSectin are added
+ untill the value numSegment is reached. Then the sum_variable is cleared
+ and the calculation starts from the beginning. As much extended sorted
+ Sections are summed up to reach the value numSegment, as much is the
+ current entry in *pNumExtendedSortedCodewordInSectin.
+-------------------------------------------------------------------------------------------- */
+static void DeriveNumberOfExtendedSortedSectionsInSets(UINT numSegment,
+ USHORT *pNumExtendedSortedCodewordInSection,
+ int numExtendedSortedCodewordInSectionIdx,
+ USHORT *pNumExtendedSortedSectionsInSets,
+ int numExtendedSortedSectionsInSetsIdx)
+{
+ USHORT counter = 0;
+ UINT cwSum = 0;
+ USHORT *pNumExSortCwInSec = pNumExtendedSortedCodewordInSection;
+ USHORT *pNumExSortSecInSets = pNumExtendedSortedSectionsInSets;
+
+ while (pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx] != 0)
+ {
+ cwSum += pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx];
+ numExtendedSortedCodewordInSectionIdx++;
+ if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) {
+ return;
+ }
+ if (cwSum > numSegment) {
+ return;
+ }
+ counter++;
+ if (counter > 1024/4) {
+ return;
+ }
+ if ( cwSum == numSegment ) {
+ pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter;
+ numExtendedSortedSectionsInSetsIdx++;
+ if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) {
+ return;
+ }
+ counter = 0;
+ cwSum = 0;
+ }
+ }
+ pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter; /* save last entry for the last - probably shorter - set */
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function decodes all priority codewords (PCWs) in a spectrum (within
+ set 0). The calculation of the PCWs is managed in two loops. The
+ loopcounter of the outer loop is set to the first value pointer
+ pNumExtendedSortedSectionsInSets points to. This value represents the
+ number of extended sorted sections within set 0.
+ The loopcounter of the inner loop is set to the first value pointer
+ pNumExtendedSortedCodewordInSectin points to. The value represents the
+ number of extended sorted codewords in sections (the original sections have
+ been splitted to go along with the borders of the sets).
+ Each time the number of the extended sorted codewords in sections are de-
+ coded, the pointer 'pNumExtendedSortedCodewordInSectin' is incremented by
+ one.
+-------------------------------------------------------------------------------------------- */
+static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr)
+{
+ UINT i;
+ USHORT extSortSec;
+ USHORT curExtSortCwInSec;
+ UCHAR codebook;
+ UCHAR dimension;
+ const UINT *pCurrentTree;
+ const SCHAR *pQuantValBase;
+ const SCHAR *pQuantVal;
+
+ USHORT *pNumExtendedSortedCodewordInSection = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection;
+ int numExtendedSortedCodewordInSectionIdx = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx;
+ UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook;
+ int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx;
+ USHORT *pNumExtendedSortedSectionsInSets = pHcr->sectionInfo.pNumExtendedSortedSectionsInSets;
+ int numExtendedSortedSectionsInSetsIdx = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx;
+ FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase);
+ int quantizedSpectralCoefficientsIdx = pHcr->decInOut.quantizedSpectralCoefficientsIdx;
+ USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+#if DETECT_TOO_LONG_CW_READS
+ UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec;
+ int maxLenOfCbInExtSrtSecIdx = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx;
+ UCHAR maxAllowedCwLen;
+ int numDecodedBits;
+#endif
+ const UCHAR *pCbDimension = pHcr->tableInfo.pCbDimension;
+ const UCHAR *pCbSign = pHcr->tableInfo.pCbSign;
+
+ /* clear result array */
+ //pQSC = &pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx];
+ //pQSC = *pQuantizedSpectralCoefficients;
+
+ FDKmemclear(pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx,1024*sizeof(FIXP_DBL));
+
+ /* decode all PCWs in the extended sorted section(s) belonging to set 0 */
+ for ( extSortSec = pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; extSortSec != 0; extSortSec-- ) {
+
+ codebook = pExtendedSortedCodebook[extendedSortedCodebookIdx]; /* get codebook for this extended sorted section and increment ptr to cb of next ext. sort sec */
+ extendedSortedCodebookIdx++;
+ if (extendedSortedCodebookIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) {
+ return;
+ }
+ dimension = pCbDimension[codebook]; /* get dimension of codebook of this extended sort. sec. */
+ pCurrentTree = aHuffTable [codebook]; /* convert codebook to pointer to QSCs */
+ pQuantValBase = aQuantTable [codebook]; /* convert codebook to index to table of QSCs */
+#if DETECT_TOO_LONG_CW_READS
+ maxAllowedCwLen = pMaxLenOfCbInExtSrtSec[maxLenOfCbInExtSrtSecIdx];
+ maxLenOfCbInExtSrtSecIdx++;
+ if (maxLenOfCbInExtSrtSecIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) {
+ return;
+ }
+#endif
+
+ /* switch for decoding with different codebooks: */
+ if ( pCbSign[codebook] == 0 ) { /* no sign bits follow after the codeword-body */
+ /* PCW_BodyONLY */
+ /*==============*/
+
+ for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--) {
+ numDecodedBits = 0;
+
+ /* decode PCW_BODY */
+ pQuantVal = DecodePCW_Body(bs,
+ pCurrentTree,
+ pQuantValBase,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+
+ /* result is written out here because NO sign bits follow the body */
+ for( i=dimension; i != 0 ; i-- ) {
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) *pQuantVal++; /* write quant. spec. coef. into spectrum; sign is already valid */
+ quantizedSpectralCoefficientsIdx++;
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+ }
+
+ /* one more PCW should be decoded */
+
+#if DETECT_TOO_LONG_CW_READS
+ if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_ONLY_TOO_LONG) ) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_BITS_DECODED;
+ }
+#endif
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+ if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY,pHcr,PCW_BODY,pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) {
+ return;
+ }
+#endif
+ pLeftStartOfSegment++; /* update pointer for decoding the next PCW */
+ pRemainingBitsInSegment++; /* update pointer for decoding the next PCW */
+ }
+ }
+ else if (( pCbSign[codebook] == 1 ) && ( codebook < 11 )) { /* possibly there follow 1,2,3 or 4 sign bits after the codeword-body */
+ /* PCW_Body and PCW_Sign */
+ /*=======================*/
+
+ for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--)
+ {
+ int err;
+ numDecodedBits = 0;
+
+ pQuantVal = DecodePCW_Body(bs,
+ pCurrentTree,
+ pQuantValBase,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+
+ err = DecodePCW_Sign( bs,
+ dimension,
+ pQuantVal,
+ pQuantizedSpectralCoefficients,
+ &quantizedSpectralCoefficientsIdx,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+ if (err != 0) {
+ return;
+ }
+ /* one more PCW should be decoded */
+
+#if DETECT_TOO_LONG_CW_READS
+ if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_TOO_LONG) ) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_BITS_DECODED;
+ }
+#endif
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+ if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY_SIGN,pHcr,PCW_BODY_SIGN, pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) {
+ return;
+ }
+#endif
+ pLeftStartOfSegment++;
+ pRemainingBitsInSegment++;
+ }
+ }
+ else if (( pCbSign[codebook] == 1 ) && ( codebook >= 11 )) { /* possibly there follow some sign bits and maybe one or two escape sequences after the cw-body */
+ /* PCW_Body, PCW_Sign and maybe PCW_Escape */
+ /*=========================================*/
+
+ for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--)
+ {
+ int err;
+ numDecodedBits = 0;
+
+ /* decode PCW_BODY */
+ pQuantVal = DecodePCW_Body(bs,
+ pCurrentTree,
+ pQuantValBase,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+
+ err = DecodePCW_Sign( bs,
+ dimension,
+ pQuantVal,
+ pQuantizedSpectralCoefficients,
+ &quantizedSpectralCoefficientsIdx,
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+ if (err != 0) {
+ return;
+ }
+
+ /* decode PCW_ESCAPE if present */
+ quantizedSpectralCoefficientsIdx -= DIMENSION_OF_ESCAPE_CODEBOOK;
+
+ if ( fixp_abs(pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]) == (FIXP_DBL)ESCAPE_VALUE ) {
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) DecodeEscapeSequence( bs,
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx],
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+ }
+ quantizedSpectralCoefficientsIdx++;
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+
+ if ( fixp_abs(pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]) == (FIXP_DBL)ESCAPE_VALUE ) {
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) DecodeEscapeSequence( bs,
+ pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx],
+ pLeftStartOfSegment,
+ pRemainingBitsInSegment,
+ &numDecodedBits
+ );
+ }
+ quantizedSpectralCoefficientsIdx++;
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+
+ /* one more PCW should be decoded */
+
+#if DETECT_TOO_LONG_CW_READS
+ if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_ESC_TOO_LONG) ) {
+ pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED;
+ }
+#endif
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+ if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY_SIGN_ESC,pHcr,PCW_BODY_SIGN_ESC,pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-DIMENSION_OF_ESCAPE_CODEBOOK,DIMENSION_OF_ESCAPE_CODEBOOK)) {
+ return;
+ }
+#endif
+ pLeftStartOfSegment++;
+ pRemainingBitsInSegment++;
+ }
+ }
+
+ /* all PCWs belonging to this extended section should be decoded */
+ numExtendedSortedCodewordInSectionIdx++;
+ if (numExtendedSortedCodewordInSectionIdx >= MAX_SFB_HCR+MAX_HCR_SETS) {
+ return;
+ }
+ }
+ /* all PCWs should be decoded */
+
+ numExtendedSortedSectionsInSetsIdx++;
+ if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) {
+ return;
+ }
+
+ /* Write back indexes into structure */
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = numExtendedSortedCodewordInSectionIdx;
+ pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx;
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = numExtendedSortedSectionsInSetsIdx;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx = quantizedSpectralCoefficientsIdx;
+ pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = maxLenOfCbInExtSrtSecIdx;
+}
+
+#if CHECK_SEGMENTATION_IMMEDIATELY
+/*---------------------------------------------------------------------------------------------
+ description: This function checks immediately after every decoded PCW, whether out of
+ the current segment too many bits have been read or not. If an error occurrs,
+ probably the sideinfo or the HCR-bitstream block holding the huffman
+ encoded quantized spectral coefficients is distorted. In this case the two
+ or four quantized spectral coefficients belonging to the current codeword
+ are marked (for being detected by concealment later).
+-------------------------------------------------------------------------------------------- */
+static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment,
+ H_HCR_INFO pHcr,
+ PCW_TYPE kind,
+ FIXP_DBL *qsc_base_of_cw,
+ UCHAR dimension)
+{
+ SCHAR i;
+ if ( remainingBitsInSegment < 0 ) {
+ /* log the error */
+ switch (kind) {
+ case PCW_BODY:
+ pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY;
+ break;
+ case PCW_BODY_SIGN:
+ pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN;
+ break;
+ case PCW_BODY_SIGN_ESC:
+ pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC;
+ break;
+ }
+ /* mark the erred lines */
+ for ( i = dimension; i != 0; i-- ) {
+ *qsc_base_of_cw++ = (FIXP_DBL) Q_VALUE_INVALID;
+ }
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+#if CHECK_SEGMENTATION_FINAL
+/*---------------------------------------------------------------------------------------------
+ description: This function checks if all segments are empty after decoding. There
+ are _no lines markded_ as invalid because it could not be traced back
+ where from the remaining bits are.
+-------------------------------------------------------------------------------------------- */
+static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr)
+{
+ UCHAR segmentationErrorFlag = 0;
+ USHORT i;
+ SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ UINT numSegment = pHcr->segmentInfo.numSegment;
+
+ for ( i=numSegment; i != 0 ; i--) {
+ if (*pRemainingBitsInSegment++ != 0) {
+ segmentationErrorFlag = 1;
+ }
+ }
+ if (segmentationErrorFlag == 1) {
+ pHcr->decInOut.errorLog |= BIT_IN_SEGMENTATION_ERROR;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------------------------
+ description: This function walks one step within the decoding tree. Which branch is
+ taken depends on the decoded carryBit input parameter.
+-------------------------------------------------------------------------------------------- */
+void CarryBitToBranchValue(UCHAR carryBit,
+ UINT treeNode,
+ UINT *branchValue,
+ UINT *branchNode)
+{
+ if (carryBit == 0) {
+ *branchNode = (treeNode & MASK_LEFT) >> LEFT_OFFSET; /* MASK_LEFT: 00FFF000 */
+ }
+ else {
+ *branchNode = treeNode & MASK_RIGHT; /* MASK_RIGHT: 00000FFF */
+ }
+
+ *branchValue = *branchNode & CLR_BIT_10; /* clear bit 10 (if set) */
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Decodes the body of a priority codeword (PCW)
+-----------------------------------------------------------------------------------------------
+ return: - return value is pointer to first of two or four quantized spectral
+ coefficients
+-------------------------------------------------------------------------------------------- */
+static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs,
+ const UINT *pCurrentTree,
+ const SCHAR *pQuantValBase,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ )
+{
+ UCHAR carryBit;
+ UINT branchNode;
+ UINT treeNode;
+ UINT branchValue;
+ const SCHAR *pQuantVal;
+
+ /* decode PCW_BODY */
+ treeNode = *pCurrentTree; /* get first node of current tree belonging to current codebook */
+
+ /* decode whole PCW-codeword-body */
+ while (1) {
+
+ carryBit = HcrGetABitFromBitstream(bs,
+ pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+
+ CarryBitToBranchValue(carryBit,
+ treeNode,
+ &branchValue,
+ &branchNode);
+
+ if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> codeword-body is complete */
+ break; /* end of branch in tree reached i.e. a whole PCW-Body is decoded */
+ }
+ else {
+ treeNode = *(pCurrentTree + branchValue); /* update treeNode for further step in decoding tree */
+ }
+
+ }
+
+ pQuantVal = pQuantValBase + branchValue; /* update pointer to valid first of 2 or 4 quantized values */
+
+ return pQuantVal;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function decodes one escape sequence. In case of a escape codebook
+ and in case of the absolute value of the quantized spectral value == 16,
+ a escapeSequence is decoded in two steps:
+ 1. escape prefix
+ 2. escape word
+-------------------------------------------------------------------------------------------- */
+
+static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs,
+ INT quantSpecCoef,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ )
+{
+ UINT i;
+ INT sign;
+ UINT escapeOnesCounter = 0;
+ UINT carryBit;
+ INT escape_word = 0;
+
+ /* decode escape prefix */
+ while (1) {
+ carryBit = HcrGetABitFromBitstream(bs,
+ pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+
+ if (carryBit != 0) {
+ escapeOnesCounter += 1;
+ }
+ else {
+ escapeOnesCounter += 4;
+ break;
+ }
+ }
+
+ /* decode escape word */
+ for( i=escapeOnesCounter; i != 0 ; i-- ) {
+ carryBit = HcrGetABitFromBitstream(bs,
+ pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+
+ escape_word <<= 1;
+ escape_word = escape_word | carryBit;
+ }
+
+ sign = (quantSpecCoef >= 0) ? 1 : -1;
+
+ quantSpecCoef = sign * (((INT ) 1 << escapeOnesCounter) + escape_word);
+
+ return quantSpecCoef;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Decodes the Signbits of a priority codeword (PCW) and writes out the
+ resulting quantized spectral values into unsorted sections
+-----------------------------------------------------------------------------------------------
+ output: - two or four lines at position in corresponding section (which are not
+ located at the desired position, i.e. they must be reordered in the last
+ of eight function of HCR)
+-----------------------------------------------------------------------------------------------
+ return: - updated pQuantSpecCoef pointer (to next empty storage for a line)
+-------------------------------------------------------------------------------------------- */
+static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs,
+ UINT codebookDim,
+ const SCHAR *pQuantVal,
+ FIXP_DBL *pQuantSpecCoef,
+ int *quantSpecCoefIdx,
+ USHORT *pLeftStartOfSegment,
+ SCHAR *pRemainingBitsInSegment,
+ int *pNumDecodedBits
+ )
+{
+ UINT i;
+ UINT carryBit;
+ INT quantSpecCoef;
+
+ for( i=codebookDim; i != 0 ; i-- ) {
+ quantSpecCoef = *pQuantVal++;
+ if (quantSpecCoef != 0) {
+ carryBit = HcrGetABitFromBitstream(bs,
+ pLeftStartOfSegment,
+ pLeftStartOfSegment, /* dummy */
+ FROM_LEFT_TO_RIGHT);
+ *pRemainingBitsInSegment -= 1;
+ *pNumDecodedBits += 1;
+ if (*pRemainingBitsInSegment < 0 || *pNumDecodedBits >= (1024>>1)) {
+ return -1;
+ }
+
+ /* adapt sign of values according to the decoded sign bit */
+ if (carryBit != 0) {
+ pQuantSpecCoef[*quantSpecCoefIdx] = -(FIXP_DBL)quantSpecCoef;
+ }
+ else {
+ pQuantSpecCoef[*quantSpecCoefIdx] = (FIXP_DBL)quantSpecCoef;
+ }
+ }
+ else {
+ pQuantSpecCoef[*quantSpecCoefIdx] = FL2FXCONST_DBL(0.0f);
+ }
+ *quantSpecCoefIdx += 1 ;
+ if (*quantSpecCoefIdx >= 1024) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Mutes spectral lines which have been marked as erroneous (Q_VALUE_INVALID)
+-------------------------------------------------------------------------------------------- */
+void HcrMuteErroneousLines(H_HCR_INFO hHcr)
+{
+ int c;
+ FIXP_DBL *RESTRICT pLong = SPEC_LONG(hHcr->decInOut.pQuantizedSpectralCoefficientsBase);
+
+ /* if there is a line with value Q_VALUE_INVALID mute it */
+ for (c = 0; c < 1024; c++) {
+ if (pLong[c] == (FIXP_DBL)Q_VALUE_INVALID) {
+#if HCR_LISTEN_TO_MUTED_LINES
+ pLong[c] = (FIXP_DBL)HCR_DIRAC; /* marking */
+#else
+ pLong[c] = FL2FXCONST_DBL(0.0f); /* muting */
+#endif
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Sets global HCR type
+-------------------------------------------------------------------------------------------- */
+void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type)
+{
+ switch (type) {
+ case ID_SCE:
+ hHcr->globalHcrType = 0;
+ break;
+ case ID_CPE:
+ hHcr->globalHcrType = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Gets HCR type from the HCR data structure
+-----------------------------------------------------------------------------------------------
+ return: - global HCR type
+-------------------------------------------------------------------------------------------- */
+INT getHcrType(H_HCR_INFO hHcr)
+{
+ return hHcr->globalHcrType;
+}
+
+
+
+
diff --git a/libAACdec/src/aacdec_hcr.h b/libAACdec/src/aacdec_hcr.h
new file mode 100644
index 0000000..f053448
--- /dev/null
+++ b/libAACdec/src/aacdec_hcr.h
@@ -0,0 +1,64 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: HCR Decoder: Interface function declaration; common defines
+ and structures; defines for switching error-generator,
+ -detector, and -concealment
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#ifndef _AACDEC_HCR_H_
+#define _AACDEC_HCR_H_
+
+
+
+#include "channelinfo.h"
+#include "FDK_bitstream.h"
+
+void HcrInitRom (H_HCR_INFO hHcr);
+UINT HcrInit(H_HCR_INFO pHcr,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ HANDLE_FDK_BITSTREAM bs);
+UINT HcrDecoder (H_HCR_INFO hHcr,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ HANDLE_FDK_BITSTREAM bs);
+void CarryBitToBranchValue(
+ UCHAR carryBit,
+ UINT treeNode,
+ UINT *branchValue,
+ UINT *branchNode
+ );
+
+void CHcr_Read (HANDLE_FDK_BITSTREAM bs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo);
+void HcrMuteErroneousLines(H_HCR_INFO hHcr);
+
+void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type);
+INT getHcrType(H_HCR_INFO hHcr);
+
+
+
+#endif /* _AACDEC_HCR_H_ */
diff --git a/libAACdec/src/aacdec_hcr_bit.cpp b/libAACdec/src/aacdec_hcr_bit.cpp
new file mode 100644
index 0000000..92695d9
--- /dev/null
+++ b/libAACdec/src/aacdec_hcr_bit.cpp
@@ -0,0 +1,103 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: HCR Decoder: Bitstream reading
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#include "aacdec_hcr_bit.h"
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function toggles the read direction.
+-----------------------------------------------------------------------------------------------
+ input: current read direction
+-----------------------------------------------------------------------------------------------
+ return: new read direction
+-------------------------------------------------------------------------------------------- */
+UCHAR ToggleReadDirection(UCHAR readDirection)
+{
+ if ( readDirection == FROM_LEFT_TO_RIGHT ) {
+ return FROM_RIGHT_TO_LEFT;
+ }
+ else {
+ return FROM_LEFT_TO_RIGHT;
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function returns a bit from the bitstream according to read direction.
+ It is called very often, therefore it makes sense to inline it (runtime).
+-----------------------------------------------------------------------------------------------
+ input: - handle to FDK bitstream
+ - reference value marking start of bitfield
+ - pLeftStartOfSegment
+ - pRightStartOfSegment
+ - readDirection
+-----------------------------------------------------------------------------------------------
+ return: - bit from bitstream
+-------------------------------------------------------------------------------------------- */
+UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs,
+ USHORT *pLeftStartOfSegment,
+ USHORT *pRightStartOfSegment,
+ UCHAR readDirection)
+{
+ UINT bit;
+ INT readBitOffset;
+
+ if (readDirection == FROM_LEFT_TO_RIGHT) {
+ readBitOffset = *pLeftStartOfSegment-FDKgetBitCnt(bs);
+ if( readBitOffset ) {
+ FDKpushBiDirectional(bs, readBitOffset);
+ }
+
+ bit = FDKreadBits(bs, 1);
+
+ *pLeftStartOfSegment += 1;
+ }
+ else {
+ readBitOffset = *pRightStartOfSegment-FDKgetBitCnt(bs);
+ if( readBitOffset ) {
+ FDKpushBiDirectional(bs, readBitOffset);
+ }
+
+ /* to be replaced with a brother function of FDKreadBits() */
+ bit = FDKreadBits(bs, 1);
+ FDKpushBack(bs, 2);
+
+ *pRightStartOfSegment -= 1;
+ }
+
+
+#if ERROR_GENERATOR_BIT_STREAM_HCR
+ static int a;
+ if ((++a % MODULO_DIVISOR_HCR) == 0) {
+ bit = (bit == 0) ? 1 : 0;
+ }
+#endif
+
+ return (bit);
+}
+
diff --git a/libAACdec/src/aacdec_hcr_bit.h b/libAACdec/src/aacdec_hcr_bit.h
new file mode 100644
index 0000000..e49ce5a
--- /dev/null
+++ b/libAACdec/src/aacdec_hcr_bit.h
@@ -0,0 +1,44 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: HCR Decoder: Bitstream reading prototypes
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#ifndef _AACDEC_HCR_BIT_H_
+#define _AACDEC_HCR_BIT_H_
+
+
+
+#include "aacdec_hcr.h"
+
+UCHAR ToggleReadDirection(UCHAR readDirection);
+
+UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs,
+ USHORT *pLeftStartOfSegment,
+ USHORT *pRightStartOfSegment,
+ UCHAR readDirection);
+
+
+#endif /* _AACDEC_HCR_BIT_H_ */
diff --git a/libAACdec/src/aacdec_hcr_types.h b/libAACdec/src/aacdec_hcr_types.h
new file mode 100644
index 0000000..0fe7730
--- /dev/null
+++ b/libAACdec/src/aacdec_hcr_types.h
@@ -0,0 +1,304 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2009
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: HCR Decoder: Common defines and structures; defines for
+ switching error-generator, -detector, and -concealment;
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#ifndef _AACDEC_HCR_TYPES_H_
+#define _AACDEC_HCR_TYPES_H_
+
+
+
+#include "FDK_bitstream.h"
+#include "overlapadd.h"
+
+/* ------------------------------------------------ */
+/* ------------------------------------------------ */
+
+#define LINES_PER_UNIT 4
+
+/* ------------------------------------------------ */
+/* ------------------------------------------------ */
+/* ----------- basic HCR configuration ------------ */
+
+
+ #define MAX_SFB_HCR (((1024/8) / LINES_PER_UNIT) * 8) /* (8 * 16) is not enough because sfbs are split in units for blocktype short */
+ #define NUMBER_OF_UNIT_GROUPS (LINES_PER_UNIT * 8)
+ #define LINES_PER_UNIT_GROUP (1024 / NUMBER_OF_UNIT_GROUPS) /* 15 16 30 32 */
+
+
+/* ------------------------------------------------ */
+/* ------------------------------------------------ */
+/* ------------------------------------------------ */
+
+#define FROM_LEFT_TO_RIGHT 0
+#define FROM_RIGHT_TO_LEFT 1
+
+#define MAX_CB_PAIRS 23
+#define MAX_HCR_SETS 14
+
+#define ESCAPE_VALUE 16
+#define POSITION_OF_FLAG_A 21
+#define POSITION_OF_FLAG_B 20
+
+#define MAX_CB 32 /* last used CB is cb #31 when VCB11 is used */
+
+#define MAX_CB_CHECK 32 /* support for VCB11 available -- is more general, could therefore used in both cases */
+
+#define NUMBER_OF_BIT_IN_WORD 32
+
+/* log */
+#define THIRTYTWO_LOG_DIV_TWO_LOG 5
+#define EIGHT_LOG_DIV_TWO_LOG 3
+#define FOUR_LOG_DIV_TWO_LOG 2
+
+/* borders */
+#define CPE_TOP_LENGTH 12288
+#define SCE_TOP_LENGTH 6144
+#define LEN_OF_LONGEST_CW_TOP_LENGTH 49
+
+/* qsc's of high level */
+#define Q_VALUE_INVALID 8192 /* mark a invalid line with this value (to be concealed later on) */
+#define HCR_DIRAC 500 /* a line of high level */
+
+/* masks */
+#define MASK_LEFT 0xFFF000
+#define MASK_RIGHT 0xFFF
+#define CLR_BIT_10 0x3FF
+#define TEST_BIT_10 0x400
+
+#define LEFT_OFFSET 12
+
+/* when set HCR is replaced by a dummy-module which just fills the outputbuffer with a dirac sequence */
+/* use this if HCR is suspected to write in other modules -- if error is stell there, HCR is innocent */
+#define USE_HCR_DUMMY 0
+
+
+/* ------------------------------ */
+/* - insert HCR errors - */
+/* ------------------------------ */
+
+ /* modify input lengths -- high protected */
+#define ERROR_LORSD 0 /* offset: error if different from zero */
+#define ERROR_LOLC 0 /* offset: error if different from zero */
+
+ /* segments are earlier empty as expected when decoding PCWs */
+#define ERROR_PCW_BODY 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */
+#define ERROR_PCW_BODY_SIGN 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */
+#define ERROR_PCW_BODY_SIGN_ESC 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */
+
+ /* pretend there are too many bits decoded (enlarge length of codeword) at PCWs -- use a positive value */
+#define ERROR_PCW_BODY_ONLY_TOO_LONG 0 /* set a positive values to trigger the error */
+#define ERROR_PCW_BODY_SIGN_TOO_LONG 0 /* set a positive values to trigger the error */
+#define ERROR_PCW_BODY_SIGN_ESC_TOO_LONG 0 /* set a positive values to trigger the error */
+
+ /* modify HCR bitstream block */
+#define ERROR_GENERATOR_BIT_STREAM_HCR 0 /* modify every <MODULO_DIVISOR_HCR>-bit when reading from bitstream */ /* !!! BEWARE!!! if RVLC is active, also RVLC data at ESC2 will be modified !!! */
+#define MODULO_DIVISOR_HCR 30
+
+
+/* ------------------------------ */
+/* - detect HCR errors - */
+/* ------------------------------ */
+ /* check input data */
+#define CHECK_VALID_HCR_INPUT 1 /* it is highly recommended to check input data */
+
+ /* during decoding */
+#define CHECK_SEGMENTATION_IMMEDIATELY 1 /* the 2 or 4 lines of a detected PCW-decoding-error is marked */
+
+#define CHECK_SEGMENTATION_FINAL 1 /* all the segments are checked -- therefore -- if this check passes, its a kind of evidence that the
+ decoded PCWs and non-PCWs are fine */
+
+#define DETECT_TOO_LONG_CW_READS 1 /* if a codeword is decoded there exists a border for the number of bits, which are allowed to read for this
+ codeword. This border is the minimum of the length of the longest codeword (for the currently used
+ codebook) and the separately transmitted 'lengthOfLongestCodeword' in this frame and channel. The number
+ of decoded bits is counted (for PCWs only -- there it makes really sense in my opinion). If this number
+ exceeds the border (derived as minimum -- see above), a error is detected. */
+
+#define STATE_MACHINE_ERROR_CHECK 1 /* test if the number of remaining bits in a segment is _below_ zero. If there are no errors the lowest
+ allowed value for remainingBitsInSegment is zero. This check also could be set to zero (save runtime) */
+ /* other */
+#define VALID_LAV_ERROR_TRIGGER 1 /* when set to '1', avoid setting the LAV-Flag in errorLog due to a previous-line-marking (at PCW decoder). A little
+ more runtime is needed then when writing values out into output-buffer. */
+
+#define HCR_LISTEN_TO_MUTED_LINES 0 /* listen to the "error-concealment" for testing */
+
+/* ------------------------------ */
+/* - conceal HCR errors - */
+/* ------------------------------ */
+
+#define HCR_ERROR_CONCEALMENT 1 /* if set to '1', HCR _mutes_ the erred quantized spectral coefficients */
+
+
+// ------------------------------------------------------------------------------------------------------------------
+// errorLog: A word of 32 bits used for logging possible errors within HCR
+// in case of distorted bitstreams. Table of all known errors:
+// ------------------------------------------------------------------------------------------------------------------------
+ // bit fatal location meaning
+ // ----+-----+-----------+--------------------------------------
+#define SEGMENT_OVERRIDE_ERR_PCW_BODY 0x80000000 // 31 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check).
+#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN 0x40000000 // 30 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check).
+#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC 0x20000000 // 29 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check).
+#define EXTENDED_SORTED_COUNTER_OVERFLOW 0x10000000 // 28 yes Init-Dec Error during extending sideinfo (neither a PCW nor a nonPCW was decoded so far)
+ // 0x08000000 // 27 reserved
+ // 0x04000000 // 26 reserved
+ // 0x02000000 // 25 reserved
+ // 0x01000000 // 24 reserved
+ // 0x00800000 // 23 reserved
+ // 0x00400000 // 22 reserved
+ // 0x00200000 // 21 reserved
+ // 0x00100000 // 20 reserved
+
+ /* special errors */
+#define TOO_MANY_PCW_BODY_BITS_DECODED 0x00080000 // 19 yes PCW-Dec During PCW-body-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding
+#define TOO_MANY_PCW_BODY_SIGN_BITS_DECODED 0x00040000 // 18 yes PCW-Dec During PCW-body-sign-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding
+#define TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED 0x00020000 // 17 yes PCW-Dec During PCW-body-sign-esc-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding
+
+
+ // 0x00010000 // 16 reserved
+#define STATE_ERROR_BODY_ONLY 0x00008000 // 15 no NonPCW-Dec State machine returned with error
+#define STATE_ERROR_BODY_SIGN__BODY 0x00004000 // 14 no NonPCW-Dec State machine returned with error
+#define STATE_ERROR_BODY_SIGN__SIGN 0x00002000 // 13 no NonPCW-Dec State machine returned with error
+#define STATE_ERROR_BODY_SIGN_ESC__BODY 0x00001000 // 12 no NonPCW-Dec State machine returned with error
+#define STATE_ERROR_BODY_SIGN_ESC__SIGN 0x00000800 // 11 no NonPCW-Dec State machine returned with error
+#define STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX 0x00000400 // 10 no NonPCW-Dec State machine returned with error
+#define STATE_ERROR_BODY_SIGN_ESC__ESC_WORD 0x00000200 // 9 no NonPCW-Dec State machine returned with error
+#define HCR_SI_LENGTHS_FAILURE 0x00000100 // 8 yes Init-Dec LengthOfLongestCodeword must not be less than lenghtOfReorderedSpectralData
+#define NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK 0x00000080 // 7 yes Init-Dec The number of sections is not within the allowed range (short block)
+#define NUM_SECT_OUT_OF_RANGE_LONG_BLOCK 0x00000040 // 6 yes Init-Dec The number of sections is not within the allowed range (long block)
+#define LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK 0x00000020 // 5 yes Init-Dec The number of lines per section is not within the allowed range (short block)
+#define CB_OUT_OF_RANGE_SHORT_BLOCK 0x00000010 // 4 yes Init-Dec The codebook is not within the allowed range (short block)
+#define LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK 0x00000008 // 3 yes Init-Dec The number of lines per section is not within the allowed range (long block)
+#define CB_OUT_OF_RANGE_LONG_BLOCK 0x00000004 // 2 yes Init-Dec The codebook is not within the allowed range (long block)
+#define LAV_VIOLATION 0x00000002 // 1 no Final The absolute value of at least one decoded line was too high for the according codebook.
+#define BIT_IN_SEGMENTATION_ERROR 0x00000001 // 0 no Final After PCW and non-PWC-decoding at least one segment is not zero (global check).
+
+ /*----------*/
+#define HCR_FATAL_PCW_ERROR_MASK 0x100E01FC
+
+
+typedef enum {
+ PCW_BODY,
+ PCW_BODY_SIGN,
+ PCW_BODY_SIGN_ESC
+} PCW_TYPE;
+
+
+/* interface Decoder <---> HCR */
+typedef struct {
+ UINT errorLog;
+ SPECTRAL_PTR pQuantizedSpectralCoefficientsBase;
+ int quantizedSpectralCoefficientsIdx;
+ SHORT lengthOfReorderedSpectralData;
+ SHORT numSection;
+ SHORT *pNumLineInSect;
+ USHORT bitstreamIndex;
+ SCHAR lengthOfLongestCodeword;
+ UCHAR *pCodebook;
+} HCR_INPUT_OUTPUT;
+
+typedef struct {
+ const UCHAR *pMinOfCbPair;
+ const UCHAR *pMaxOfCbPair;
+} HCR_CB_PAIRS;
+
+typedef struct{
+ const USHORT *pLargestAbsVal;
+ const UCHAR *pMaxCwLength;
+ const UCHAR *pCbDimension;
+ const UCHAR *pCbDimShift;
+ const UCHAR *pCbSign;
+ const UCHAR *pCbPriority;
+} HCR_TABLE_INFO;
+
+typedef struct{
+ UINT numSegment;
+ UINT pSegmentBitfield[((1024>>1)/NUMBER_OF_BIT_IN_WORD+1)];
+ UINT pCodewordBitfield[((1024>>1)/NUMBER_OF_BIT_IN_WORD+1)];
+ UINT segmentOffset;
+ FIXP_DBL pTempValues[1024];
+ USHORT pLeftStartOfSegment[1024>>1];
+ USHORT pRightStartOfSegment[1024>>1];
+ SCHAR pRemainingBitsInSegment[1024>>1];
+ UCHAR readDirection;
+ UCHAR numWordForBitfield;
+ USHORT pNumBitValidInLastWord;
+} HCR_SEGMENT_INFO;
+
+typedef struct{
+
+ UINT numCodeword;
+ UINT numSortedSection;
+ USHORT pNumCodewordInSection[MAX_SFB_HCR];
+ USHORT pNumSortedCodewordInSection[MAX_SFB_HCR];
+ USHORT pNumExtendedSortedCodewordInSection[MAX_SFB_HCR+MAX_HCR_SETS];
+ int numExtendedSortedCodewordInSectionIdx;
+ USHORT pNumExtendedSortedSectionsInSets[MAX_HCR_SETS];
+ int numExtendedSortedSectionsInSetsIdx;
+ USHORT pReorderOffset[MAX_SFB_HCR];
+ UCHAR pSortedCodebook[MAX_SFB_HCR];
+
+ UCHAR pExtendedSortedCodebook[MAX_SFB_HCR+MAX_HCR_SETS];
+ int extendedSortedCodebookIdx;
+#if DETECT_TOO_LONG_CW_READS
+ UCHAR pMaxLenOfCbInExtSrtSec[MAX_SFB_HCR+MAX_HCR_SETS];
+ int maxLenOfCbInExtSrtSecIdx;
+#endif
+ UCHAR pCodebookSwitch[MAX_SFB_HCR];
+} HCR_SECTION_INFO;
+
+typedef UINT (*STATEFUNC)(HANDLE_FDK_BITSTREAM, void*);
+
+typedef struct{
+ /* worst-case and 1024/4 non-PCWs exist in worst-case */
+ FIXP_DBL *pResultBase; /* Base address for spectral data output target buffer */
+ UINT iNode[1024>>2]; /* Helper indices for code books */
+ USHORT iResultPointer[1024>>2]; /* Helper indices for accessing pResultBase */
+ UINT pEscapeSequenceInfo[1024>>2];
+ UINT codewordOffset;
+ STATEFUNC pState;
+ UCHAR pCodebook[1024>>2];
+ UCHAR pCntSign[1024>>2];
+ /* this array holds the states coded as integer values within the range [0,1,..,7] */
+ SCHAR pSta[1024>>2];
+} HCR_NON_PCW_SIDEINFO;
+
+typedef struct{
+ HCR_INPUT_OUTPUT decInOut;
+ HCR_CB_PAIRS cbPairs;
+ HCR_TABLE_INFO tableInfo;
+ HCR_SEGMENT_INFO segmentInfo;
+ HCR_SECTION_INFO sectionInfo;
+ HCR_NON_PCW_SIDEINFO nonPcwSideinfo;
+
+ INT globalHcrType;
+} CErHcrInfo;
+
+
+typedef CErHcrInfo *H_HCR_INFO;
+
+
+#endif /* _AACDEC_HCR_TYPES_H_ */
diff --git a/libAACdec/src/aacdec_hcrs.cpp b/libAACdec/src/aacdec_hcrs.cpp
new file mode 100644
index 0000000..da8928e
--- /dev/null
+++ b/libAACdec/src/aacdec_hcrs.cpp
@@ -0,0 +1,1344 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: HCR Decoder: Prepare decoding of non-PCWs, segmentation- and
+ bitfield-handling, HCR-Statemachine
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#include "aacdec_hcrs.h"
+
+
+#include "aacdec_hcr.h"
+
+#include "aacdec_hcr_bit.h"
+#include "aac_rom.h"
+#include "aac_ram.h"
+
+
+static UINT InitSegmentBitfield(UINT *pNumSegment,
+ SCHAR *pRemainingBitsInSegment,
+ UINT *pSegmentBitfield,
+ UCHAR *pNumWordForBitfield,
+ USHORT *pNumBitValidInLastWord);
+
+static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr);
+
+static INT ModuloValue(INT input, INT bufferlength);
+
+static void ClearBitFromBitfield(STATEFUNC *ptrState,
+ UINT offset,
+ UINT *pBitfield);
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function decodes all non-priority codewords (non-PCWs) by using a
+ state-machine.
+-------------------------------------------------------------------------------------------- */
+void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr)
+{
+ UINT numValidSegment;
+ INT segmentOffset;
+ INT codewordOffsetBase;
+ INT codewordOffset;
+ UINT trial;
+
+ UINT *pNumSegment;
+ SCHAR *pRemainingBitsInSegment;
+ UINT *pSegmentBitfield;
+ UCHAR *pNumWordForBitfield;
+ USHORT *pNumBitValidInLastWord;
+ UINT *pCodewordBitfield;
+ INT bitfieldWord;
+ INT bitInWord;
+ UINT tempWord;
+ UINT interMediateWord;
+ INT tempBit;
+ INT carry;
+
+ UINT numCodeword;
+ UCHAR numSet;
+ UCHAR currentSet;
+ UINT codewordInSet;
+ UINT remainingCodewordsInSet;
+ SCHAR *pSta;
+ UINT ret;
+
+ pNumSegment = &(pHcr->segmentInfo.numSegment);
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ pNumWordForBitfield = &(pHcr->segmentInfo.numWordForBitfield);
+ pNumBitValidInLastWord = &(pHcr->segmentInfo.pNumBitValidInLastWord);
+ pSta = pHcr->nonPcwSideinfo.pSta;
+
+ numValidSegment = InitSegmentBitfield(pNumSegment,
+ pRemainingBitsInSegment,
+ pSegmentBitfield,
+ pNumWordForBitfield,
+ pNumBitValidInLastWord);
+
+ if ( numValidSegment != 0 ) {
+ numCodeword = pHcr->sectionInfo.numCodeword;
+ numSet = ((numCodeword - 1) / *pNumSegment) + 1;
+
+
+ pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT;
+
+ /* Process sets subsequently */
+ for ( currentSet = 1; currentSet < numSet ; currentSet++ ) {
+
+
+
+ /* step 1 */
+ numCodeword -= *pNumSegment; /* number of remaining non PCWs [for all sets] */
+ if ( numCodeword < *pNumSegment ) {
+ codewordInSet = numCodeword; /* for last set */
+ }
+ else {
+ codewordInSet = *pNumSegment; /* for all sets except last set */
+ }
+
+ /* step 2 */
+ /* prepare array 'CodewordBitfield'; as much ones are written from left in all words, as much decodedCodewordInSetCounter nonPCWs exist in this set */
+ tempWord = 0xFFFFFFFF;
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+
+ for ( bitfieldWord = *pNumWordForBitfield; bitfieldWord !=0; bitfieldWord-- ) { /* loop over all used words */
+ if ( codewordInSet > NUMBER_OF_BIT_IN_WORD ) { /* more codewords than number of bits => fill ones */
+ /* fill a whole word with ones */
+ *pCodewordBitfield++ = tempWord;
+ codewordInSet -= NUMBER_OF_BIT_IN_WORD; /* subtract number of bits */
+ }
+ else {
+ /* prepare last tempWord */
+ for (remainingCodewordsInSet = codewordInSet; remainingCodewordsInSet < NUMBER_OF_BIT_IN_WORD ; remainingCodewordsInSet++ ) {
+ tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD-1-remainingCodewordsInSet)); /* set a zero at bit number (NUMBER_OF_BIT_IN_WORD-1-i) in tempWord */
+ }
+ *pCodewordBitfield++ = tempWord;
+ tempWord = 0x00000000;
+ }
+ }
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+
+ /* step 3 */
+ /* build non-PCW sideinfo for each non-PCW of the current set */
+ InitNonPCWSideInformationForCurrentSet(pHcr);
+
+ /* step 4 */
+ /* decode all non-PCWs belonging to this set */
+
+ /* loop over trials */
+ codewordOffsetBase = 0;
+ for ( trial = *pNumSegment; trial > 0; trial-- ) {
+
+ /* loop over number of words in bitfields */
+ segmentOffset = 0; /* start at zero in every segment */
+ pHcr->segmentInfo.segmentOffset = segmentOffset; /* store in structure for states */
+ codewordOffset = codewordOffsetBase;
+ pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; /* store in structure for states */
+
+ for ( bitfieldWord=0; bitfieldWord < *pNumWordForBitfield; bitfieldWord++ ) {
+
+ /* derive tempWord with bitwise and */
+ tempWord = pSegmentBitfield[bitfieldWord] & pCodewordBitfield[bitfieldWord];
+
+ /* if tempWord is not zero, decode something */
+ if ( tempWord != 0 ) {
+
+
+ /* loop over all bits in tempWord; start state machine if & is true */
+ for ( bitInWord = NUMBER_OF_BIT_IN_WORD; bitInWord > 0; bitInWord-- ) {
+
+ interMediateWord = ((UINT)1 << (bitInWord-1) );
+ if ( ( tempWord & interMediateWord ) == interMediateWord ) {
+
+ /* get state and start state machine */
+ pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]];
+
+ while(pHcr->nonPcwSideinfo.pState) {
+ ret = ((STATEFUNC) pHcr->nonPcwSideinfo.pState)(bs, pHcr);
+#if STATE_MACHINE_ERROR_CHECK
+ if ( ret != 0 ) {
+ return;
+ }
+#endif
+ }
+ }
+
+ /* update both offsets */
+ segmentOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */
+ pHcr->segmentInfo.segmentOffset = segmentOffset;
+ codewordOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */
+ codewordOffset = ModuloValue(codewordOffset,*pNumSegment); /* index of the current codeword lies within modulo range */
+ pHcr->nonPcwSideinfo.codewordOffset = codewordOffset;
+ }
+ }
+ else {
+ segmentOffset += NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */
+ pHcr->segmentInfo.segmentOffset = segmentOffset;
+ codewordOffset += NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */
+ codewordOffset = ModuloValue(codewordOffset,*pNumSegment); /* index of the current codeword lies within modulo range */
+ pHcr->nonPcwSideinfo.codewordOffset = codewordOffset;
+ }
+ } /* end of bitfield word loop */
+
+ /* decrement codeword - pointer */
+ codewordOffsetBase -= 1;
+ codewordOffsetBase = ModuloValue(codewordOffsetBase,*pNumSegment); /* index of the current codeword base lies within modulo range */
+
+ /* rotate numSegment bits in codewordBitfield */
+ /* rotation of *numSegment bits in bitfield of codewords (circle-rotation) */
+ /* get last valid bit */
+ tempBit = pCodewordBitfield[*pNumWordForBitfield-1] & (1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord));
+ tempBit = tempBit >> (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord);
+
+ /* write zero into place where tempBit was fetched from */
+ pCodewordBitfield[*pNumWordForBitfield-1] = pCodewordBitfield[*pNumWordForBitfield-1] & ~(1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord));
+
+ /* rotate last valid word */
+ pCodewordBitfield[*pNumWordForBitfield-1] = pCodewordBitfield[*pNumWordForBitfield-1] >> 1;
+
+ /* transfare carry bit 0 from current word into bitposition 31 from next word and rotate current word */
+ for ( bitfieldWord = *pNumWordForBitfield-2; bitfieldWord > -1 ; bitfieldWord-- ) {
+ /* get carry (=bit at position 0) from current word */
+ carry = pCodewordBitfield[bitfieldWord] & 1;
+
+ /* put the carry bit at position 31 into word right from current word */
+ pCodewordBitfield[bitfieldWord+1] = pCodewordBitfield[bitfieldWord+1] | (carry << (NUMBER_OF_BIT_IN_WORD-1));
+
+ /* shift current word */
+ pCodewordBitfield[bitfieldWord] = pCodewordBitfield[bitfieldWord] >> 1;
+ }
+
+ /* put tempBit into free bit-position 31 from first word */
+ pCodewordBitfield[0] = pCodewordBitfield[0] | (tempBit << (NUMBER_OF_BIT_IN_WORD-1));
+
+ } /* end of trial loop */
+
+ /* toggle read direction */
+ pHcr->segmentInfo.readDirection = ToggleReadDirection(pHcr->segmentInfo.readDirection);
+
+ }
+ /* end of set loop */
+
+ /* all non-PCWs of this spectrum are decoded */
+ }
+
+ /* all PCWs and all non PCWs are decoded. They are unbacksorted in output buffer. Here is the Interface with comparing QSCs to asm decoding */
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function prepares the bitfield used for the
+ segments. The list is set up once to be used in all following sets. If a
+ segment is decoded empty, the according bit from the Bitfield is removed.
+-----------------------------------------------------------------------------------------------
+ return: numValidSegment = the number of valid segments
+-------------------------------------------------------------------------------------------- */
+static UINT InitSegmentBitfield(UINT *pNumSegment,
+ SCHAR *pRemainingBitsInSegment,
+ UINT *pSegmentBitfield,
+ UCHAR *pNumWordForBitfield,
+ USHORT *pNumBitValidInLastWord)
+{
+ SHORT i;
+ USHORT r;
+ UCHAR bitfieldWord;
+ UINT tempWord;
+ USHORT numValidSegment;
+
+ *pNumWordForBitfield = ((*pNumSegment-1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1;
+
+ /* loop over all words, which are completely used or only partial */
+ /* bit in pSegmentBitfield is zero if segment is empty; bit in pSegmentBitfield is one if segment is not empty */
+ numValidSegment = 0;
+ *pNumBitValidInLastWord = *pNumSegment;
+
+ /* loop over words */
+ for ( bitfieldWord=0; bitfieldWord < *pNumWordForBitfield - 1; bitfieldWord++ ) {
+ tempWord = 0xFFFFFFFF; /* set ones */
+ r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG;
+ for ( i=0; i < NUMBER_OF_BIT_IN_WORD; i++) {
+ if ( pRemainingBitsInSegment[r + i] == 0 ) {
+ tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD-1-i)); /* set a zero at bit number (NUMBER_OF_BIT_IN_WORD-1-i) in tempWord */
+ }
+ else {
+ numValidSegment += 1; /* count segments which are not empty */
+ }
+ }
+ pSegmentBitfield[bitfieldWord] = tempWord; /* store result */
+ *pNumBitValidInLastWord -= NUMBER_OF_BIT_IN_WORD; /* calculate number of zeros on LSB side in the last word */
+ }
+
+
+ /* calculate last word: prepare special tempWord */
+ tempWord = 0xFFFFFFFF;
+ for ( i=0; i < ( NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord ); i++ ) {
+ tempWord = tempWord & ~(1 << i); /* clear bit i in tempWord */
+ }
+
+ /* calculate last word */
+ r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG;
+ for ( i=0; i<*pNumBitValidInLastWord; i++) {
+ if ( pRemainingBitsInSegment[r + i] == 0 ) {
+ tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD-1-i)); /* set a zero at bit number (NUMBER_OF_BIT_IN_WORD-1-i) in tempWord */
+ }
+ else {
+ numValidSegment += 1; /* count segments which are not empty */
+ }
+ }
+ pSegmentBitfield[bitfieldWord] = tempWord; /* store result */
+
+
+
+ return numValidSegment;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function sets up sideinfo for the non-PCW decoder (for the current set).
+---------------------------------------------------------------------------------------------*/
+static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr)
+{
+ USHORT i,k;
+ UCHAR codebookDim;
+ UINT startNode;
+
+ UCHAR *pCodebook = pHcr->nonPcwSideinfo.pCodebook;
+ UINT *iNode = pHcr->nonPcwSideinfo.iNode;
+ UCHAR *pCntSign = pHcr->nonPcwSideinfo.pCntSign;
+ USHORT *iResultPointer = pHcr->nonPcwSideinfo.iResultPointer;
+ UINT *pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo;
+ SCHAR *pSta = pHcr->nonPcwSideinfo.pSta;
+ USHORT *pNumExtendedSortedCodewordInSection = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection;
+ int numExtendedSortedCodewordInSectionIdx = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx;
+ UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook;
+ int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx;
+ USHORT *pNumExtendedSortedSectionsInSets = pHcr->sectionInfo.pNumExtendedSortedSectionsInSets;
+ int numExtendedSortedSectionsInSetsIdx = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx;
+ FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase);
+ int quantizedSpectralCoefficientsIdx = pHcr->decInOut.quantizedSpectralCoefficientsIdx;
+ const UCHAR *pCbDimension = pHcr->tableInfo.pCbDimension;
+ int iterationCounter = 0;
+
+ /* loop over number of extended sorted sections in the current set so all codewords sideinfo variables within this set can be prepared for decoding */
+ for ( i=pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; i != 0; i-- ) {
+
+ codebookDim = pCbDimension[pExtendedSortedCodebook[extendedSortedCodebookIdx]];
+ startNode = *aHuffTable[pExtendedSortedCodebook[extendedSortedCodebookIdx]];
+
+ for ( k = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx]; k != 0; k-- ) {
+ iterationCounter++;
+ if (iterationCounter > (1024>>2)) {
+ return;
+ }
+ *pSta++ = aCodebook2StartInt[pExtendedSortedCodebook[extendedSortedCodebookIdx]];
+ *pCodebook++ = pExtendedSortedCodebook[extendedSortedCodebookIdx];
+ *iNode++ = startNode;
+ *pCntSign++ = 0;
+ *iResultPointer++ = quantizedSpectralCoefficientsIdx;
+ *pEscapeSequenceInfo++ = 0;
+ quantizedSpectralCoefficientsIdx += codebookDim; /* update pointer by codebookDim --> point to next starting value for writing out */
+ if (quantizedSpectralCoefficientsIdx >= 1024) {
+ return;
+ }
+ }
+ numExtendedSortedCodewordInSectionIdx++; /* inc ptr for next ext sort sec in current set */
+ extendedSortedCodebookIdx++; /* inc ptr for next ext sort sec in current set */
+ if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR+MAX_HCR_SETS) || extendedSortedCodebookIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) {
+ return;
+ }
+ }
+ numExtendedSortedSectionsInSetsIdx++; /* inc ptr for next set of non-PCWs */
+ if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) {
+ return;
+ }
+
+ /* Write back indexes */
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = numExtendedSortedCodewordInSectionIdx;
+ pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx;
+ pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = numExtendedSortedSectionsInSetsIdx;
+ pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = numExtendedSortedCodewordInSectionIdx;
+ pHcr->decInOut.quantizedSpectralCoefficientsIdx = quantizedSpectralCoefficientsIdx;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function returns the input value if the value is in the
+ range of bufferlength. If <input> is smaller, one bufferlength is added,
+ if <input> is bigger one bufferlength is subtracted.
+-----------------------------------------------------------------------------------------------
+ return: modulo result
+-------------------------------------------------------------------------------------------- */
+static INT ModuloValue(INT input, INT bufferlength)
+{
+ if ( input > (bufferlength - 1) ) {
+ return (input - bufferlength);
+ }
+ if ( input < 0 ) {
+ return (input + bufferlength);
+ }
+ return input;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This function clears a bit from current bitfield and
+ switches off the statemachine.
+
+ A bit is cleared in two cases:
+ a) a codeword is decoded, then a bit is cleared in codeword bitfield
+ b) a segment is decoded empty, then a bit is cleared in segment bitfield
+-------------------------------------------------------------------------------------------- */
+static void ClearBitFromBitfield(STATEFUNC *ptrState,
+ UINT offset,
+ UINT *pBitfield)
+{
+ UINT numBitfieldWord;
+ UINT numBitfieldBit;
+
+ /* get both values needed for clearing the bit */
+ numBitfieldWord = offset >> THIRTYTWO_LOG_DIV_TWO_LOG; /* int = wordNr */
+ numBitfieldBit = offset - (numBitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG); /* fract = bitNr */
+
+ /* clear a bit in bitfield */
+ pBitfield[numBitfieldWord] = pBitfield[numBitfieldWord] & ~(1 << (NUMBER_OF_BIT_IN_WORD-1 - numBitfieldBit));
+
+ /* switch off state machine because codeword is decoded and/or because segment is empty */
+ *ptrState = NULL;
+}
+
+
+
+/* =========================================================================================
+ the states of the statemachine
+ ========================================================================================= */
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Decodes the body of a codeword. This State is used for codebooks 1,2,5 and 6.
+ No sign bits are decoded, because the table of the quantized spectral values
+ has got a valid sign at the quantized spectral lines.
+-----------------------------------------------------------------------------------------------
+ output: Two or four quantizes spectral values written at position where pResultPointr
+ points to
+-----------------------------------------------------------------------------------------------
+ return: 0
+-------------------------------------------------------------------------------------------- */
+UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM bs, void *ptr)
+{
+ H_HCR_INFO pHcr = (H_HCR_INFO)ptr;
+ UINT *pSegmentBitfield;
+ UINT *pCodewordBitfield;
+ UINT segmentOffset;
+ FIXP_DBL *pResultBase;
+ UINT *iNode;
+ USHORT *iResultPointer;
+ UINT codewordOffset;
+ UINT branchNode;
+ UINT branchValue;
+ UINT iQSC;
+ UINT treeNode;
+ UCHAR carryBit;
+ USHORT *pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment;
+ SCHAR *pRemainingBitsInSegment;
+ UCHAR readDirection;
+ UCHAR *pCodebook;
+ UCHAR dimCntr;
+ const UINT *pCurrentTree;
+ const UCHAR *pCbDimension;
+ const SCHAR *pQuantVal;
+ const SCHAR *pQuantValBase;
+
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ readDirection = pHcr->segmentInfo.readDirection;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+ segmentOffset = pHcr->segmentInfo.segmentOffset;
+
+ pCodebook = pHcr->nonPcwSideinfo.pCodebook;
+ iNode = pHcr->nonPcwSideinfo.iNode;
+ pResultBase = pHcr->nonPcwSideinfo.pResultBase;
+ iResultPointer = pHcr->nonPcwSideinfo.iResultPointer;
+ codewordOffset = pHcr->nonPcwSideinfo.codewordOffset;
+
+ pCbDimension = pHcr->tableInfo.pCbDimension;
+
+ treeNode = iNode[codewordOffset];
+ pCurrentTree = aHuffTable[pCodebook[codewordOffset]];
+
+
+ for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) {
+
+ carryBit = HcrGetABitFromBitstream( bs,
+ &pLeftStartOfSegment[segmentOffset],
+ &pRightStartOfSegment[segmentOffset],
+ readDirection);
+
+ CarryBitToBranchValue(carryBit, /* make a step in decoding tree */
+ treeNode,
+ &branchValue,
+ &branchNode);
+
+ /* if end of branch reached write out lines and count bits needed for sign, otherwise store node in codeword sideinfo */
+ if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; ==> body is complete */
+ pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base address of quantized values belonging to current codebook */
+ pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid line [of 2 or 4 quantized values] */
+
+ iQSC = iResultPointer[codewordOffset]; /* get position of first line for writing out result */
+
+ for ( dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; dimCntr-- ) {
+ pResultBase[iQSC++] = (FIXP_DBL)*pQuantVal++; /* write out 2 or 4 lines into spectrum; no Sign bits available in this state */
+ }
+
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */
+ pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */
+ break; /* end of branch in tree reached i.e. a whole nonPCW-Body is decoded */
+ }
+ else { /* body is not decoded completely: */
+ treeNode = *(pCurrentTree + branchValue); /* update treeNode for further step in decoding tree */
+ }
+ }
+ iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe decoding of codeword body not finished yet */
+
+ if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */
+
+#if STATE_MACHINE_ERROR_CHECK
+ if ( pRemainingBitsInSegment[segmentOffset] < 0 ) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_ONLY;
+ return BODY_ONLY;
+ }
+#endif
+ }
+
+ return STOP_THIS_STATE;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Decodes the codeword body, writes out result and counts the number of quantized
+ spectral values, which are different form zero. For those values sign bits are
+ needed.
+
+ If sign bit counter cntSign is different from zero, switch to next state to
+ decode sign Bits there.
+ If sign bit counter cntSign is zero, no sign bits are needed and codeword is
+ decoded.
+-----------------------------------------------------------------------------------------------
+ output: Two or four written quantizes spectral values written at position where
+ pResultPointr points to. The signs of those lines may be wrong. If the signs
+ [on just one signle sign] is wrong, the next state will correct it.
+-----------------------------------------------------------------------------------------------
+ return: 0
+-------------------------------------------------------------------------------------------- */
+UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr)
+{
+ H_HCR_INFO pHcr = (H_HCR_INFO)ptr;
+ SCHAR *pRemainingBitsInSegment;
+ USHORT *pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment;
+ UCHAR readDirection;
+ UINT *pSegmentBitfield;
+ UINT *pCodewordBitfield;
+ UINT segmentOffset;
+
+ UCHAR *pCodebook;
+ UINT *iNode;
+ UCHAR *pCntSign;
+ FIXP_DBL *pResultBase;
+ USHORT *iResultPointer;
+ UINT codewordOffset;
+
+ UINT iQSC;
+ UINT cntSign;
+ UCHAR dimCntr;
+ UCHAR carryBit;
+ SCHAR *pSta;
+ UINT treeNode;
+ UINT branchValue;
+ UINT branchNode;
+ const UCHAR *pCbDimension;
+ const UINT *pCurrentTree;
+ const SCHAR *pQuantValBase;
+ const SCHAR *pQuantVal;
+
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ readDirection = pHcr->segmentInfo.readDirection;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+ segmentOffset = pHcr->segmentInfo.segmentOffset;
+
+ pCodebook = pHcr->nonPcwSideinfo.pCodebook;
+ iNode = pHcr->nonPcwSideinfo.iNode;
+ pCntSign = pHcr->nonPcwSideinfo.pCntSign;
+ pResultBase = pHcr->nonPcwSideinfo.pResultBase;
+ iResultPointer = pHcr->nonPcwSideinfo.iResultPointer;
+ codewordOffset = pHcr->nonPcwSideinfo.codewordOffset;
+ pSta = pHcr->nonPcwSideinfo.pSta;
+
+ pCbDimension = pHcr->tableInfo.pCbDimension;
+
+ treeNode = iNode[codewordOffset];
+ pCurrentTree = aHuffTable[pCodebook[codewordOffset]];
+
+
+ for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) {
+
+ carryBit = HcrGetABitFromBitstream( bs,
+ &pLeftStartOfSegment[segmentOffset],
+ &pRightStartOfSegment[segmentOffset],
+ readDirection);
+
+ CarryBitToBranchValue(carryBit, /* make a step in decoding tree */
+ treeNode,
+ &branchValue,
+ &branchNode);
+
+ /* if end of branch reached write out lines and count bits needed for sign, otherwise store node in codeword sideinfo */
+ if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set body complete */
+ /* body completely decoded; branchValue is valid, set pQuantVal to first (of two or four) quantized spectral coefficients */
+ pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base address of quantized values belonging to current codebook */
+ pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid line [of 2 or 4 quantized values] */
+
+ iQSC = iResultPointer[codewordOffset]; /* get position of first line for writing result */
+
+ /* codeword decoding result is written out here: Write out 2 or 4 quantized spectral values with probably */
+ /* wrong sign and count number of values which are different from zero for sign bit decoding [which happens in next state] */
+ cntSign = 0;
+ for ( dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; dimCntr-- ) {
+ pResultBase[iQSC++] = (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */
+ if ( *pQuantVal++ != 0 ) {
+ cntSign += 1;
+ }
+ }
+
+ if ( cntSign == 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */
+ }
+ else {
+ pCntSign[codewordOffset] = cntSign; /* write sign count result into codewordsideinfo of current codeword */
+ pSta[codewordOffset] = BODY_SIGN__SIGN; /* change state */
+ pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */
+ }
+ pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */
+ break; /* end of branch in tree reached i.e. a whole nonPCW-Body is decoded */
+ }
+ else {/* body is not decoded completely: */
+ treeNode = *(pCurrentTree + branchValue); /* update treeNode for further step in decoding tree */
+ }
+ }
+ iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe decoding of codeword body not finished yet */
+
+ if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */
+
+#if STATE_MACHINE_ERROR_CHECK
+ if ( pRemainingBitsInSegment[segmentOffset] < 0 ) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__BODY;
+ return BODY_SIGN__BODY;
+ }
+#endif
+ }
+
+ return STOP_THIS_STATE;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This state decodes the sign bits belonging to a codeword. The state is called
+ as often in different "trials" until pCntSgn[codewordOffset] is zero.
+-----------------------------------------------------------------------------------------------
+ output: The two or four quantizes spectral values (written in previous state) have
+ now the correct sign.
+-----------------------------------------------------------------------------------------------
+ return: 0
+-------------------------------------------------------------------------------------------- */
+UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr)
+{
+ H_HCR_INFO pHcr = (H_HCR_INFO)ptr;
+ SCHAR *pRemainingBitsInSegment;
+ USHORT *pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment;
+ UCHAR readDirection;
+ UINT *pSegmentBitfield;
+ UINT *pCodewordBitfield;
+ UINT segmentOffset;
+
+ UCHAR *pCntSign;
+ FIXP_DBL *pResultBase;
+ USHORT *iResultPointer;
+ UINT codewordOffset;
+ UCHAR carryBit;
+ UINT iQSC;
+ UCHAR cntSign;
+
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ readDirection = pHcr->segmentInfo.readDirection;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+ segmentOffset = pHcr->segmentInfo.segmentOffset;
+
+ pCntSign = pHcr->nonPcwSideinfo.pCntSign;
+ pResultBase = pHcr->nonPcwSideinfo.pResultBase;
+ iResultPointer = pHcr->nonPcwSideinfo.iResultPointer;
+ codewordOffset = pHcr->nonPcwSideinfo.codewordOffset;
+ iQSC = iResultPointer[codewordOffset];
+ cntSign = pCntSign[codewordOffset];
+
+
+
+ /* loop for sign bit decoding */
+ for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) {
+
+ carryBit = HcrGetABitFromBitstream( bs,
+ &pLeftStartOfSegment[segmentOffset],
+ &pRightStartOfSegment[segmentOffset],
+ readDirection);
+ cntSign -= 1; /* decrement sign counter because one sign bit has been read */
+
+ /* search for a line (which was decoded in previous state) which is not zero. [This value will get a sign] */
+ while ( pResultBase[iQSC] == (FIXP_DBL)0 ) {
+ iQSC++; /* points to current value different from zero */
+ }
+
+ /* put sign together with line; if carryBit is zero, the sign is ok already; no write operation necessary in this case */
+ if ( carryBit != 0 ) {
+ pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */
+ }
+
+ iQSC++; /* update pointer to next (maybe valid) value */
+
+ if ( cntSign == 0 ) { /* if (cntSign==0) ==> set state CODEWORD_DECODED */
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */
+ pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */
+ break; /* whole nonPCW-Body and according sign bits are decoded */
+ }
+ }
+ pCntSign[codewordOffset] = cntSign;
+ iResultPointer[codewordOffset] = iQSC; /* store updated pResultPointer */
+
+ if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */
+
+#if STATE_MACHINE_ERROR_CHECK
+ if ( pRemainingBitsInSegment[segmentOffset] < 0 ) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__SIGN;
+ return BODY_SIGN__SIGN;
+ }
+#endif
+ }
+
+ return STOP_THIS_STATE;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Decodes the codeword body in case of codebook is 11. Writes out resulting
+ two or four lines [with probably wrong sign] and counts the number of
+ lines, which are different form zero. This information is needed in next
+ state where sign bits will be decoded, if necessary.
+ If sign bit counter cntSign is zero, no sign bits are needed and codeword is
+ decoded completely.
+-----------------------------------------------------------------------------------------------
+ output: Two lines (quantizes spectral coefficients) which are probably wrong. The
+ sign may be wrong and if one or two values is/are 16, the following states
+ will decode the escape sequence to correct the values which are wirtten here.
+-----------------------------------------------------------------------------------------------
+ return: 0
+-------------------------------------------------------------------------------------------- */
+UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr)
+{
+ H_HCR_INFO pHcr = (H_HCR_INFO)ptr;
+ SCHAR *pRemainingBitsInSegment;
+ USHORT *pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment;
+ UCHAR readDirection;
+ UINT *pSegmentBitfield;
+ UINT *pCodewordBitfield;
+ UINT segmentOffset;
+
+ UINT *iNode;
+ UCHAR *pCntSign;
+ FIXP_DBL *pResultBase;
+ USHORT *iResultPointer;
+ UINT codewordOffset;
+
+ UCHAR carryBit;
+ UINT iQSC;
+ UINT cntSign;
+ UINT dimCntr;
+ UINT treeNode;
+ SCHAR *pSta;
+ UINT branchNode;
+ UINT branchValue;
+ const UINT *pCurrentTree;
+ const SCHAR *pQuantValBase;
+ const SCHAR *pQuantVal;
+
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ readDirection = pHcr->segmentInfo.readDirection;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+ segmentOffset = pHcr->segmentInfo.segmentOffset;
+
+ iNode = pHcr->nonPcwSideinfo.iNode;
+ pCntSign = pHcr->nonPcwSideinfo.pCntSign;
+ pResultBase = pHcr->nonPcwSideinfo.pResultBase;
+ iResultPointer = pHcr->nonPcwSideinfo.iResultPointer;
+ codewordOffset = pHcr->nonPcwSideinfo.codewordOffset;
+ pSta = pHcr->nonPcwSideinfo.pSta;
+
+ treeNode = iNode[codewordOffset];
+ pCurrentTree = aHuffTable[ESCAPE_CODEBOOK];
+
+
+ for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) {
+
+ carryBit = HcrGetABitFromBitstream( bs,
+ &pLeftStartOfSegment[segmentOffset],
+ &pRightStartOfSegment[segmentOffset],
+ readDirection);
+
+ /* make a step in tree */
+ CarryBitToBranchValue(carryBit,
+ treeNode,
+ &branchValue,
+ &branchNode);
+
+ /* if end of branch reached write out lines and count bits needed for sign, otherwise store node in codeword sideinfo */
+ if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set body complete */
+
+ /* body completely decoded; branchValue is valid */
+ /* set pQuantVol to first (of two or four) quantized spectral coefficients */
+ pQuantValBase = aQuantTable[ESCAPE_CODEBOOK]; /* get base address of quantized values belonging to current codebook */
+ pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid line [of 2 or 4 quantized values] */
+
+ /* make backup from original resultPointer in node storage for state BODY_SIGN_ESC__SIGN */
+ iNode[codewordOffset] = iResultPointer[codewordOffset];
+
+ /* get position of first line for writing result */
+ iQSC = iResultPointer[codewordOffset];
+
+ /* codeword decoding result is written out here: Write out 2 or 4 quantized spectral values with probably */
+ /* wrong sign and count number of values which are different from zero for sign bit decoding [which happens in next state] */
+ cntSign = 0;
+
+ for ( dimCntr = DIMENSION_OF_ESCAPE_CODEBOOK; dimCntr != 0; dimCntr-- ) {
+ pResultBase[iQSC++] = (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */
+ if ( *pQuantVal++ != 0 ) {
+ cntSign += 1;
+ }
+ }
+
+ if ( cntSign == 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */
+ /* codeword decoded */
+ }
+ else {
+ /* write sign count result into codewordsideinfo of current codeword */
+ pCntSign[codewordOffset] = cntSign;
+ pSta[codewordOffset] = BODY_SIGN_ESC__SIGN; /* change state */
+ pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */
+ }
+ pRemainingBitsInSegment[segmentOffset] -= 1; /* the last reinitialzation of for loop counter (see above) is done here */
+ break; /* end of branch in tree reached i.e. a whole nonPCW-Body is decoded */
+ }
+ else { /* body is not decoded completely: */
+ /* update treeNode for further step in decoding tree and store updated treeNode because maybe no more bits left in segment */
+ treeNode = *(pCurrentTree + branchValue);
+ iNode[codewordOffset] = treeNode;
+ }
+ }
+
+ if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */
+
+#if STATE_MACHINE_ERROR_CHECK
+ if ( pRemainingBitsInSegment[segmentOffset] < 0 ) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__BODY;
+ return BODY_SIGN_ESC__BODY;
+ }
+#endif
+ }
+
+ return STOP_THIS_STATE;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: This state decodes the sign bits, if a codeword of codebook 11 needs some.
+ A flag named 'flagB' in codeword sideinfo is set, if the second line of
+ quantized spectral values is 16. The 'flagB' is used in case of decoding
+ of a escape sequence is necessary as far as the second line is concerned.
+
+ If only the first line needs an escape sequence, the flagB is cleared.
+ If only the second line needs an escape sequence, the flagB is not used.
+
+ For storing sideinfo in case of escape sequence decoding one single word
+ can be used for both escape sequences because they are decoded not at the
+ same time:
+
+
+ bit 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ ===== == == =========== =========== ===================================
+ ^ ^ ^ ^ ^ ^
+ | | | | | |
+ res. flagA flagB escapePrefixUp escapePrefixDown escapeWord
+
+-----------------------------------------------------------------------------------------------
+ output: Two lines with correct sign. If one or two values is/are 16, the lines are
+ not valid, otherwise they are.
+-----------------------------------------------------------------------------------------------
+ return: 0
+-------------------------------------------------------------------------------------------- */
+UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr)
+{
+ H_HCR_INFO pHcr = (H_HCR_INFO)ptr;
+ SCHAR *pRemainingBitsInSegment;
+ USHORT *pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment;
+ UCHAR readDirection;
+ UINT *pSegmentBitfield;
+ UINT *pCodewordBitfield;
+ UINT segmentOffset;
+
+ UINT *iNode;
+ UCHAR *pCntSign;
+ FIXP_DBL *pResultBase;
+ USHORT *iResultPointer;
+ UINT *pEscapeSequenceInfo;
+ UINT codewordOffset;
+
+ UINT iQSC;
+ UCHAR cntSign;
+ UINT flagA;
+ UINT flagB;
+ UINT flags;
+ UCHAR carryBit;
+ SCHAR *pSta;
+
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ readDirection = pHcr->segmentInfo.readDirection;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+ segmentOffset = pHcr->segmentInfo.segmentOffset;
+
+ iNode = pHcr->nonPcwSideinfo.iNode;
+ pCntSign = pHcr->nonPcwSideinfo.pCntSign;
+ pResultBase = pHcr->nonPcwSideinfo.pResultBase;
+ iResultPointer = pHcr->nonPcwSideinfo.iResultPointer;
+ pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo;
+ codewordOffset = pHcr->nonPcwSideinfo.codewordOffset;
+ pSta = pHcr->nonPcwSideinfo.pSta;
+
+ iQSC = iResultPointer[codewordOffset];
+ cntSign = pCntSign[codewordOffset];
+
+
+ /* loop for sign bit decoding */
+ for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) {
+
+ carryBit = HcrGetABitFromBitstream( bs,
+ &pLeftStartOfSegment[segmentOffset],
+ &pRightStartOfSegment[segmentOffset],
+ readDirection);
+
+ /* decrement sign counter because one sign bit has been read */
+ cntSign -= 1;
+ pCntSign[codewordOffset] = cntSign;
+
+ /* get a quantized spectral value (which was decoded in previous state) which is not zero. [This value will get a sign] */
+ while ( pResultBase[iQSC] == (FIXP_DBL)0 ) {
+ iQSC++;
+ }
+ iResultPointer[codewordOffset] = iQSC;
+
+ /* put negative sign together with quantized spectral value; if carryBit is zero, the sign is ok already; no write operation necessary in this case */
+ if ( carryBit != 0 ) {
+ pResultBase[iQSC] = - pResultBase[iQSC]; /* carryBit = 1 --> minus */
+ }
+ iQSC++; /* update index to next (maybe valid) value */
+ iResultPointer[codewordOffset] = iQSC;
+
+ if ( cntSign == 0 ) {
+ /* all sign bits are decoded now */
+ pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */
+
+ /* check decoded values if codeword is decoded: Check if one or two escape sequences 16 follow */
+
+ /* step 0 */
+ /* restore pointer to first decoded quantized value [ = original pResultPointr] from index iNode prepared in State_BODY_SIGN_ESC__BODY */
+ iQSC = iNode[codewordOffset];
+
+ /* step 1 */
+ /* test first value if escape sequence follows */
+ flagA = 0; /* for first possible escape sequence */
+ if ( fixp_abs(pResultBase[iQSC++]) == (FIXP_DBL)ESCAPE_VALUE ) {
+ flagA = 1;
+ }
+
+ /* step 2 */
+ /* test second value if escape sequence follows */
+ flagB = 0; /* for second possible escape sequence */
+ if ( fixp_abs(pResultBase[iQSC]) == (FIXP_DBL)ESCAPE_VALUE ) {
+ flagB = 1;
+ }
+
+
+ /* step 3 */
+ /* evaluate flag result and go on if necessary */
+ if ( !flagA && !flagB ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */
+ }
+ else {
+ /* at least one of two lines is 16 */
+ /* store both flags at correct positions in non PCW codeword sideinfo pEscapeSequenceInfo[codewordOffset] */
+ flags = 0;
+ flags = flagA << POSITION_OF_FLAG_A;
+ flags |= (flagB << POSITION_OF_FLAG_B);
+ pEscapeSequenceInfo[codewordOffset] = flags;
+
+
+ /* set next state */
+ pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX;
+ pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */
+
+ /* set result pointer to the first line of the two decoded lines */
+ iResultPointer[codewordOffset] = iNode[codewordOffset];
+
+ if ( !flagA && flagB ) {
+ /* update pResultPointr ==> state Stat_BODY_SIGN_ESC__ESC_WORD writes to correct position. Second value is the one and only escape value */
+ iQSC = iResultPointer[codewordOffset];
+ iQSC++;
+ iResultPointer[codewordOffset] = iQSC;
+ }
+
+ } /* at least one of two lines is 16 */
+ break; /* nonPCW-Body at cb 11 and according sign bits are decoded */
+
+ } /* if ( cntSign == 0 ) */
+ } /* loop over remaining Bits in segment */
+
+ if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */
+
+#if STATE_MACHINE_ERROR_CHECK
+ if ( pRemainingBitsInSegment[segmentOffset] < 0 ) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__SIGN;
+ return BODY_SIGN_ESC__SIGN;
+ }
+#endif
+
+ }
+ return STOP_THIS_STATE;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Decode escape prefix of first or second escape sequence. The escape prefix
+ consists of ones. The following zero is also decoded here.
+-----------------------------------------------------------------------------------------------
+ output: If the single separator-zero which follows the escape-prefix-ones is not yet decoded:
+ The value 'escapePrefixUp' in word pEscapeSequenceInfo[codewordOffset] is updated.
+
+ If the single separator-zero which follows the escape-prefix-ones is decoded:
+ Two updated values 'escapePrefixUp' and 'escapePrefixDown' in word
+ pEscapeSequenceInfo[codewordOffset]. This State is finished. Switch to next state.
+-----------------------------------------------------------------------------------------------
+ return: 0
+-------------------------------------------------------------------------------------------- */
+UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr)
+{
+ H_HCR_INFO pHcr = (H_HCR_INFO)ptr;
+ SCHAR *pRemainingBitsInSegment;
+ USHORT *pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment;
+ UCHAR readDirection;
+ UINT *pSegmentBitfield;
+ UINT segmentOffset;
+ UINT *pEscapeSequenceInfo;
+ UINT codewordOffset;
+ UCHAR carryBit;
+ UINT escapePrefixUp;
+ SCHAR *pSta;
+
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ readDirection = pHcr->segmentInfo.readDirection;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ segmentOffset = pHcr->segmentInfo.segmentOffset;
+ pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo;
+ codewordOffset = pHcr->nonPcwSideinfo.codewordOffset;
+ pSta = pHcr->nonPcwSideinfo.pSta;
+
+ escapePrefixUp = (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> LSB_ESCAPE_PREFIX_UP;
+
+
+ /* decode escape prefix */
+ for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) {
+
+ carryBit = HcrGetABitFromBitstream( bs,
+ &pLeftStartOfSegment[segmentOffset],
+ &pRightStartOfSegment[segmentOffset],
+ readDirection);
+
+ /* count ones and store sum in escapePrefixUp */
+ if ( carryBit == 1 ) {
+ escapePrefixUp += 1; /* update conter for ones */
+
+ /* store updated counter in sideinfo of current codeword */
+ pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */
+ escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */
+ pEscapeSequenceInfo[codewordOffset] |= escapePrefixUp; /* insert new escapePrefixUp */
+ escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */
+ }
+ else { /* separator [zero] reached */
+ pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */
+ escapePrefixUp += 4; /* if escape_separator '0' appears, add 4 and ==> break */
+
+ /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit position escapePrefixUp */
+ pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */
+ escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */
+ pEscapeSequenceInfo[codewordOffset] |= escapePrefixUp; /* insert new escapePrefixUp */
+ escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */
+
+ /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit position escapePrefixDown */
+ pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */
+ escapePrefixUp <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */
+ pEscapeSequenceInfo[codewordOffset] |= escapePrefixUp; /* insert new escapePrefixDown */
+ escapePrefixUp >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back down */
+
+ pSta[codewordOffset] = BODY_SIGN_ESC__ESC_WORD; /* set next state */
+ pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */
+ break;
+ }
+ }
+
+ if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */
+
+#if STATE_MACHINE_ERROR_CHECK
+ if ( pRemainingBitsInSegment[segmentOffset] < 0 ) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX;
+ return BODY_SIGN_ESC__ESC_PREFIX;
+ }
+#endif
+ }
+
+ return STOP_THIS_STATE;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Decode escapeWord of escape sequence. If the escape sequence is decoded
+ completely, assemble quantized-spectral-escape-coefficient and replace the
+ previous decoded 16 by the new value.
+ Test flagB. If flagB is set, the second escape sequence must be decoded. If
+ flagB is not set, the codeword is decoded and the state machine is switched
+ off.
+-----------------------------------------------------------------------------------------------
+ output: Two lines with valid sign. At least one of both lines has got the correct
+ value.
+-----------------------------------------------------------------------------------------------
+ return: 0
+-------------------------------------------------------------------------------------------- */
+UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM bs, void *ptr)
+{
+ H_HCR_INFO pHcr = (H_HCR_INFO)ptr;
+ SCHAR *pRemainingBitsInSegment;
+ USHORT *pLeftStartOfSegment;
+ USHORT *pRightStartOfSegment;
+ UCHAR readDirection;
+ UINT *pSegmentBitfield;
+ UINT *pCodewordBitfield;
+ UINT segmentOffset;
+
+ FIXP_DBL *pResultBase;
+ USHORT *iResultPointer;
+ UINT *pEscapeSequenceInfo;
+ UINT codewordOffset;
+
+ UINT escapeWord;
+ UINT escapePrefixDown;
+ UINT escapePrefixUp;
+ UCHAR carryBit;
+ UINT iQSC;
+ INT sign;
+ UINT flagA;
+ UINT flagB;
+ SCHAR *pSta;
+
+ pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment;
+ pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment;
+ pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment;
+ readDirection = pHcr->segmentInfo.readDirection;
+ pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield;
+ pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield;
+ segmentOffset = pHcr->segmentInfo.segmentOffset;
+
+ pResultBase = pHcr->nonPcwSideinfo.pResultBase;
+ iResultPointer = pHcr->nonPcwSideinfo.iResultPointer;
+ pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo;
+ codewordOffset = pHcr->nonPcwSideinfo.codewordOffset;
+ pSta = pHcr->nonPcwSideinfo.pSta;
+
+ escapeWord = pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_WORD;
+ escapePrefixDown = (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_DOWN) >> LSB_ESCAPE_PREFIX_DOWN;
+
+
+ /* decode escape word */
+ for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) {
+
+ carryBit = HcrGetABitFromBitstream( bs,
+ &pLeftStartOfSegment[segmentOffset],
+ &pRightStartOfSegment[segmentOffset],
+ readDirection);
+
+ /* build escape word */
+ escapeWord <<= 1; /* left shift previous decoded part of escapeWord by on bit */
+ escapeWord = escapeWord | carryBit; /* assemble escape word by bitwise or */
+
+ /* decrement counter for length of escape word because one more bit was decoded */
+ escapePrefixDown -= 1;
+
+ /* store updated escapePrefixDown */
+ pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */
+ escapePrefixDown <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */
+ pEscapeSequenceInfo[codewordOffset] |= escapePrefixDown; /* insert new escapePrefixDown */
+ escapePrefixDown >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back */
+
+
+ /* store updated escapeWord */
+ pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_WORD; /* delete old escapeWord */
+ pEscapeSequenceInfo[codewordOffset] |= escapeWord; /* insert new escapeWord */
+
+
+ if ( escapePrefixDown == 0 ) {
+ pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */
+
+ /* escape sequence decoded. Assemble escape-line and replace original line */
+
+ /* step 0 */
+ /* derive sign */
+ iQSC = iResultPointer[codewordOffset];
+ sign = (pResultBase[iQSC] >= (FIXP_DBL)0) ? 1 : -1; /* get sign of escape value 16 */
+
+ /* step 1 */
+ /* get escapePrefixUp */
+ escapePrefixUp = (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> LSB_ESCAPE_PREFIX_UP;
+
+ /* step 2 */
+ /* calculate escape value */
+ pResultBase[iQSC] = (FIXP_DBL)(sign * (((INT) 1 << escapePrefixUp) + escapeWord));
+
+ /* get both flags from sideinfo (flags are not shifted to the lsb-position) */
+ flagA = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_A;
+ flagB = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_B;
+
+ /* step 3 */
+ /* clear the whole escape sideinfo word */
+ pEscapeSequenceInfo[codewordOffset] = 0;
+
+ /* change state in dependence of flag flagB */
+ if ( flagA != 0 ) {
+ /* first escape sequence decoded; previous decoded 16 has been replaced by valid line */
+
+ /* clear flagA in sideinfo word because this escape sequence has already beed decoded */
+ pEscapeSequenceInfo[codewordOffset] &= ~MASK_FLAG_A;
+
+ if ( flagB == 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */
+ }
+ else {
+ /* updated pointer to next and last 16 */
+ iQSC++;
+ iResultPointer[codewordOffset] = iQSC;
+
+ /* change state */
+ pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX;
+ pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */
+ }
+ }
+ else {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */
+ }
+ break;
+ }
+ }
+
+ if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) {
+ ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState),
+ segmentOffset,
+ pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */
+
+#if STATE_MACHINE_ERROR_CHECK
+ if ( pRemainingBitsInSegment[segmentOffset] < 0 ) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_WORD;
+ return BODY_SIGN_ESC__ESC_WORD;
+ }
+#endif
+ }
+
+ return STOP_THIS_STATE;
+}
+
diff --git a/libAACdec/src/aacdec_hcrs.h b/libAACdec/src/aacdec_hcrs.h
new file mode 100644
index 0000000..012c089
--- /dev/null
+++ b/libAACdec/src/aacdec_hcrs.h
@@ -0,0 +1,91 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: HCR Decoder: Defines of state-constants, masks and
+ state-prototypes
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#ifndef _AACDEC_HCRS_H_
+#define _AACDEC_HCRS_H_
+
+
+
+#include "FDK_bitstream.h"
+#include "aacdec_hcr_types.h"
+ /* The four different kinds of types of states are: */
+/* different states are defined as constants */ /* start middle=self next stop */
+#define STOP_THIS_STATE 0 /* */
+#define BODY_ONLY 1 /* X X X */
+#define BODY_SIGN__BODY 2 /* X X X X [stop if no sign] */
+#define BODY_SIGN__SIGN 3 /* X X [stop if sign bits decoded] */
+#define BODY_SIGN_ESC__BODY 4 /* X X X X [stop if no sign] */
+#define BODY_SIGN_ESC__SIGN 5 /* X X X [stop if no escape sequence] */
+#define BODY_SIGN_ESC__ESC_PREFIX 6 /* X X */
+#define BODY_SIGN_ESC__ESC_WORD 7 /* X X X [stop if abs(second qsc) != 16] */
+
+/* examples: */
+
+/* BODY_ONLY means only the codeword body will be decoded; no sign bits will follow and no escapesequence will follow */
+
+/* BODY_SIGN__BODY means that the codeword consists of two parts; body and sign part. The part '__BODY' after the two underscores shows */
+/* that the bits which are currently decoded belong to the '__BODY' of the codeword and not to the sign part. */
+
+/* BODY_SIGN_ESC__ESC_PB means that the codeword consists of three parts; body, sign and (here: two) escape sequences; */
+/* P = Prefix = ones */
+/* W = Escape Word */
+/* A = first possible (of two) Escape sequeces */
+/* B = second possible (of two) Escape sequeces */
+/* The part after the two underscores shows that the current bits which are decoded belong to the '__ESC_PB' - part of the */
+/* codeword. That means the body and the sign bits are decoded completely and the bits which are decoded now belong to */
+/* the escape sequence [P = prefix; B=second possible escape sequence] */
+
+
+#define MSB_31_MASK 0x80000000 /* masks MSB (= Bit 31) in a 32 bit word */
+#define DIMENSION_OF_ESCAPE_CODEBOOK 2 /* for cb >= 11 is dimension 2 */
+#define ESCAPE_CODEBOOK 11
+
+#define MASK_ESCAPE_PREFIX_UP 0x000F0000
+#define LSB_ESCAPE_PREFIX_UP 16
+
+#define MASK_ESCAPE_PREFIX_DOWN 0x0000F000
+#define LSB_ESCAPE_PREFIX_DOWN 12
+
+#define MASK_ESCAPE_WORD 0x00000FFF
+#define MASK_FLAG_A 0x00200000
+#define MASK_FLAG_B 0x00100000
+
+
+extern void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO hHcr);
+
+UINT Hcr_State_BODY_ONLY (HANDLE_FDK_BITSTREAM, void*);
+UINT Hcr_State_BODY_SIGN__BODY (HANDLE_FDK_BITSTREAM, void*);
+UINT Hcr_State_BODY_SIGN__SIGN (HANDLE_FDK_BITSTREAM, void*);
+UINT Hcr_State_BODY_SIGN_ESC__BODY (HANDLE_FDK_BITSTREAM, void*);
+UINT Hcr_State_BODY_SIGN_ESC__SIGN (HANDLE_FDK_BITSTREAM, void*);
+UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX (HANDLE_FDK_BITSTREAM, void*);
+UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD (HANDLE_FDK_BITSTREAM, void*);
+
+#endif /* _AACDEC_HCRS_H_ */
+
diff --git a/libAACdec/src/aacdec_pns.cpp b/libAACdec/src/aacdec_pns.cpp
new file mode 100644
index 0000000..bd92fed
--- /dev/null
+++ b/libAACdec/src/aacdec_pns.cpp
@@ -0,0 +1,320 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: perceptual noise substitution tool
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "aacdec_pns.h"
+
+
+#include "aac_ram.h"
+#include "aac_rom.h"
+#include "channelinfo.h"
+#include "block.h"
+#include "FDK_bitstream.h"
+
+#include "genericStds.h"
+
+
+#define NOISE_OFFSET 90 /* cf. ISO 14496-3 p. 175 */
+
+/*!
+ \brief Reset InterChannel and PNS data
+
+ The function resets the InterChannel and PNS data
+*/
+void CPns_ResetData(
+ CPnsData *pPnsData,
+ CPnsInterChannelData *pPnsInterChannelData
+ )
+{
+ /* Assign pointer always, since pPnsData is not persistent data */
+ pPnsData->pPnsInterChannelData = pPnsInterChannelData;
+ pPnsData->PnsActive = 0;
+ pPnsData->CurrentEnergy = 0;
+
+ FDKmemclear(pPnsData->pnsUsed,(8*16)*sizeof(UCHAR));
+ FDKmemclear(pPnsInterChannelData->correlated,(8*16)*sizeof(UCHAR));
+}
+
+/*!
+ \brief Initialize PNS data
+
+ The function initializes the PNS data
+*/
+void CPns_InitPns(
+ CPnsData *pPnsData,
+ CPnsInterChannelData *pPnsInterChannelData,
+ INT* currentSeed, INT* randomSeed)
+{
+ /* save pointer to inter channel data */
+ pPnsData->pPnsInterChannelData = pPnsInterChannelData;
+
+ /* use pointer because seed has to be
+ same, left and right channel ! */
+ pPnsData->currentSeed = currentSeed;
+ pPnsData->randomSeed = randomSeed;
+}
+
+/*!
+ \brief Indicates if PNS is used
+
+ The function returns a value indicating whether PNS is used or not
+ acordding to the noise energy
+
+ \return PNS used
+*/
+int CPns_IsPnsUsed (const CPnsData *pPnsData,
+ const int group,
+ const int band)
+{
+ unsigned pns_band = group*16+band;
+
+ return pPnsData->pnsUsed[pns_band] & (UCHAR)1;
+}
+
+/*!
+ \brief Set correlation
+
+ The function activates the noise correlation between the channel pair
+*/
+void CPns_SetCorrelation(CPnsData *pPnsData,
+ const int group,
+ const int band,
+ const int outofphase)
+{
+ CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
+ unsigned pns_band = group*16+band;
+
+ pInterChannelData->correlated[pns_band] = (outofphase) ? 3 : 1;
+}
+
+/*!
+ \brief Indicates if correlation is used
+
+ The function indicates if the noise correlation between the channel pair
+ is activated
+
+ \return PNS is correlated
+*/
+static
+int CPns_IsCorrelated(const CPnsData *pPnsData,
+ const int group,
+ const int band)
+{
+ CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
+ unsigned pns_band = group*16+band;
+
+ return (pInterChannelData->correlated[pns_band] & 0x01) ? 1 : 0;
+}
+
+/*!
+ \brief Indicates if correlated out of phase mode is used.
+
+ The function indicates if the noise correlation between the channel pair
+ is activated in out-of-phase mode.
+
+ \return PNS is out-of-phase
+*/
+static
+int CPns_IsOutOfPhase(const CPnsData *pPnsData,
+ const int group,
+ const int band)
+{
+ CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
+ unsigned pns_band = group*16+band;
+
+ return (pInterChannelData->correlated[pns_band] & 0x02) ? 1 : 0;
+}
+
+/*!
+ \brief Read PNS information
+
+ The function reads the PNS information from the bitstream
+*/
+void CPns_Read (CPnsData *pPnsData,
+ HANDLE_FDK_BITSTREAM bs,
+ const CodeBookDescription *hcb,
+ SHORT *pScaleFactor,
+ UCHAR global_gain,
+ int band,
+ int group /* = 0 */)
+{
+ int delta ;
+ UINT pns_band = group*16+band;
+
+ if (pPnsData->PnsActive) {
+ /* Next PNS band case */
+ delta = CBlock_DecodeHuffmanWord (bs, hcb) - 60;
+ } else {
+ /* First PNS band case */
+ int noiseStartValue = FDKreadBits(bs,9);
+
+ delta = noiseStartValue - 256 ;
+ pPnsData->PnsActive = 1;
+ pPnsData->CurrentEnergy = global_gain - NOISE_OFFSET;
+ }
+
+ pPnsData->CurrentEnergy += delta ;
+ pScaleFactor[pns_band] = pPnsData->CurrentEnergy;
+
+ pPnsData->pnsUsed[pns_band] = 1;
+}
+
+
+/**
+ * \brief Generate a vector of noise of given length. The noise values are
+ * scaled in order to yield a noise energy of 1.0
+ * \param spec pointer to were the noise values will be written to.
+ * \param size amount of noise values to be generated.
+ * \param pRandomState pointer to the state of the random generator being used.
+ * \return exponent of generated noise vector.
+ */
+static int GenerateRandomVector (FIXP_DBL *RESTRICT spec,
+ int size,
+ int *pRandomState)
+{
+ int i, invNrg_e = 0, nrg_e = 0;
+ FIXP_DBL invNrg_m, nrg_m = FL2FXCONST_DBL(0.0f) ;
+ FIXP_DBL *RESTRICT ptr = spec;
+ int randomState = *pRandomState;
+
+#define GEN_NOISE_NRG_SCALE 7
+
+ /* Generate noise and calculate energy. */
+ for (i=0; i<size; i++)
+ {
+ randomState = (1664525L * randomState) + 1013904223L; // Numerical Recipes
+ nrg_m = fPow2AddDiv2(nrg_m, (FIXP_DBL)randomState>>GEN_NOISE_NRG_SCALE);
+ *ptr++ = (FIXP_DBL)randomState;
+ }
+ nrg_e = GEN_NOISE_NRG_SCALE*2 + 1;
+
+ /* weight noise with = 1 / sqrt_nrg; */
+ invNrg_m = invSqrtNorm2(nrg_m<<1, &invNrg_e);
+ invNrg_e += -((nrg_e-1)>>1);
+
+ for (i=size; i--; )
+ {
+ spec[i] = fMult(spec[i], invNrg_m);
+ }
+
+ /* Store random state */
+ *pRandomState = randomState;
+
+ return invNrg_e;
+}
+
+static void ScaleBand (FIXP_DBL *RESTRICT spec, int size, int scaleFactor, int specScale, int noise_e, int out_of_phase)
+{
+ int i, shift, sfExponent;
+ FIXP_DBL sfMatissa;
+
+ /* Get gain from scale factor value = 2^(scaleFactor * 0.25) */
+ sfMatissa = MantissaTable[scaleFactor & 0x03][0];
+ /* sfExponent = (scaleFactor >> 2) + ExponentTable[scaleFactor & 0x03][0]; */
+ /* Note: ExponentTable[scaleFactor & 0x03][0] is always 1. */
+ sfExponent = (scaleFactor >> 2) + 1;
+
+ if (out_of_phase != 0) {
+ sfMatissa = -sfMatissa;
+ }
+
+ /* +1 because of fMultDiv2 below. */
+ shift = sfExponent - specScale + 1 + noise_e;
+
+ /* Apply gain to noise values */
+ if (shift>=0) {
+ shift = fixMin( shift, DFRACT_BITS-1 );
+ for (i = size ; i-- != 0; ) {
+ spec [i] = fMultDiv2 (spec [i], sfMatissa) << shift;
+ }
+ } else {
+ shift = fixMin( -shift, DFRACT_BITS-1 );
+ for (i = size ; i-- != 0; ) {
+ spec [i] = fMultDiv2 (spec [i], sfMatissa) >> shift;
+ }
+ }
+}
+
+
+/*!
+ \brief Apply PNS
+
+ The function applies PNS (i.e. it generates noise) on the bands
+ flagged as noisy bands
+
+*/
+void CPns_Apply (const CPnsData *pPnsData,
+ const CIcsInfo *pIcsInfo,
+ SPECTRAL_PTR pSpectrum,
+ const SHORT *pSpecScale,
+ const SHORT *pScaleFactor,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const INT granuleLength,
+ const int channel)
+{
+ if (pPnsData->PnsActive) {
+ const short *BandOffsets = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo);
+
+ int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(pIcsInfo);
+
+ for (int window = 0, group = 0; group < GetWindowGroups(pIcsInfo); group++) {
+ for (int groupwin = 0; groupwin < GetWindowGroupLength(pIcsInfo, group); groupwin++, window++) {
+ FIXP_DBL *spectrum = SPEC(pSpectrum, window, granuleLength);
+
+ for (int band = 0 ; band < ScaleFactorBandsTransmitted; band++) {
+ if (CPns_IsPnsUsed (pPnsData, group, band)) {
+ UINT pns_band = group*16+band;
+
+ int bandWidth = BandOffsets [band + 1] - BandOffsets [band] ;
+ int noise_e;
+
+ FDK_ASSERT(bandWidth >= 0);
+
+ if (channel > 0 && CPns_IsCorrelated(pPnsData, group, band))
+ {
+ noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth,
+ &pPnsData->randomSeed [pns_band]) ;
+ }
+ else
+ {
+ pPnsData->randomSeed [pns_band] = *pPnsData->currentSeed ;
+
+ noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth,
+ pPnsData->currentSeed) ;
+ }
+
+ int outOfPhase = CPns_IsOutOfPhase (pPnsData, group, band);
+
+ ScaleBand (spectrum + BandOffsets [band], bandWidth,
+ pScaleFactor[pns_band],
+ pSpecScale[window], noise_e, outOfPhase) ;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/libAACdec/src/aacdec_pns.h b/libAACdec/src/aacdec_pns.h
new file mode 100644
index 0000000..a2d8e98
--- /dev/null
+++ b/libAACdec/src/aacdec_pns.h
@@ -0,0 +1,58 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: perceptual noise substitution tool
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef PNS_H
+#define PNS_H
+
+#include "common_fix.h"
+
+
+#define NO_OFBANDS ((8*16))
+
+typedef struct {
+ UCHAR correlated[NO_OFBANDS];
+} CPnsInterChannelData;
+
+typedef struct {
+ CPnsInterChannelData *pPnsInterChannelData;
+ UCHAR pnsUsed[NO_OFBANDS];
+ int CurrentEnergy;
+ UCHAR PnsActive;
+ INT *currentSeed;
+ INT *randomSeed;
+} CPnsData;
+
+void CPns_InitPns ( CPnsData *pPnsData,
+ CPnsInterChannelData *pPnsInterChannelData,
+ INT* currentSeed,
+ INT* randomSeed );
+
+void CPns_ResetData ( CPnsData *pPnsData, CPnsInterChannelData *pPnsInterChannelData );
+
+
+#endif /* #ifndef PNS_H */
diff --git a/libAACdec/src/aacdec_tns.cpp b/libAACdec/src/aacdec_tns.cpp
new file mode 100644
index 0000000..83ae5ae
--- /dev/null
+++ b/libAACdec/src/aacdec_tns.cpp
@@ -0,0 +1,350 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: temporal noise shaping tool
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "aacdec_tns.h"
+#include "aac_rom.h"
+#include "FDK_bitstream.h"
+#include "channelinfo.h"
+
+
+
+/*!
+ \brief Reset tns data
+
+ The function resets the tns data
+
+ \return none
+*/
+void CTns_Reset(CTnsData *pTnsData)
+{
+ /* Note: the following FDKmemclear should not be required. */
+ FDKmemclear(pTnsData->Filter, TNS_MAX_WINDOWS*TNS_MAXIMUM_FILTERS*sizeof(CFilter));
+ FDKmemclear(pTnsData->NumberOfFilters, TNS_MAX_WINDOWS*sizeof(UCHAR));
+ pTnsData->DataPresent = 0;
+ pTnsData->Active = 0;
+}
+
+void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */
+ CTnsData *pTnsData) /*!< pointer to aac decoder channel info */
+{
+ pTnsData->DataPresent = (UCHAR) FDKreadBits(bs,1);
+}
+
+/*!
+ \brief Read tns data from bitstream
+
+ The function reads the elements for tns from
+ the bitstream.
+
+ \return none
+*/
+AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs,
+ CTnsData *pTnsData,
+ const CIcsInfo *pIcsInfo,
+ const UINT flags)
+{
+ UCHAR n_filt,order;
+ UCHAR length,coef_res,coef_compress;
+ UCHAR window;
+ UCHAR wins_per_frame = GetWindowsPerFrame(pIcsInfo);
+ UCHAR isLongFlag = IsLongBlock(pIcsInfo);
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+
+ if (!pTnsData->DataPresent) {
+ return ErrorStatus;
+ }
+
+ for (window = 0; window < wins_per_frame; window++)
+ {
+ pTnsData->NumberOfFilters[window] = n_filt = (UCHAR) FDKreadBits(bs, isLongFlag ? 2 : 1);
+
+ if (pTnsData->NumberOfFilters[window] > TNS_MAXIMUM_FILTERS){
+ pTnsData->NumberOfFilters[window] = n_filt = TNS_MAXIMUM_FILTERS;
+ }
+
+ if (n_filt)
+ {
+ int index;
+ UCHAR nextstopband;
+
+ coef_res = (UCHAR) FDKreadBits(bs,1);
+
+ nextstopband = GetScaleFactorBandsTotal(pIcsInfo);
+
+ for (index=0; index < n_filt; index++)
+ {
+ CFilter *filter = &pTnsData->Filter[window][index];
+
+ length = (UCHAR)FDKreadBits(bs, isLongFlag ? 6 : 4);
+
+ if (length > nextstopband){
+ length = nextstopband;
+ }
+
+ filter->StartBand = nextstopband - length;
+ filter->StopBand = nextstopband;
+ nextstopband = filter->StartBand;
+
+ {
+ filter->Order = order = (UCHAR) FDKreadBits(bs, isLongFlag ? 5 : 3);
+ }
+
+ if (filter->Order > TNS_MAXIMUM_ORDER){
+ filter->Order = order = TNS_MAXIMUM_ORDER;
+ }
+
+ if (order)
+ {
+ UCHAR coef,s_mask;
+ UCHAR i;
+ SCHAR n_mask;
+ static const UCHAR sgn_mask[] = { 0x2, 0x4, 0x8 };
+ static const SCHAR neg_mask[] = { ~0x3, ~0x7, ~0xF };
+
+ filter->Direction = FDKreadBits(bs,1) ? -1 : 1;
+
+ coef_compress = (UCHAR) FDKreadBits(bs,1);
+
+ filter->Resolution = coef_res + 3;
+
+ s_mask = sgn_mask[coef_res + 1 - coef_compress];
+ n_mask = neg_mask[coef_res + 1 - coef_compress];
+
+ for (i=0; i < order; i++)
+ {
+ coef = (UCHAR) FDKreadBits(bs,filter->Resolution - coef_compress);
+ filter->Coeff[i] = (coef & s_mask) ? (coef | n_mask) : coef;
+ }
+ }
+ }
+ }
+ }
+
+ pTnsData->Active = 1;
+
+ return ErrorStatus;
+}
+
+
+static void CTns_Filter (FIXP_DBL *spec, int size, int inc, FIXP_TCC coeff [], int order)
+{
+ // - Simple all-pole filter of order "order" defined by
+ // y(n) = x(n) - a(2)*y(n-1) - ... - a(order+1)*y(n-order)
+ //
+ // - The state variables of the filter are initialized to zero every time
+ //
+ // - The output data is written over the input data ("in-place operation")
+ //
+ // - An input vector of "size" samples is processed and the index increment
+ // to the next data sample is given by "inc"
+
+ int i,j,N;
+ FIXP_DBL *pSpec;
+ FIXP_DBL maxVal=FL2FXCONST_DBL(0.0);
+ INT s;
+
+ FDK_ASSERT(order <= TNS_MAXIMUM_ORDER);
+ C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER);
+ FDKmemclear(state, order*sizeof(FIXP_DBL));
+
+ for (i=0; i<size; i++) {
+ maxVal = fixMax(maxVal,fixp_abs(spec[i]));
+ }
+
+ if ( maxVal > FL2FXCONST_DBL(0.03125*0.70710678118) )
+ s = fixMax(CntLeadingZeros(maxVal)-6,0);
+ else
+ s = fixMax(CntLeadingZeros(maxVal)-5,0);
+
+ s = fixMin(s,2);
+ s = s-1;
+
+ if (inc == -1)
+ pSpec = &spec[size - 1];
+ else
+ pSpec = &spec[0];
+
+ FIXP_TCC *pCoeff;
+
+#define FIRST_PART_FLTR \
+ FIXP_DBL x, *pState = state; \
+ pCoeff = coeff; \
+ \
+ if (s < 0) \
+ x = (pSpec [0]>>1) + fMultDiv2 (*pCoeff++, pState [0]) ; \
+ else \
+ x = (pSpec [0]<<s) + fMultDiv2 (*pCoeff++, pState [0]) ;
+
+#define INNER_FLTR_INLINE \
+ x = fMultAddDiv2 (x, *pCoeff, pState [1]); \
+ pState [0] = pState [1] - (fMultDiv2 (*pCoeff++, x) <<2) ; \
+ pState++;
+
+#define LAST_PART_FLTR \
+ if (s < 0) \
+ *pSpec = x << 1; \
+ else \
+ *pSpec = x >> s; \
+ *pState =(-x) << 1; \
+ pSpec += inc ;
+
+
+ if (order>8)
+ {
+ N = (order-1)&7;
+
+ for (i = size ; i != 0 ; i--)
+ {
+ FIRST_PART_FLTR
+
+ for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE }
+
+ INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE
+ INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE
+
+ LAST_PART_FLTR
+ }
+
+ } else if (order>4) {
+
+ N = (order-1)&3;
+
+ for (i = size ; i != 0 ; i--)
+ {
+ FIRST_PART_FLTR
+ for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE }
+
+ INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE
+
+ LAST_PART_FLTR
+ }
+
+ } else {
+
+ N = order-1;
+
+ for (i = size ; i != 0 ; i--)
+ {
+ FIRST_PART_FLTR
+
+ for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE }
+
+ LAST_PART_FLTR
+ }
+ }
+
+ C_ALLOC_SCRATCH_END(state, FIXP_DBL, TNS_MAXIMUM_ORDER);
+}
+
+/*!
+ \brief Apply tns to spectral lines
+
+ The function applies the tns to the spectrum,
+
+ \return none
+*/
+void CTns_Apply (
+ CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */
+ const CIcsInfo *pIcsInfo,
+ SPECTRAL_PTR pSpectralCoefficient,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const INT granuleLength
+ )
+{
+ int window,index,start,stop,size;
+
+
+ if (pTnsData->Active)
+ {
+ C_AALLOC_SCRATCH_START(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER);
+
+ for (window=0; window < GetWindowsPerFrame(pIcsInfo); window++)
+ {
+ FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, granuleLength);
+
+ for (index=0; index < pTnsData->NumberOfFilters[window]; index++)
+ {
+ CFilter *RESTRICT filter = &pTnsData->Filter[window][index];
+
+ if (filter->Order > 0)
+ {
+ FIXP_TCC *pCoeff;
+ int tns_max_bands;
+
+ pCoeff = &coeff[filter->Order-1];
+ if (filter->Resolution == 3)
+ {
+ int i;
+ for (i=0; i < filter->Order; i++)
+ *pCoeff-- = FDKaacDec_tnsCoeff3[filter->Coeff[i]+4];
+ }
+ else
+ {
+ int i;
+ for (i=0; i < filter->Order; i++)
+ *pCoeff-- = FDKaacDec_tnsCoeff4[filter->Coeff[i]+8];
+ }
+
+ switch (granuleLength) {
+ case 480:
+ tns_max_bands = tns_max_bands_tbl_480[pSamplingRateInfo->samplingRateIndex-3];
+ break;
+ case 512:
+ tns_max_bands = tns_max_bands_tbl_512[pSamplingRateInfo->samplingRateIndex-3];
+ break;
+ default:
+ tns_max_bands = GetMaximumTnsBands(pIcsInfo, pSamplingRateInfo->samplingRateIndex);
+ break;
+ }
+
+ start = fixMin( fixMin(filter->StartBand, tns_max_bands),
+ GetScaleFactorBandsTransmitted(pIcsInfo) );
+
+ start = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[start];
+
+ stop = fixMin( fixMin(filter->StopBand, tns_max_bands),
+ GetScaleFactorBandsTransmitted(pIcsInfo) );
+
+ stop = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[stop];
+
+ size = stop - start;
+
+ if (size > 0) {
+ CTns_Filter(&pSpectrum[start],
+ size,
+ filter->Direction,
+ coeff,
+ filter->Order );
+ }
+ }
+ }
+ }
+ C_AALLOC_SCRATCH_END(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER);
+ }
+
+}
diff --git a/libAACdec/src/aacdec_tns.h b/libAACdec/src/aacdec_tns.h
new file mode 100644
index 0000000..cf3f597
--- /dev/null
+++ b/libAACdec/src/aacdec_tns.h
@@ -0,0 +1,64 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: temporal noise shaping tool
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef TNS_H
+#define TNS_H
+
+#include "common_fix.h"
+
+enum
+{
+ TNS_MAX_WINDOWS = 8, /* 8 */
+ TNS_MAXIMUM_ORDER = 12, /* 12 for AAC-LC and AAC-SSR. Set to 20 for AAC-Main (AOT 1). Some broken encoders also do order 20 for AAC-LC :( */
+ TNS_MAXIMUM_FILTERS = 3
+};
+
+typedef struct
+{
+ SCHAR Coeff[TNS_MAXIMUM_ORDER];
+
+ UCHAR StartBand;
+ UCHAR StopBand;
+
+ SCHAR Direction;
+ SCHAR Resolution;
+
+ UCHAR Order;
+} CFilter;
+
+typedef struct
+{
+ CFilter Filter[TNS_MAX_WINDOWS][TNS_MAXIMUM_FILTERS];
+ UCHAR NumberOfFilters[TNS_MAX_WINDOWS];
+ UCHAR DataPresent;
+ UCHAR Active;
+} CTnsData;
+
+void CTns_Reset(CTnsData *pTnsData);
+
+#endif /* #ifndef TNS_H */
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
new file mode 100644
index 0000000..534d48f
--- /dev/null
+++ b/libAACdec/src/aacdecoder.cpp
@@ -0,0 +1,1667 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+
+/*!
+ \page default General Overview of the AAC Decoder Implementation
+
+ The main entry point to decode a AAC frame is CAacDecoder_DecodeFrame(). It handles the different
+ transport multiplexes and bitstream formats supported by this implementation. It extracts the
+ AAC_raw_data_blocks from these bitstreams to further process then in the actual decoding stages.
+
+ Note: Click on a function of file in the above image to see details about the function. Also note, that
+ this is just an overview of the most important functions and not a complete call graph.
+
+ <h2>1 Bitstream deformatter</h2>
+ The basic bit stream parser function CChannelElement_Read() is called. It uses other subcalls in order
+ to parse and unpack the bitstreams. Note, that this includes huffmann decoding of the coded spectral data.
+ This operation can be computational significant specifically at higher bitrates. Optimization is likely in
+ CBlock_ReadSpectralData().
+
+ The bitstream deformatter also includes many bitfield operations. Profiling on the target will determine
+ required optimizations.
+
+ <h2>2 Actual decoding to retain the time domain output</h2>
+ The basic bitstream deformatter function CChannelElement_Decode() for CPE elements and SCE elements are called.
+ Except for the stereo processing (2.1) which is only used for CPE elements, the function calls for CPE or SCE
+ are similar, except that CPE always processes to independent channels while SCE only processes one channel.
+
+ Often there is the distinction between long blocks and short blocks. However, computational expensive functions
+ that ususally require optimization are being shared by these two groups,
+
+ <h3>2.1 Stereo processing for CPE elements</h3>
+ CChannelPairElement_Decode() first calles the joint stereo tools in stereo.cpp when required.
+
+ <h3>2.2 Scaling of spectral data</h3>
+ CBlock_ScaleSpectralData().
+
+ <h3>2.3 Apply additional coding tools</h3>
+ ApplyTools() calles the PNS tools in case of MPEG-4 bitstreams, and TNS filtering CTns_Apply() for MPEG-2 and MPEG-4 bitstreams.
+ The function TnsFilterIIR() which is called by CTns_Apply() (2.3.1) might require some optimization.
+
+ <h2>3 Frequency-To-Time conversion</h3>
+ The filterbank is called using CBlock_FrequencyToTime() using the MDCT module from the FDK Tools
+
+*/
+
+
+
+#include "aacdecoder.h"
+
+#include "aac_rom.h"
+#include "aac_ram.h"
+#include "channel.h"
+#include "FDK_audio.h"
+
+#include "FDK_tools_rom.h"
+
+ #include "aacdec_pns.h"
+
+/*#ifdef AACDEC_HDAAC_ENABLE
+#include "slsdecifc.h"
+#endif
+*/
+
+ #include "sbrdecoder.h"
+
+
+
+
+ #include "aacdec_hcr.h"
+ #include "rvlc.h"
+
+
+#include "tpdec_lib.h"
+
+#include "conceal.h"
+
+
+
+#define CAN_DO_PS(aot) \
+ ((aot) == AOT_AAC_LC \
+|| (aot) == AOT_SBR \
+|| (aot) == AOT_PS \
+|| (aot) == AOT_ER_BSAC \
+|| (aot) == AOT_DRM_AAC)
+
+#define IS_USAC(aot) \
+ ((aot) == AOT_USAC \
+|| (aot) == AOT_RSVD50)
+
+#define IS_LOWDELAY(aot) \
+ ((aot) == AOT_ER_AAC_LD \
+|| (aot) == AOT_ER_AAC_ELD)
+
+void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self)
+{
+
+ /* Assign user requested mode */
+ self->qmfModeCurr = self->qmfModeUser;
+
+ if ( self->qmfModeCurr == NOT_DEFINED )
+ {
+ if ( (IS_LOWDELAY(self->streamInfo.aot) && (self->flags & AC_MPS_PRESENT))
+ || ( (self->ascChannels == 1)
+ && ( (CAN_DO_PS(self->streamInfo.aot) && !(self->flags & AC_MPS_PRESENT))
+ || ( IS_USAC(self->streamInfo.aot) && (self->flags & AC_MPS_PRESENT)) ) ) )
+ {
+ self->qmfModeCurr = MODE_HQ;
+ } else {
+ self->qmfModeCurr = MODE_LP;
+ }
+ }
+
+
+ /* Set SBR to current QMF mode. Error does not matter. */
+ sbrDecoder_SetParam(self->hSbrDecoder, SBR_QMF_MODE, (self->qmfModeCurr == MODE_LP));
+ self->psPossible = ((CAN_DO_PS(self->streamInfo.aot) && self->aacChannels == 1 && ! (self->flags & AC_MPS_PRESENT))) && self->qmfModeCurr == MODE_HQ ;
+ FDK_ASSERT( ! ( (self->flags & AC_MPS_PRESENT) && self->psPossible ) );
+}
+
+void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self)
+{
+}
+
+/*!
+ \brief Reset ancillary data struct. Call before parsing a new frame.
+
+ \ancData Pointer to ancillary data structure
+
+ \return Error code
+*/
+static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData)
+{
+ int i;
+ for (i=0; i<8; i++)
+ {
+ ancData->offset[i] = 0;
+ }
+ ancData->nrElements = 0;
+
+ return AAC_DEC_OK;
+}
+
+/*!
+ \brief Initialize ancillary buffer
+
+ \ancData Pointer to ancillary data structure
+ \buffer Pointer to (external) anc data buffer
+ \size Size of the buffer pointed on by buffer in bytes
+
+ \return Error code
+*/
+AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buffer, int size)
+{
+ if (size >= 0) {
+ ancData->buffer = buffer;
+ ancData->bufferSize = size;
+
+ CAacDecoder_AncDataReset(ancData);
+
+ return AAC_DEC_OK;
+ }
+
+ return AAC_DEC_ANC_DATA_ERROR;
+}
+
+/*!
+ \brief Get one ancillary data element
+
+ \ancData Pointer to ancillary data structure
+ \index Index of the anc data element to get
+ \ptr Pointer to a buffer receiving a pointer to the requested anc data element
+ \size Pointer to a buffer receiving the length of the requested anc data element in bytes
+
+ \return Error code
+*/
+AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, unsigned char **ptr, int *size)
+{
+ AAC_DECODER_ERROR error = AAC_DEC_OK;
+
+ *ptr = NULL;
+ *size = 0;
+
+ if (index >= 0 && index < 8 && index < ancData->nrElements)
+ {
+ *ptr = &ancData->buffer[ancData->offset[index]];
+ *size = ancData->offset[index+1] - ancData->offset[index];
+ }
+
+ return error;
+}
+
+
+/*!
+ \brief Parse ancillary data
+
+ \ancData Pointer to ancillary data structure
+ \hBs Handle to FDK bitstream
+ \ancBytes Length of ancillary data to read from the bitstream
+
+ \return Error code
+*/
+static
+AAC_DECODER_ERROR CAacDecoder_AncDataParse (
+ CAncData *ancData,
+ HANDLE_FDK_BITSTREAM hBs,
+ const int ancBytes )
+{
+ AAC_DECODER_ERROR error = AAC_DEC_OK;
+ int readBytes = 0;
+
+ if (ancData->buffer != NULL)
+ {
+ if (ancBytes > 0) {
+ /* write ancillary data to external buffer */
+ int offset = ancData->offset[ancData->nrElements];
+
+ if ((offset + ancBytes) > ancData->bufferSize)
+ {
+ error = AAC_DEC_TOO_SMALL_ANC_BUFFER;
+ }
+ else if (ancData->nrElements >= 8-1)
+ {
+ error = AAC_DEC_TOO_MANY_ANC_ELEMENTS;
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < ancBytes; i++) {
+ ancData->buffer[i+offset] = FDKreadBits(hBs, 8);
+ readBytes++;
+ }
+
+ ancData->nrElements++;
+ ancData->offset[ancData->nrElements] = ancBytes + ancData->offset[ancData->nrElements-1];
+ }
+ }
+ }
+
+ readBytes = ancBytes - readBytes;
+
+ if (readBytes > 0) {
+ /* skip data */
+ FDKpushFor(hBs, readBytes<<3);
+ }
+
+ return error;
+}
+
+/*!
+ \brief Read Stream Data Element
+
+ \bs Bitstream Handle
+
+ \return Error code
+*/
+static AAC_DECODER_ERROR CDataStreamElement_Read (
+ HANDLE_FDK_BITSTREAM bs,
+ CAncData *ancData,
+ HANDLE_AAC_DRC hDrcInfo,
+ HANDLE_TRANSPORTDEC pTp,
+ UCHAR *elementInstanceTag,
+ UINT alignmentAnchor )
+{
+ AAC_DECODER_ERROR error = AAC_DEC_OK;
+ UINT dataStart;
+ int dataByteAlignFlag, count;
+
+ int crcReg = transportDec_CrcStartReg(pTp, 0);
+
+ /* Element Instance Tag */
+ *elementInstanceTag = FDKreadBits(bs,4);
+ /* Data Byte Align Flag */
+ dataByteAlignFlag = FDKreadBits(bs,1);
+
+ count = FDKreadBits(bs,8);
+
+ if (count == 255) {
+ count += FDKreadBits(bs,8); /* EscCount */
+ }
+
+ if (dataByteAlignFlag) {
+ FDKbyteAlign(bs, alignmentAnchor);
+ }
+
+ dataStart = FDKgetValidBits(bs);
+
+ error = CAacDecoder_AncDataParse(ancData, bs, count);
+ transportDec_CrcEndReg(pTp, crcReg);
+
+ {
+ INT readBits, dataBits = count<<3;
+
+ /* Move to the beginning of the data junk */
+ FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
+
+ /* Read Anc data if available */
+ readBits = aacDecoder_drcMarkPayload( hDrcInfo, bs, DVB_DRC_ANC_DATA );
+
+ if (readBits != dataBits) {
+ /* Move to the end again. */
+ FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dataBits);
+ }
+ }
+
+ return error;
+}
+
+#ifdef TP_PCE_ENABLE
+/*!
+ \brief Read Program Config Element
+
+ \bs Bitstream Handle
+ \count Pointer to program config element.
+
+ \return Error code
+*/
+static AAC_DECODER_ERROR CProgramConfigElement_Read (
+ HANDLE_FDK_BITSTREAM bs,
+ HANDLE_TRANSPORTDEC pTp,
+ CProgramConfig *pce,
+ UINT alignAnchor )
+{
+ AAC_DECODER_ERROR error = AAC_DEC_OK;
+ int crcReg;
+
+ /* read PCE to temporal buffer first */
+ C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
+
+ CProgramConfig_Init(tmpPce);
+ CProgramConfig_Reset(tmpPce);
+
+ crcReg = transportDec_CrcStartReg(pTp, 0);
+
+ CProgramConfig_Read(tmpPce, bs, alignAnchor);
+
+ transportDec_CrcEndReg(pTp, crcReg);
+
+ if (!pce->isValid && tmpPce->NumChannels <= (6) && tmpPce->Profile == 1) {
+ /* store PCE data */
+ FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig));
+ }
+
+ C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
+
+ return error;
+}
+#endif
+
+/*!
+ \brief Parse Extension Payload
+
+ \self Handle of AAC decoder
+ \count Pointer to bit counter.
+ \previous_element ID of previous element (required by some extension payloads)
+
+ \return Error code
+*/
+static
+AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self,
+ HANDLE_FDK_BITSTREAM hBs,
+ int *count,
+ MP4_ELEMENT_ID previous_element,
+ int elIndex,
+ int fIsFillElement)
+{
+ AAC_DECODER_ERROR error = AAC_DEC_OK;
+ EXT_PAYLOAD_TYPE extension_type;
+ int bytes = (*count) >> 3;
+ int crcFlag = 0;
+
+ if (*count < 4) {
+ return AAC_DEC_PARSE_ERROR;
+ } else if ((INT)FDKgetValidBits(hBs) < *count) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+
+ extension_type = (EXT_PAYLOAD_TYPE) FDKreadBits(hBs, 4); /* bs_extension_type */
+ *count -= 4;
+
+ switch (extension_type)
+ {
+ case EXT_DYNAMIC_RANGE:
+ {
+ INT readBits = aacDecoder_drcMarkPayload( self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA );
+
+ if (readBits > *count)
+ {
+ FDKpushBack(hBs, readBits - *count);
+ error = AAC_DEC_PARSE_ERROR;
+ return error;
+ }
+ else
+ {
+ *count -= (readBits+7) & ~0x7;
+ }
+ }
+ break;
+ case EXT_LDSAC_DATA:
+ case EXT_SAC_DATA:
+ /* Skip MPEG Surround Extension payload */
+ FDKpushFor(hBs, *count);
+ *count = 0;
+ break;
+
+ case EXT_SBR_DATA_CRC:
+ crcFlag = 1;
+
+ case EXT_SBR_DATA:
+ {
+ SBR_ERROR sbrError;
+
+ CAacDecoder_SyncQmfMode(self);
+
+ sbrError = sbrDecoder_InitElement(
+ self->hSbrDecoder,
+ self->streamInfo.aacSampleRate,
+ self->streamInfo.extSamplingRate,
+ self->streamInfo.aacSamplesPerFrame,
+ self->streamInfo.aot,
+ previous_element,
+ elIndex
+ );
+
+ if (sbrError == SBRDEC_OK) {
+ sbrError = sbrDecoder_Parse (
+ self->hSbrDecoder,
+ hBs,
+ count,
+ *count,
+ crcFlag,
+ previous_element,
+ elIndex,
+ self->flags & AC_INDEP );
+ /* Enable SBR for implicit SBR signalling. */
+ if (sbrError == SBRDEC_OK) {
+ self->sbrEnabled = 1;
+ }
+ } else {
+ /* Do not try to apply SBR because initializing the element failed. */
+ self->sbrEnabled = 0;
+ }
+ /* Citation from ISO/IEC 14496-3 chapter 4.5.2.1.5.2
+ Fill elements containing an extension_payload() with an extension_type of EXT_SBR_DATA
+ or EXT_SBR_DATA_CRC shall not contain any other extension_payload of any other extension_type.
+ */
+ if (fIsFillElement) {
+ FDKpushBiDirectional(hBs, *count);
+ *count = 0;
+ } else {
+ /* If this is not a fill element with a known length, we are screwed an no further parsing makes sense. */
+ if (sbrError != SBRDEC_OK) {
+ self->frameOK = 0;
+ }
+ }
+ }
+ break;
+
+ case EXT_FILL_DATA:
+ {
+ int temp;
+
+ temp = FDKreadBits(hBs,4);
+ bytes--;
+ if (temp != 0) {
+ error = AAC_DEC_PARSE_ERROR;
+ break;
+ }
+ while (bytes > 0) {
+ temp = FDKreadBits(hBs,8);
+ bytes--;
+ if (temp != 0xa5) {
+ error = AAC_DEC_PARSE_ERROR;
+ break;
+ }
+ }
+ *count = bytes<<3;
+ }
+ break;
+
+ case EXT_DATA_ELEMENT:
+ {
+ int dataElementVersion;
+
+ dataElementVersion = FDKreadBits(hBs,4);
+ *count -= 4;
+ if (dataElementVersion == 0) /* ANC_DATA */
+ {
+ int temp, dataElementLength = 0;
+ do {
+ temp = FDKreadBits(hBs,8);
+ *count -= 8;
+ dataElementLength += temp;
+ } while (temp == 255 );
+
+ CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength);
+ *count -= (dataElementLength<<3);
+ } else {
+ /* align = 0 */
+ FDKpushFor(hBs, (*count)<<3);
+ *count = 0;
+ }
+ }
+ break;
+
+ case EXT_DATA_LENGTH:
+ {
+ int bitCnt, len = FDKreadBits(hBs, 4);
+ *count -= 4;
+
+ if (len == 15) {
+ int add_len = FDKreadBits(hBs, 8);
+ *count -= 8;
+ len += add_len;
+
+ if (add_len == 255) {
+ len += FDKreadBits(hBs, 16);
+ *count -= 16;
+ }
+ }
+ len <<= 3;
+ bitCnt = len;
+
+ if ( (EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4) == EXT_DATA_LENGTH ) {
+ /* Check NOTE 2: The extension_payload() included here must
+ not have extension_type == EXT_DATA_LENGTH. */
+ error = AAC_DEC_PARSE_ERROR;
+ } else {
+ /* rewind and call myself again. */
+ FDKpushBack(hBs, 4);
+
+ error =
+ CAacDecoder_ExtPayloadParse (
+ self,
+ hBs,
+ &bitCnt,
+ previous_element,
+ elIndex,
+ 0 );
+
+ *count -= len - bitCnt;
+ }
+ }
+ break;
+
+ case EXT_FIL:
+
+ default:
+ /* align = 4 */
+ FDKpushFor(hBs, *count);
+ *count = 0;
+ break;
+ }
+
+ return error;
+}
+
+/* Stream Configuration and Information.
+
+ This class holds configuration and information data for a stream to be decoded. It
+ provides the calling application as well as the decoder with substantial information,
+ e.g. profile, sampling rate, number of channels found in the bitstream etc.
+*/
+static
+void CStreamInfoInit(CStreamInfo *pStreamInfo)
+{
+ pStreamInfo->aacSampleRate = 0;
+ pStreamInfo->profile = -1;
+ pStreamInfo->aot = AOT_NONE;
+
+ pStreamInfo->channelConfig = -1;
+ pStreamInfo->bitRate = 0;
+ pStreamInfo->aacSamplesPerFrame = 0;
+
+ pStreamInfo->extAot = AOT_NONE;
+ pStreamInfo->extSamplingRate = 0;
+
+ pStreamInfo->flags = 0;
+
+ pStreamInfo->epConfig = -1; /* default is no ER */
+
+ pStreamInfo->numChannels = 0;
+ pStreamInfo->sampleRate = 0;
+ pStreamInfo->frameSize = 0;
+}
+
+/*!
+ \brief Initialization of AacDecoderChannelInfo
+
+ The function initializes the pointers to AacDecoderChannelInfo for each channel,
+ set the start values for window shape and window sequence of overlap&add to zero,
+ set the overlap buffer to zero and initializes the pointers to the window coefficients.
+ \param bsFormat is the format of the AAC bitstream
+
+ \return AACDECODER instance
+*/
+LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */
+{
+ HANDLE_AACDECODER self;
+
+ self = GetAacDecoder();
+ if (self == NULL) {
+ goto bail;
+ }
+
+ /* Assign channel mapping info arrays (doing so removes dependency of settings header in API header). */
+ self->streamInfo.pChannelIndices = self->channelIndices;
+ self->streamInfo.pChannelType = self->channelType;
+
+ /* set default output mode */
+ self->outputInterleaved = 1; /* interleaved */
+
+ /* initialize anc data */
+ CAacDecoder_AncDataInit(&self->ancData, NULL, 0);
+
+ /* initialize stream info */
+ CStreamInfoInit(&self->streamInfo);
+
+ /* initialize error concealment common data */
+ CConcealment_InitCommonData(&self->concealCommonData);
+
+ self->hDrcInfo = GetDrcInfo();
+ if (self->hDrcInfo == NULL) {
+ goto bail;
+ }
+ /* Init common DRC structure */
+ aacDecoder_drcInit( self->hDrcInfo );
+ /* Set default frame delay */
+ aacDecoder_drcSetParam (
+ self->hDrcInfo,
+ DRC_BS_DELAY,
+ CConcealment_GetDelay(&self->concealCommonData)
+ );
+
+
+ self->aacCommonData.workBufferCore1 = GetWorkBufferCore1();
+ self->aacCommonData.workBufferCore2 = GetWorkBufferCore2();
+ if (self->aacCommonData.workBufferCore1 == NULL
+ ||self->aacCommonData.workBufferCore2 == NULL )
+ goto bail;
+
+ return self;
+
+bail:
+ CAacDecoder_Close( self );
+
+ return NULL;
+}
+
+/* Destroy aac decoder */
+LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
+{
+ int ch;
+
+ if (self == NULL)
+ return;
+
+ for (ch=0; ch<(6); ch++) {
+ if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
+ FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
+ FreeAacDecoderStaticChannelInfo (&self->pAacDecoderStaticChannelInfo[ch]);
+ }
+ if (self->pAacDecoderChannelInfo[ch] != NULL) {
+ FreeAacDecoderChannelInfo (&self->pAacDecoderChannelInfo[ch]);
+ }
+ }
+
+ self->aacChannels = 0;
+
+ if (self->hDrcInfo) {
+ FreeDrcInfo(&self->hDrcInfo);
+ }
+
+ FreeWorkBufferCore1 (&self->aacCommonData.workBufferCore1);
+ FreeWorkBufferCore2 (&self->aacCommonData.workBufferCore2);
+
+ FreeAacDecoder ( &self);
+}
+
+
+/*!
+ \brief Initialization of decoder instance
+
+ The function initializes the decoder.
+
+ \return error status: 0 for success, <>0 for unsupported configurations
+*/
+LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc)
+{
+ AAC_DECODER_ERROR err = AAC_DEC_OK;
+ INT ascChannels, ch, ascChanged = 0;
+
+ if (!self)
+ return AAC_DEC_INVALID_HANDLE;
+
+ // set profile and check for supported aot
+ // leave profile on default (=-1) for all other supported MPEG-4 aot's except aot=2 (=AAC-LC)
+ switch (asc->m_aot) {
+ case AOT_AAC_LC:
+ self->streamInfo.profile = 1;
+ break;
+
+ case AOT_SBR:
+ case AOT_PS:
+ case AOT_ER_AAC_LD:
+ case AOT_ER_AAC_ELD:
+ break;
+
+ default:
+ return AAC_DEC_UNSUPPORTED_AOT;
+ }
+
+ CProgramConfig_Init(&self->pce);
+
+ /* set channels */
+ switch (asc->m_channelConfiguration) {
+ case 0:
+#ifdef TP_PCE_ENABLE
+ /* get channels from program config (ASC) */
+ if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) {
+ ascChannels = asc->m_progrConfigElement.NumChannels;
+ if (ascChannels > 0) {
+ int el;
+ /* valid number of channels -> copy program config element (PCE) from ASC */
+ FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig));
+ /* Built element table */
+ el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements);
+ for (; el<7; el++) {
+ self->elements[el] = ID_NONE;
+ }
+ } else {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+ } else {
+ if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) {
+ /* set default max_channels for memory allocation because in implicit channel mapping mode
+ we don't know the actual number of channels until we processed at least one raw_data_block(). */
+ ascChannels = (6);
+ } else {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+ }
+#else /* TP_PCE_ENABLE */
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+#endif /* TP_PCE_ENABLE */
+ break;
+ case 1: case 2: case 3: case 4: case 5: case 6:
+ ascChannels = asc->m_channelConfiguration;
+ break;
+ case 7:
+ ascChannels = 8;
+ break;
+ default:
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+
+ /* Initialize constant mappings for channel config 1-7 */
+ if (asc->m_channelConfiguration > 0) {
+ int el;
+ FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,7));
+ for (el=7; el<7; el++) {
+ self->elements[el] = ID_NONE;
+ }
+ for (ch=0; ch<ascChannels; ch++) {
+ self->chMapping[ch] = ch;
+ }
+ for (; ch<(6); ch++) {
+ self->chMapping[ch] = 255;
+ }
+ }
+
+ self->streamInfo.channelConfig = asc->m_channelConfiguration;
+
+ if (ascChannels > (6)) {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+ if (self->streamInfo.aot != asc->m_aot) {
+ self->streamInfo.aot = asc->m_aot;
+ ascChanged = 1;
+ }
+
+ if (self->streamInfo.aacSamplesPerFrame != (INT)asc->m_samplesPerFrame) {
+ self->streamInfo.aacSamplesPerFrame = asc->m_samplesPerFrame;
+ ascChanged = 1;
+ }
+
+ self->streamInfo.bitRate = 0;
+
+ /* Set syntax flags */
+ self->flags = 0;
+
+ self->streamInfo.extAot = asc->m_extensionAudioObjectType;
+ self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency;
+ self->flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
+ self->flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
+ self->sbrEnabled = 0;
+
+ /* --------- vcb11 ------------ */
+ self->flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
+
+ /* ---------- rvlc ------------ */
+ self->flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
+
+ /* ----------- hcr ------------ */
+ self->flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
+
+ if (asc->m_aot == AOT_ER_AAC_ELD) {
+ self->flags |= AC_ELD;
+ self->flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
+ self->flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_LD_MPS : 0;
+ }
+ self->flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
+ self->flags |= (asc->m_epConfig >= 0) ? AC_ER : 0;
+
+
+ if (asc->m_sbrPresentFlag) {
+ self->sbrEnabled = 1;
+ self->sbrEnabledPrev = 1;
+ }
+ if (asc->m_psPresentFlag) {
+ self->flags |= AC_PS_PRESENT;
+ }
+
+ if ( (asc->m_epConfig >= 0)
+ && (asc->m_channelConfiguration <= 0) ) {
+ /* we have to know the number of channels otherwise no decoding is possible */
+ return AAC_DEC_UNSUPPORTED_ER_FORMAT;
+ }
+
+ self->streamInfo.epConfig = asc->m_epConfig;
+ /* self->hInput->asc.m_epConfig = asc->m_epConfig; */
+
+ if (asc->m_epConfig > 1)
+ return AAC_DEC_UNSUPPORTED_ER_FORMAT;
+
+ /* Check if samplerate changed. */
+ if (self->streamInfo.aacSampleRate != (INT)asc->m_samplingFrequency) {
+ AAC_DECODER_ERROR error;
+
+ ascChanged = 1;
+
+ /* Update samplerate info. */
+ error = getSamplingRateInfo(&self->samplingRateInfo, asc->m_samplesPerFrame, asc->m_samplingFrequencyIndex, asc->m_samplingFrequency);
+ if (error != AAC_DEC_OK) {
+ return error;
+ }
+ self->streamInfo.aacSampleRate = self->samplingRateInfo.samplingRate;
+ }
+
+ /* Check if amount of channels has changed. */
+ if (self->ascChannels != ascChannels)
+ {
+ ascChanged = 1;
+
+ /* Allocate all memory structures for each channel */
+ {
+ for (ch = 0; ch < ascChannels; ch++) {
+ CAacDecoderDynamicData *aacDecoderDynamicData = &self->aacCommonData.workBufferCore1->pAacDecoderDynamicData[ch%2];
+
+ /* initialize pointer to CAacDecoderChannelInfo */
+ if (self->pAacDecoderChannelInfo[ch] == NULL) {
+ self->pAacDecoderChannelInfo[ch] = GetAacDecoderChannelInfo(ch);
+ /* This is temporary until the DynamicData is split into two or more regions!
+ The memory could be reused after completed core decoding. */
+ if (self->pAacDecoderChannelInfo[ch] == NULL) {
+ goto bail;
+ }
+ /* Hook shared work memory into channel data structure */
+ self->pAacDecoderChannelInfo[ch]->pDynData = aacDecoderDynamicData;
+ self->pAacDecoderChannelInfo[ch]->pComData = &self->aacCommonData;
+ }
+
+ /* Allocate persistent channel memory */
+ if (self->pAacDecoderStaticChannelInfo[ch] == NULL) {
+ self->pAacDecoderStaticChannelInfo[ch] = GetAacDecoderStaticChannelInfo(ch);
+ if (self->pAacDecoderStaticChannelInfo[ch] == NULL) {
+ goto bail;
+ }
+ self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer = GetOverlapBuffer(ch); /* This area size depends on the AOT */
+ if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) {
+ goto bail;
+ }
+ self->pAacDecoderChannelInfo[ch]->pSpectralCoefficient = (SPECTRAL_PTR) &self->aacCommonData.workBufferCore2[ch*1024];
+
+ }
+ CPns_InitPns(&self->pAacDecoderChannelInfo[ch]->data.aac.PnsData, &self->aacCommonData.pnsInterChannelData, &self->aacCommonData.pnsCurrentSeed, self->aacCommonData.pnsRandomSeed);
+ }
+
+
+ HcrInitRom(&self->aacCommonData.overlay.aac.erHcrInfo);
+ setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, ID_SCE);
+
+ /* Make allocated channel count persistent in decoder context. */
+ self->aacChannels = ascChannels;
+ }
+
+ /* Make amount of signalled channels persistent in decoder context. */
+ self->ascChannels = ascChannels;
+ }
+
+ /* Update structures */
+ if (ascChanged) {
+
+ /* Things to be done for each channel, which do not involved allocating memory. */
+ for (ch = 0; ch < ascChannels; ch++) {
+ switch (self->streamInfo.aot) {
+ case AOT_ER_AAC_ELD:
+ case AOT_ER_AAC_LD:
+ self->pAacDecoderChannelInfo[ch]->granuleLength = self->streamInfo.aacSamplesPerFrame;
+ break;
+ default:
+ self->pAacDecoderChannelInfo[ch]->granuleLength = self->streamInfo.aacSamplesPerFrame / 8;
+ break;
+ }
+ mdct_init( &self->pAacDecoderStaticChannelInfo[ch]->IMdct,
+ self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer,
+ OverlapBufferSize );
+
+
+ /* Reset DRC control data for this channel */
+ aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[ch]->drcData );
+
+ /* Reset concealment only if ASC changed. Otherwise it will be done with any config callback.
+ E.g. every time the LATM SMC is present. */
+ CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
+ &self->concealCommonData,
+ self->streamInfo.aacSamplesPerFrame );
+ }
+ }
+
+ /* Update externally visible copy of flags */
+ self->streamInfo.flags = self->flags;
+
+ return err;
+
+bail:
+ aacDecoder_Close( self );
+ return AAC_DEC_OUT_OF_MEMORY;
+}
+
+
+LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
+ HANDLE_AACDECODER self,
+ const UINT flags,
+ INT_PCM *pTimeData,
+ const INT timeDataSize,
+ const INT interleaved
+ )
+{
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+
+ CProgramConfig *pce;
+ HANDLE_FDK_BITSTREAM bs = transportDec_GetBitstream(self->hInput, 0);
+
+ MP4_ELEMENT_ID type = ID_NONE; /* Current element type */
+ INT aacChannels=0; /* Channel counter for channels found in the bitstream */
+
+ INT auStartAnchor = (INT)FDKgetValidBits(bs); /* AU start bit buffer position for AU byte alignment */
+
+ self->frameOK = 1;
+
+ /* Any supported base layer valid AU will require more than 16 bits. */
+ if ( (transportDec_GetAuBitsRemaining(self->hInput, 0) < 15) && (flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) == 0) {
+ self->frameOK = 0;
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ }
+
+
+ /* Reset Program Config structure */
+ pce = &self->pce;
+ CProgramConfig_Reset(pce);
+
+ CAacDecoder_AncDataReset(&self->ancData);
+
+ {
+ int ch;
+
+ if (self->streamInfo.channelConfig == 0) {
+ /* Init Channel/Element mapping table */
+ for (ch=0; ch<(6); ch++) {
+ self->chMapping[ch] = 255;
+ }
+ if (!CProgramConfig_IsValid(pce)) {
+ int el;
+ for (el=0; el<7; el++) {
+ self->elements[el] = ID_NONE;
+ }
+ }
+ }
+ }
+
+ /* Check sampling frequency */
+ switch ( self->streamInfo.aacSampleRate ) {
+ case 16000:
+ case 12000:
+ case 11025:
+ case 8000:
+ case 7350:
+ case 48000:
+ case 44100:
+ case 32000:
+ case 24000:
+ case 22050:
+ break;
+ default:
+ if ( ! (self->flags & (AC_USAC|AC_RSVD50)) ) {
+ return AAC_DEC_UNSUPPORTED_SAMPLINGRATE;
+ }
+ break;
+ }
+
+
+ if ( flags & AACDEC_CLRHIST )
+ {
+ int ch;
+ /* Clear history */
+ for (ch = 0; ch < self->aacChannels; ch++) {
+ /* Reset concealment */
+ CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
+ &self->concealCommonData,
+ self->streamInfo.aacSamplesPerFrame );
+ /* Clear concealment buffers to get rid of the complete history */
+ FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.spectralCoefficient, 1024 * sizeof(FIXP_CNCL));
+ FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.specScale, 8 * sizeof(SHORT));
+ /* Clear overlap-add buffers to avoid clicks. */
+ FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->IMdct.overlap.freq, OverlapBufferSize*sizeof(FIXP_DBL));
+ }
+ }
+
+
+
+#ifdef TP_PCE_ENABLE
+ int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */
+#endif
+
+
+ INT hdaacDecoded = 0;
+ MP4_ELEMENT_ID previous_element = ID_END; /* Last element ID (required for extension payload mapping */
+ UCHAR previous_element_index = 0; /* Canonical index of last element */
+ int element_count = 0; /* Element counter for elements found in the bitstream */
+ int el_cnt[ID_LAST] = { 0 }; /* element counter ( robustness ) */
+
+ while ( (type != ID_END) && (! (flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) && self->frameOK )
+ {
+ int el_channels;
+
+ if (! (self->flags & (AC_USAC|AC_RSVD50|AC_ELD|AC_SCALABLE|AC_ER)))
+ type = (MP4_ELEMENT_ID) FDKreadBits(bs,3);
+ else
+ type = self->elements[element_count];
+
+ setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, type);
+
+
+ if ((INT)FDKgetValidBits(bs) < 0)
+ self->frameOK = 0;
+
+ switch (type)
+ {
+ case ID_SCE:
+ case ID_CPE:
+ case ID_LFE:
+ /*
+ Consistency check
+ */
+
+ if (type == ID_CPE) {
+ el_channels = 2;
+ } else {
+ el_channels = 1;
+ }
+
+ if ( (el_cnt[type] >= (self->ascChannels>>(el_channels-1))) || (aacChannels > (self->ascChannels-el_channels)) ) {
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ self->frameOK = 0;
+ break;
+ }
+
+ if ( !(self->flags & (AC_USAC|AC_RSVD50)) ) {
+ int ch;
+ for (ch=0; ch < el_channels; ch+=1) {
+ CPns_ResetData(&self->pAacDecoderChannelInfo[aacChannels+ch]->data.aac.PnsData,
+ &self->pAacDecoderChannelInfo[aacChannels+ch]->pComData->pnsInterChannelData);
+ }
+ }
+
+ if(self->frameOK) {
+ ErrorStatus = CChannelElement_Read( bs,
+ &self->pAacDecoderChannelInfo[aacChannels],
+ &self->pAacDecoderStaticChannelInfo[aacChannels],
+ self->streamInfo.aot,
+ &self->samplingRateInfo,
+ self->flags,
+ self->streamInfo.aacSamplesPerFrame,
+ el_channels,
+ self->streamInfo.epConfig,
+ self->hInput
+ );
+ if (ErrorStatus) {
+ self->frameOK = 0;
+ }
+ }
+
+
+ if ( self->frameOK) {
+ /* Lookup the element and decode it only if it belongs to the current program */
+ if ( CProgramConfig_LookupElement(
+ pce,
+ self->streamInfo.channelConfig,
+ self->pAacDecoderChannelInfo[aacChannels]->ElementInstanceTag,
+ aacChannels,
+ self->chMapping,
+ self->channelType,
+ self->channelIndices,
+ &previous_element_index,
+ self->elements,
+ type) )
+ {
+ if ( !hdaacDecoded ) {
+ CChannelElement_Decode(
+ &self->pAacDecoderChannelInfo[aacChannels],
+ &self->pAacDecoderStaticChannelInfo[aacChannels],
+ &self->samplingRateInfo,
+ self->flags,
+ el_channels
+ );
+ }
+ aacChannels += 1;
+ if (type == ID_CPE) {
+ aacChannels += 1;
+ }
+ }
+ else {
+ self->frameOK = 0;
+ }
+ /* Create SBR element for SBR for upsampling. */
+ if ( (type == ID_LFE)
+ && ( (self->flags & AC_SBR_PRESENT)
+ || (self->sbrEnabled == 1) ) )
+ {
+ SBR_ERROR sbrError;
+
+ sbrError = sbrDecoder_InitElement(
+ self->hSbrDecoder,
+ self->streamInfo.aacSampleRate,
+ self->streamInfo.extSamplingRate,
+ self->streamInfo.aacSamplesPerFrame,
+ self->streamInfo.aot,
+ ID_LFE,
+ previous_element_index
+ );
+ if (sbrError != SBRDEC_OK) {
+ /* Do not try to apply SBR because initializing the element failed. */
+ self->sbrEnabled = 0;
+ }
+ }
+ }
+
+ el_cnt[type]++;
+ break;
+
+ case ID_CCE:
+ /*
+ Consistency check
+ */
+ if ( el_cnt[type] > self->ascChannels ) {
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ self->frameOK = 0;
+ break;
+ }
+
+ if (self->frameOK)
+ {
+ /* memory for spectral lines temporal on scratch */
+ C_ALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024);
+
+ /* create dummy channel for CCE parsing on stack */
+ CAacDecoderChannelInfo tmpAacDecoderChannelInfo, *pTmpAacDecoderChannelInfo;
+
+ FDKmemclear(mdctSpec, 1024*sizeof(FIXP_DBL));
+
+ tmpAacDecoderChannelInfo.pDynData = self->aacCommonData.workBufferCore1->pAacDecoderDynamicData;
+ tmpAacDecoderChannelInfo.pComData = &self->aacCommonData;
+ tmpAacDecoderChannelInfo.pSpectralCoefficient = (SPECTRAL_PTR)mdctSpec;
+ /* Assume AAC-LC */
+ tmpAacDecoderChannelInfo.granuleLength = self->streamInfo.aacSamplesPerFrame / 8;
+
+ /* Reset PNS data. */
+ CPns_ResetData(&tmpAacDecoderChannelInfo.data.aac.PnsData, &tmpAacDecoderChannelInfo.pComData->pnsInterChannelData);
+
+ pTmpAacDecoderChannelInfo = &tmpAacDecoderChannelInfo;
+ /* do CCE parsing */
+ ErrorStatus = CChannelElement_Read( bs,
+ &pTmpAacDecoderChannelInfo,
+ NULL,
+ self->streamInfo.aot,
+ &self->samplingRateInfo,
+ self->flags,
+ self->streamInfo.aacSamplesPerFrame,
+ 1,
+ self->streamInfo.epConfig,
+ self->hInput
+ );
+
+ C_ALLOC_SCRATCH_END(mdctSpec, FIXP_DBL, 1024);
+
+ if (ErrorStatus) {
+ self->frameOK = 0;
+ }
+
+ if (self->frameOK) {
+ /* Lookup the element and decode it only if it belongs to the current program */
+ if (CProgramConfig_LookupElement(
+ pce,
+ self->streamInfo.channelConfig,
+ pTmpAacDecoderChannelInfo->ElementInstanceTag,
+ 0,
+ self->chMapping,
+ self->channelType,
+ self->channelIndices,
+ &previous_element_index,
+ self->elements,
+ type) )
+ {
+ /* decoding of CCE not supported */
+ }
+ else {
+ self->frameOK = 0;
+ }
+ }
+ }
+ el_cnt[type]++;
+ break;
+
+ case ID_DSE:
+ {
+ UCHAR element_instance_tag;
+
+ CDataStreamElement_Read( bs,
+ &self->ancData,
+ self->hDrcInfo,
+ self->hInput,
+ &element_instance_tag,
+ auStartAnchor );
+
+ if (!CProgramConfig_LookupElement(
+ pce,
+ self->streamInfo.channelConfig,
+ element_instance_tag,
+ 0,
+ self->chMapping,
+ self->channelType,
+ self->channelIndices,
+ &previous_element_index,
+ self->elements,
+ type) )
+ {
+ /* most likely an error in bitstream occured */
+ //self->frameOK = 0;
+ }
+ }
+
+#if defined(PCM_POSTPROCESS_ENABLE) && defined(DVB_MIXDOWN_ENABLE) && defined(AACDEC_DVB_SUPPORT_ENABLE)
+ {
+ UCHAR *pDvbAncData = NULL;
+ AAC_DECODER_ERROR ancErr;
+ int ancIndex;
+ int dvbAncDataSize = 0;
+
+ /* Ask how many anc data elements are in buffer */
+ ancIndex = self->ancData.nrElements - 1;
+ /* Get the last one (if available) */
+ ancErr = CAacDecoder_AncDataGet( &self->ancData,
+ ancIndex,
+ &pDvbAncData,
+ &dvbAncDataSize );
+
+ if (ancErr == AAC_DEC_OK) {
+ pcmDmx_ReadDvbAncData (
+ self->hPcmUtils,
+ pDvbAncData,
+ dvbAncDataSize,
+ 0 /* not mpeg2 */ );
+ }
+ }
+#endif /* PCM_POSTPROCESS_ENABLE && DVB_MIXDOWN_ENABLE && AACDEC_DVB_SUPPORT_ENABLE */
+ break;
+
+#ifdef TP_PCE_ENABLE
+ case ID_PCE:
+
+ if ( CProgramConfigElement_Read( bs,
+ self->hInput,
+ pce,
+ auStartAnchor ) )
+ { /* Built element table */
+ int elIdx = CProgramConfig_GetElementTable(pce, self->elements);
+ /* Reset the remaining tabs */
+ for ( ; elIdx<7; elIdx++) {
+ self->elements[elIdx] = ID_NONE;
+ }
+ /* Make new number of channel persistant */
+ self->ascChannels = pce->NumChannels;
+ /* If PCE is not first element conceal this frame to avoid inconsistencies */
+ if ( element_count != 0 ) {
+ self->frameOK = 0;
+ }
+ }
+ pceRead = 1;
+ break;
+#endif /* TP_PCE_ENABLE */
+
+ case ID_FIL:
+ {
+ int bitCnt = FDKreadBits(bs,4); /* bs_count */
+
+ if (bitCnt == 15)
+ {
+ int esc_count = FDKreadBits(bs,8); /* bs_esc_count */
+ bitCnt = esc_count + 14;
+ }
+
+ /* Convert to bits */
+ bitCnt <<= 3;
+
+ while (bitCnt > 0) {
+ ErrorStatus = CAacDecoder_ExtPayloadParse(self, bs, &bitCnt, previous_element, previous_element_index, 1);
+ if (ErrorStatus != AAC_DEC_OK) {
+ self->frameOK = 0;
+ break;
+ }
+ }
+ }
+ break;
+
+ case ID_EXT:
+ {
+ INT bitCnt = 0;
+
+ /* get the remaining bits of this frame */
+ bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0);
+
+ if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD)) )
+ {
+ SBR_ERROR err;
+ int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE];
+
+ for (elIdx = 0; elIdx < numChElements; elIdx += 1)
+ {
+ err = sbrDecoder_Parse (
+ self->hSbrDecoder,
+ bs,
+ &bitCnt,
+ -1,
+ self->flags & AC_SBRCRC,
+ self->elements[elIdx],
+ elIdx,
+ self->flags & AC_INDEP );
+
+ if (err != SBRDEC_OK) {
+ break;
+ }
+ }
+ if (err == SBRDEC_OK) {
+ self->sbrEnabled = 1;
+ } else {
+ self->frameOK = 0;
+ }
+ }
+
+
+ if ( ! (self->flags & (AC_USAC|AC_RSVD50|AC_DRM)) )
+ {
+ while ( bitCnt > 7 ) {
+ ErrorStatus = CAacDecoder_ExtPayloadParse(self, bs, &bitCnt, previous_element, previous_element_index, 0);
+ if (ErrorStatus != AAC_DEC_OK) {
+ self->frameOK = 0;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case ID_END:
+ break;
+
+ default:
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ self->frameOK = 0;
+ break;
+ }
+
+ previous_element = type;
+ element_count++;
+
+ } /* while ( (type != ID_END) ... ) */
+
+ if ( !(flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) )
+ {
+ /* Byte alignment with respect to the first bit of the raw_data_block(). */
+ {
+ FDKbyteAlign(bs, auStartAnchor);
+ }
+
+ /* Check if all bits of the raw_data_block() have been read. */
+ if ( transportDec_GetAuBitsTotal(self->hInput, 0) > 0 ) {
+ INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0);
+ if ( unreadBits != 0 ) {
+
+ self->frameOK = 0;
+ /* Do not overwrite current error */
+ if (ErrorStatus == AAC_DEC_OK && self->frameOK == 0) {
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ }
+ /* Always put the bitbuffer at the right position after the current Access Unit. */
+ FDKpushBiDirectional(bs, unreadBits);
+ }
+ }
+
+ /* Check the last element. The terminator (ID_END) has to be the last one (even if ER syntax is used). */
+ if ( self->frameOK && type != ID_END ) {
+ /* Do not overwrite current error */
+ if (ErrorStatus == AAC_DEC_OK) {
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ }
+ self->frameOK = 0;
+ }
+ }
+
+ /* More AAC channels than specified by the ASC not allowed. */
+ if ( (aacChannels == 0 || aacChannels > self->aacChannels) && !(flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) ) {
+ {
+ /* Do not overwrite current error */
+ if (ErrorStatus == AAC_DEC_OK) {
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ self->frameOK = 0;
+ }
+ aacChannels = 0;
+ }
+ else if ( aacChannels > self->ascChannels ) {
+ /* Do not overwrite current error */
+ if (ErrorStatus == AAC_DEC_OK) {
+ ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
+ }
+ self->frameOK = 0;
+ aacChannels = 0;
+ }
+
+ if ( TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput) )
+ {
+ self->frameOK=0;
+ }
+
+ /* store or restore the number of channels */
+ if ( self->frameOK && !(flags &(AACDEC_CONCEAL|AACDEC_FLUSH)) ) {
+ self->concealChannels = aacChannels; /* store */
+ self->sbrEnabledPrev = self->sbrEnabled;
+ } else {
+ if (self->aacChannels > 0) {
+ aacChannels = self->concealChannels; /* restore */
+ self->sbrEnabled = self->sbrEnabledPrev;
+ }
+ }
+
+ /* Update number of output channels */
+ self->streamInfo.numChannels = aacChannels;
+
+#if defined(TP_PCE_ENABLE) && defined(PCM_POSTPROCESS_ENABLE) && defined(MPEG_PCE_MIXDOWN_ENABLE)
+ if (pceRead == 1 || CProgramConfig_IsValid(pce)) {
+ /* Set matrix mixdown infos if available from PCE. */
+ pcmDmx_SetMatrixMixdownFromPce ( self->hPcmUtils,
+ pce->MatrixMixdownIndexPresent,
+ pce->MatrixMixdownIndex,
+ pce->PseudoSurroundEnable );
+ }
+#endif
+
+ /* If there is no valid data to transfrom into time domain, return. */
+ if ( ! IS_OUTPUT_VALID(ErrorStatus) ) {
+ return ErrorStatus;
+ }
+
+ /*
+ Inverse transform
+ */
+ {
+ int stride, offset, c;
+
+ /* Extract DRC control data and map it to channels (without bitstream delay) */
+ aacDecoder_drcProlog (
+ self->hDrcInfo,
+ bs,
+ self->pAacDecoderStaticChannelInfo,
+ self->pce.ElementInstanceTag,
+ self->chMapping,
+ aacChannels
+ );
+
+ /* "c" iterates in canonical MPEG channel order */
+ for (c=0; c < aacChannels; c++)
+ {
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo;
+
+ /* Select correct pAacDecoderChannelInfo for current channel */
+ if (self->chMapping[c] >= aacChannels) {
+ pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[c];
+ } else {
+ pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[self->chMapping[c]];
+ }
+
+ /* Setup offset and stride for time buffer traversal. */
+ if (interleaved) {
+ stride = aacChannels;
+ offset = self->channelOutputMapping[aacChannels-1][c];
+ } else {
+ stride = 1;
+ offset = self->channelOutputMapping[aacChannels-1][c] * self->streamInfo.aacSamplesPerFrame;
+ }
+
+
+ /*
+ Conceal defective spectral data
+ */
+ CConcealment_Apply(&self->pAacDecoderStaticChannelInfo[c]->concealmentInfo,
+ pAacDecoderChannelInfo,
+ self->pAacDecoderStaticChannelInfo[c],
+ &self->samplingRateInfo,
+ self->streamInfo.aacSamplesPerFrame,
+ 0,
+ (self->frameOK && !(flags&AACDEC_CONCEAL)),
+ self->flags
+ );
+
+
+ if (flags & (AACDEC_INTR|AACDEC_CLRHIST)) {
+ /* Reset DRC control data for this channel */
+ aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[c]->drcData );
+ }
+ /* DRC processing */
+ aacDecoder_drcApply (
+ self->hDrcInfo,
+ self->hSbrDecoder,
+ pAacDecoderChannelInfo,
+ &self->pAacDecoderStaticChannelInfo[c]->drcData,
+ c,
+ self->streamInfo.aacSamplesPerFrame,
+ self->sbrEnabled
+ );
+
+ if ( flags&AACDEC_FLUSH ) {
+ FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*self->streamInfo.aacSamplesPerFrame);
+ }
+
+ switch (pAacDecoderChannelInfo->renderMode)
+ {
+ case AACDEC_RENDER_IMDCT:
+ CBlock_FrequencyToTime(
+ self->pAacDecoderStaticChannelInfo[c],
+ pAacDecoderChannelInfo,
+ pTimeData + offset,
+ self->streamInfo.aacSamplesPerFrame,
+ stride,
+ (self->frameOK && !(flags&AACDEC_CONCEAL)),
+ self->aacCommonData.workBufferCore1->mdctOutTemp
+ );
+ break;
+ case AACDEC_RENDER_ELDFB:
+ CBlock_FrequencyToTimeLowDelay(
+ self->pAacDecoderStaticChannelInfo[c],
+ pAacDecoderChannelInfo,
+ pTimeData + offset,
+ self->streamInfo.aacSamplesPerFrame,
+ stride
+ );
+ break;
+ default:
+ ErrorStatus = AAC_DEC_UNKNOWN;
+ break;
+ }
+ if ( flags&AACDEC_FLUSH ) {
+ FDKmemclear(self->pAacDecoderStaticChannelInfo[c]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL));
+ }
+ }
+
+
+ /* Extract DRC control data and map it to channels (with bitstream delay) */
+ aacDecoder_drcEpilog (
+ self->hDrcInfo,
+ bs,
+ self->pAacDecoderStaticChannelInfo,
+ self->pce.ElementInstanceTag,
+ self->chMapping,
+ aacChannels
+ );
+ }
+
+
+ /* Reorder channel type information tables. */
+ {
+ AUDIO_CHANNEL_TYPE types[(6)];
+ UCHAR idx[(6)];
+ int c;
+
+ FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
+ FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx));
+
+ FDKmemcpy(types, self->channelType, sizeof(types));
+ FDKmemcpy(idx, self->channelIndices, sizeof(idx));
+
+ for (c=0; c<aacChannels; c++) {
+ self->channelType[self->channelOutputMapping[aacChannels-1][c]] = types[c];
+ self->channelIndices[self->channelOutputMapping[aacChannels-1][c]] = idx[c];
+ }
+ }
+
+ self->blockNumber++;
+
+ return ErrorStatus;
+}
+
+/*!
+ \brief returns the streaminfo pointer
+
+ The function hands back a pointer to the streaminfo structure
+
+ \return pointer to the struct
+*/
+LINKSPEC_CPP CStreamInfo* CAacDecoder_GetStreamInfo ( HANDLE_AACDECODER self )
+{
+ if (!self) {
+ return NULL;
+ }
+ return &self->streamInfo;
+}
+
+
+
+
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
new file mode 100644
index 0000000..66d6361
--- /dev/null
+++ b/libAACdec/src/aacdecoder.h
@@ -0,0 +1,250 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef AACDECODER_H
+#define AACDECODER_H
+
+#include "common_fix.h"
+
+#include "FDK_bitstream.h"
+
+#include "channel.h"
+
+#include "tpdec_lib.h"
+#include "FDK_audio.h"
+
+#include "block.h"
+
+#include "genericStds.h"
+
+
+#include "sbrdecoder.h"
+
+
+#include "aacdec_drc.h"
+
+ #include "pcmutils_lib.h"
+
+
+/* Capabilities flags */
+#define CAPF_AAC_LC 0x00000001
+#define CAPF_AAC_LD 0x00000002
+#define CAPF_AAC_SCAL 0x00000004
+#define CAPF_AAC_ER 0x00000008
+#define CAPF_AAC_480 0x00000010
+#define CAPF_AAC_512 0x00000020
+#define CAPF_AAC_960 0x00000040
+#define CAPF_AAC_1024 0x00000080
+#define CAPF_AAC_HCR 0x00000100
+#define CAPF_AAC_VCB11 0x00000200
+#define CAPF_AAC_RVLC 0x00000400
+#define CAPF_AAC_MPEG4 0x00000800 /* PNS */
+#define CAPF_AAC_DRC 0x00001000
+#define CAPF_AAC_CONCEAL 0x00002000
+#define CAPF_AAC_DRM_BSFORMAT 0x00004000
+#define CAPF_AAC_BSAC 0x00008000
+
+typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER;
+
+
+enum
+{
+ L = 0,
+ R = 1
+};
+
+typedef struct {
+ unsigned char *buffer;
+ int bufferSize;
+ int offset[8];
+ int nrElements;
+} CAncData;
+
+typedef enum {
+ NOT_DEFINED = -1,
+ MODE_HQ = 0,
+ MODE_LP = 1
+} QMF_MODE;
+
+typedef struct {
+ int bsDelay;
+} SBR_PARAMS;
+
+
+/* AAC decoder (opaque toward userland) struct declaration */
+struct AAC_DECODER_INSTANCE {
+ INT aacChannels; /*!< Amount of AAC decoder channels allocated. */
+ INT ascChannels; /*!< Amount of AAC decoder channels signalled in ASC. */
+ INT blockNumber; /*!< frame counter */
+
+ INT nrOfLayers;
+
+ INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved). */
+
+ HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */
+
+ SamplingRateInfo samplingRateInfo; /*!< Sampling Rate information table */
+
+ UCHAR frameOK; /*!< Will be unset if a consistency check, e.g. CRC etc. fails */
+
+ UINT flags; /*!< Flags for internal decoder use. DO NOT USE self::streaminfo::flags ! */
+
+ MP4_ELEMENT_ID elements[7]; /*!< Table where the element Id's are listed */
+ UCHAR elTags[7]; /*!< Table where the elements id Tags are listed */
+ UCHAR chMapping[(6)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */
+
+ AUDIO_CHANNEL_TYPE channelType[(6)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */
+ UCHAR channelIndices[(6)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */
+ /* See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */
+
+
+ const UCHAR (*channelOutputMapping)[8]; /*!< Table for MPEG canonical order to output channel order mapping. */
+
+
+ CProgramConfig pce;
+ CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[(6)]; /*!< Temporal channel memory */
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(6)]; /*!< Persistent channel memory */
+
+ CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */
+
+ CConcealParams concealCommonData;
+ INT concealChannels;
+
+
+ HANDLE_SBRDECODER hSbrDecoder; /*!< SBR decoder handle. */
+ UCHAR sbrEnabled; /*!< flag to store if SBR has been detected */
+ UCHAR sbrEnabledPrev; /*!< flag to store if SBR has been detected from previous frame */
+ UCHAR psPossible; /*!< flag to store if PS is possible */
+ SBR_PARAMS sbrParams; /*!< struct to store all sbr parameters */
+
+ QMF_MODE qmfModeCurr; /*!< The current QMF mode */
+ QMF_MODE qmfModeUser; /*!< The QMF mode requested by the library user */
+
+ HANDLE_AAC_DRC hDrcInfo; /*!< handle to DRC data structure */
+
+
+ CAncData ancData; /*!< structure to handle ancillary data */
+
+ HANDLE_PCM_DOWNMIX hPcmUtils; /*!< privat data for the PCM utils. */
+
+};
+
+
+#define AAC_DEBUG_EXTHLP "\
+--- AAC-Core ---\n\
+ 0x00010000 Header data\n\
+ 0x00020000 CRC data\n\
+ 0x00040000 Channel info\n\
+ 0x00080000 Section data\n\
+ 0x00100000 Scalefactor data\n\
+ 0x00200000 Pulse data\n\
+ 0x00400000 Tns data\n\
+ 0x00800000 Quantized spectrum\n\
+ 0x01000000 Requantized spectrum\n\
+ 0x02000000 Time output\n\
+ 0x04000000 Fatal errors\n\
+ 0x08000000 Buffer fullness\n\
+ 0x10000000 Average bitrate\n\
+ 0x20000000 Synchronization\n\
+ 0x40000000 Concealment\n\
+ 0x7FFF0000 all AAC-Core-Info\n\
+"
+
+/**
+ * \brief Synchronise QMF mode for all modules using QMF data.
+ * \param self decoder handle
+ */
+void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self);
+
+/**
+ * \brief Signal a bit stream interruption to the decoder
+ * \param self decoder handle
+ */
+void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self);
+
+/*!
+ \brief Initialize ancillary buffer
+
+ \ancData Pointer to ancillary data structure
+ \buffer Pointer to (external) anc data buffer
+ \size Size of the buffer pointed on by buffer
+
+ \return Error code
+*/
+AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buffer, int size);
+
+/*!
+ \brief Get one ancillary data element
+
+ \ancData Pointer to ancillary data structure
+ \index Index of the anc data element to get
+ \ptr Pointer to a buffer receiving a pointer to the requested anc data element
+ \size Pointer to a buffer receiving the length of the requested anc data element
+
+ \return Error code
+*/
+AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, unsigned char **ptr, int *size);
+
+
+/* initialization of aac decoder */
+LINKSPEC_H HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat);
+
+/* Initialization of stream-info elements */
+LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self,
+ const CSAudioSpecificConfig *asc);
+
+/*!
+ \brief Decodes one aac frame
+
+ The function decodes one aac frame. The decoding of coupling channel
+ elements are not supported. The transport layer might signal, that the
+ data of the current frame is invalid, e.g. as a result of a packet
+ loss in streaming mode.
+ The bitstream position of transportDec_GetBitstream(self->hInput) must
+ be exactly the end of the access unit, including all byte alignment bits.
+ For this purpose, the variable auStartAnchor is used.
+
+ \return error status
+*/
+LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
+ HANDLE_AACDECODER self,
+ const UINT flags,
+ INT_PCM *pTimeData,
+ const INT timeDataSize,
+ const INT interleaved
+ );
+
+/* Destroy aac decoder */
+LINKSPEC_H void CAacDecoder_Close ( HANDLE_AACDECODER self );
+
+/* get streaminfo handle from decoder */
+LINKSPEC_H CStreamInfo* CAacDecoder_GetStreamInfo ( HANDLE_AACDECODER self );
+
+
+#endif /* #ifndef AACDECODER_H */
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
new file mode 100644
index 0000000..379c84c
--- /dev/null
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -0,0 +1,925 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS 1999-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Manuel Jander
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "aacdecoder_lib.h"
+
+#include "aac_ram.h"
+#include "aacdecoder.h"
+#include "tpdec_lib.h"
+#include "FDK_core.h" /* FDK_tools version info */
+
+
+ #include "sbrdecoder.h"
+
+
+
+
+#include "conceal.h"
+
+ #include "aacdec_drc.h"
+
+
+
+/* Decoder library info */
+#define AACDECODER_LIB_VL0 2
+#define AACDECODER_LIB_VL1 4
+#define AACDECODER_LIB_VL2 0
+#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
+#define AACDECODER_LIB_BUILD_DATE __DATE__
+#define AACDECODER_LIB_BUILD_TIME __TIME__
+
+static AAC_DECODER_ERROR
+setConcealMethod ( const HANDLE_AACDECODER self,
+ const INT method );
+
+
+LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_GetFreeBytes ( const HANDLE_AACDECODER self, UINT *pFreeBytes){
+
+ /* reset free bytes */
+ *pFreeBytes = 0;
+
+ /* check handle */
+ if(!self)
+ return AAC_DEC_INVALID_HANDLE;
+
+ /* return nr of free bytes */
+ HANDLE_FDK_BITSTREAM hBs = transportDec_GetBitstream(self->hInput, 0);
+ *pFreeBytes = FDKgetFreeBits(hBs) >> 3;
+
+ /* success */
+ return AAC_DEC_OK;
+}
+
+/**
+ * Config Decoder using a CSAudioSpecificConfig struct.
+ */
+static
+LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Config(HANDLE_AACDECODER self, const CSAudioSpecificConfig *pAscStruct)
+{
+ AAC_DECODER_ERROR err;
+
+ /* Initialize AAC core decoder, and update self->streaminfo */
+ err = CAacDecoder_Init(self, pAscStruct);
+
+ return err;
+}
+
+LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw (
+ HANDLE_AACDECODER self,
+ UCHAR *conf[],
+ const UINT length[] )
+{
+ AAC_DECODER_ERROR err = AAC_DEC_OK;
+ TRANSPORTDEC_ERROR errTp;
+ UINT layer, nrOfLayers = self->nrOfLayers;
+
+ for(layer = 0; layer < nrOfLayers; layer++){
+ if(length[layer] > 0){
+ errTp = transportDec_OutOfBandConfig(self->hInput, conf[layer], length[layer], layer);
+ if (errTp != TRANSPORTDEC_OK) {
+ switch (errTp) {
+ case TRANSPORTDEC_NEED_TO_RESTART:
+ err = AAC_DEC_NEED_TO_RESTART;
+ break;
+ case TRANSPORTDEC_UNSUPPORTED_FORMAT:
+ err = AAC_DEC_UNSUPPORTED_FORMAT;
+ break;
+ default:
+ err = AAC_DEC_UNKNOWN;
+ break;
+ }
+ /* if baselayer is OK we continue decoding */
+ if(layer >= 1){
+ self->nrOfLayers = layer;
+ }
+ break;
+ }
+ }
+ }
+
+ return err;
+}
+
+
+
+static INT aacDecoder_ConfigCallback(void *handle, const CSAudioSpecificConfig *pAscStruct)
+{
+ HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle;
+ AAC_DECODER_ERROR err = AAC_DEC_OK;
+ TRANSPORTDEC_ERROR errTp;
+
+ {
+ {
+ err = aacDecoder_Config(self, pAscStruct);
+ }
+ }
+ if (err == AAC_DEC_OK) {
+ if ( self->flags & (AC_USAC|AC_RSVD50|AC_LD|AC_ELD)
+ && CConcealment_GetDelay(&self->concealCommonData) > 0 )
+ {
+ /* Revert to error concealment method Noise Substitution.
+ Because interpolation is not implemented for USAC/RSVD50 or
+ the additional delay is unwanted for low delay codecs. */
+ setConcealMethod(self, 1);
+#ifdef DEBUG
+ FDKprintf(" Concealment method was reverted to 1 !\n");
+#endif
+ }
+ errTp = TRANSPORTDEC_OK;
+ } else {
+ if (IS_INIT_ERROR(err)) {
+ errTp = TRANSPORTDEC_UNSUPPORTED_FORMAT;
+ } /* Fatal errors */
+ else if (err == AAC_DEC_NEED_TO_RESTART) {
+ errTp = TRANSPORTDEC_NEED_TO_RESTART;
+ } else {
+ errTp = TRANSPORTDEC_UNKOWN_ERROR;
+ }
+ }
+
+ return errTp;
+}
+
+
+
+LINKSPEC_CPP AAC_DECODER_ERROR
+aacDecoder_AncDataInit ( HANDLE_AACDECODER self,
+ UCHAR *buffer,
+ int size )
+{
+ CAncData *ancData = &self->ancData;
+
+ return CAacDecoder_AncDataInit(ancData, buffer, size);
+}
+
+
+LINKSPEC_CPP AAC_DECODER_ERROR
+aacDecoder_AncDataGet ( HANDLE_AACDECODER self,
+ int index,
+ UCHAR **ptr,
+ int *size )
+{
+ CAncData *ancData = &self->ancData;
+
+ return CAacDecoder_AncDataGet(ancData, index, ptr, size);
+}
+
+
+static AAC_DECODER_ERROR
+setConcealMethod ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */
+ const INT method )
+{
+ AAC_DECODER_ERROR errorStatus = AAC_DEC_OK;
+ CConcealParams *pConcealData = NULL;
+ HANDLE_SBRDECODER hSbrDec = NULL;
+ HANDLE_AAC_DRC hDrcInfo = NULL;
+ HANDLE_PCM_DOWNMIX hPcmDmx = NULL;
+ CConcealmentMethod backupMethod;
+ int backupDelay = 0;
+ int bsDelay = 0;
+
+ /* check decoder handle */
+ if (self != NULL) {
+ pConcealData = &self->concealCommonData;
+ hSbrDec = self->hSbrDecoder;
+ hDrcInfo = self->hDrcInfo;
+ hPcmDmx = self->hPcmUtils;
+ }
+
+
+ /* Get current method/delay */
+ backupMethod = CConcealment_GetMethod(pConcealData);
+ backupDelay = CConcealment_GetDelay(pConcealData);
+
+ /* Be sure to set AAC and SBR concealment method simultaneously! */
+ errorStatus =
+ CConcealment_SetParams(
+ pConcealData,
+ (int)method, // concealMethod
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeOutSlope
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeInSlope
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealMuteRelease
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED // concealComfNoiseLevel
+ );
+ if ( (errorStatus != AAC_DEC_OK)
+ && (errorStatus != AAC_DEC_INVALID_HANDLE) ) {
+ goto bail;
+ }
+
+ /* Get new delay */
+ bsDelay = CConcealment_GetDelay(pConcealData);
+
+ {
+ SBR_ERROR sbrErr = SBRDEC_OK;
+
+ /* set SBR bitstream delay */
+ sbrErr = sbrDecoder_SetParam (
+ hSbrDec,
+ SBR_SYSTEM_BITSTREAM_DELAY,
+ bsDelay
+ );
+
+ switch (sbrErr) {
+ case SBRDEC_OK:
+ case SBRDEC_NOT_INITIALIZED:
+ if (self != NULL) {
+ /* save the param value and set later
+ (when SBR has been initialized) */
+ self->sbrParams.bsDelay = bsDelay;
+ }
+ break;
+ default:
+ errorStatus = AAC_DEC_SET_PARAM_FAIL;
+ goto bail;
+ }
+ }
+
+ errorStatus =
+ aacDecoder_drcSetParam (
+ hDrcInfo,
+ DRC_BS_DELAY,
+ bsDelay
+ );
+ if ( (errorStatus != AAC_DEC_OK)
+ && (errorStatus != AAC_DEC_INVALID_HANDLE) ) {
+ goto bail;
+ }
+
+ if (errorStatus == AAC_DEC_OK) {
+ PCMDMX_ERROR err =
+ pcmDmx_SetParam (
+ hPcmDmx,
+ DMX_BS_DATA_DELAY,
+ bsDelay
+ );
+ switch (err) {
+ case PCMDMX_INVALID_HANDLE:
+ errorStatus = AAC_DEC_INVALID_HANDLE;
+ case PCMDMX_OK:
+ break;
+ default:
+ errorStatus = AAC_DEC_SET_PARAM_FAIL;
+ goto bail;
+ }
+ }
+
+
+bail:
+ if ( (errorStatus != AAC_DEC_OK)
+ && (errorStatus != AAC_DEC_INVALID_HANDLE) )
+ {
+ /* Revert to the initial state */
+ CConcealment_SetParams (
+ pConcealData,
+ (int)backupMethod,
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED,
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED,
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED,
+ AACDEC_CONCEAL_PARAM_NOT_SPECIFIED
+ );
+ /* Revert SBR bitstream delay */
+ sbrDecoder_SetParam (
+ hSbrDec,
+ SBR_SYSTEM_BITSTREAM_DELAY,
+ backupDelay
+ );
+ /* Revert DRC bitstream delay */
+ aacDecoder_drcSetParam (
+ hDrcInfo,
+ DRC_BS_DELAY,
+ backupDelay
+ );
+ /* Revert PCM mixdown bitstream delay */
+ pcmDmx_SetParam (
+ hPcmDmx,
+ DMX_BS_DATA_DELAY,
+ backupDelay
+ );
+ }
+
+ return errorStatus;
+}
+
+
+LINKSPEC_CPP AAC_DECODER_ERROR
+aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */
+ const AACDEC_PARAM param, /*!< Parameter to set */
+ const INT value) /*!< Parameter valued */
+{
+ AAC_DECODER_ERROR errorStatus = AAC_DEC_OK;
+ CConcealParams *pConcealData = NULL;
+ HANDLE_AAC_DRC hDrcInfo = NULL;
+
+ /* check decoder handle */
+ if (self != NULL) {
+ pConcealData = &self->concealCommonData;
+ hDrcInfo = self->hDrcInfo;
+ }
+
+ /* configure the subsystems */
+ switch (param)
+ {
+ case AAC_PCM_OUTPUT_INTERLEAVED:
+ if (value < 0 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->outputInterleaved = value;
+ break;
+
+ case AAC_PCM_OUTPUT_CHANNELS:
+ {
+ PCMDMX_ERROR err;
+
+ err = pcmDmx_SetParam (
+ self->hPcmUtils,
+ NUMBER_OF_OUTPUT_CHANNELS,
+ value );
+
+ switch (err) {
+ case PCMDMX_OK:
+ break;
+ case PCMDMX_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+ break;
+
+ case AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE:
+ {
+ PCMDMX_ERROR err;
+
+ err = pcmDmx_SetParam (
+ self->hPcmUtils,
+ DUAL_CHANNEL_DOWNMIX_MODE,
+ value );
+
+ switch (err) {
+ case PCMDMX_OK:
+ break;
+ case PCMDMX_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+ break;
+
+ case AAC_PCM_OUTPUT_CHANNEL_MAPPING:
+ switch (value) {
+ case 0:
+ self->channelOutputMapping = channelMappingTablePassthrough;
+ break;
+ case 1:
+ self->channelOutputMapping = channelMappingTableWAV;
+ break;
+ default:
+ errorStatus = AAC_DEC_SET_PARAM_FAIL;
+ break;
+ }
+ break;
+
+
+ case AAC_QMF_LOWPOWER:
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+
+ /**
+ * Set QMF mode (might be overriden)
+ * 0:HQ (complex)
+ * 1:LP (partially complex)
+ */
+ self->qmfModeUser = (QMF_MODE)value;
+ break;
+
+
+ case AAC_DRC_ATTENUATION_FACTOR:
+ /* DRC compression factor (where 0 is no and 127 is max compression) */
+ errorStatus =
+ aacDecoder_drcSetParam (
+ hDrcInfo,
+ DRC_CUT_SCALE,
+ value
+ );
+ break;
+
+ case AAC_DRC_BOOST_FACTOR:
+ /* DRC boost factor (where 0 is no and 127 is max boost) */
+ errorStatus =
+ aacDecoder_drcSetParam (
+ hDrcInfo,
+ DRC_BOOST_SCALE,
+ value
+ );
+ break;
+
+ case AAC_DRC_REFERENCE_LEVEL:
+ /* DRC reference level quantized in 0.25dB steps using values [0..127] it is '-' for analog scaling */
+ errorStatus =
+ aacDecoder_drcSetParam (
+ hDrcInfo,
+ TARGET_REF_LEVEL,
+ value
+ );
+ break;
+
+ case AAC_DRC_HEAVY_COMPRESSION:
+ /* Don't need to overwrite cut/boost values */
+ errorStatus =
+ aacDecoder_drcSetParam (
+ hDrcInfo,
+ APPLY_HEAVY_COMPRESSION,
+ value
+ );
+ break;
+
+
+ case AAC_TPDEC_CLEAR_BUFFER:
+ transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1);
+ self->streamInfo.numLostAccessUnits = 0;
+ self->streamInfo.numBadBytes = 0;
+ self->streamInfo.numTotalBytes = 0;
+ /* aacDecoder_SignalInterruption(self); */
+ break;
+
+ case AAC_CONCEAL_METHOD:
+ /* Changing the concealment method can introduce additional bitstream delay. And
+ that in turn affects sub libraries and modules which makes the whole thing quite
+ complex. So the complete changing routine is packed into a helper function which
+ keeps all modules and libs in a consistent state even in the case an error occures. */
+ errorStatus = setConcealMethod ( self, value );
+ break;
+
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ } /* switch(param) */
+
+ return (errorStatus);
+}
+
+
+LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, UINT nrOfLayers)
+{
+ AAC_DECODER_INSTANCE *aacDec = NULL;
+ HANDLE_TRANSPORTDEC pIn;
+ int err = 0;
+
+ /* Allocate transport layer struct. */
+ pIn = transportDec_Open(transportFmt, TP_FLAG_MPEG4);
+ if (pIn == NULL) {
+ return NULL;
+ }
+
+ /* Allocate AAC decoder core struct. */
+ aacDec = CAacDecoder_Open(transportFmt);
+
+ if (aacDec == NULL) {
+ transportDec_Close(&pIn);
+ goto bail;
+ }
+ aacDec->hInput = pIn;
+
+ aacDec->nrOfLayers = nrOfLayers;
+
+ aacDec->channelOutputMapping = channelMappingTableWAV;
+
+ /* Register Config Update callback. */
+ transportDec_RegisterAscCallback(pIn, aacDecoder_ConfigCallback, (void*)aacDec);
+
+ /* open SBR decoder */
+ if ( SBRDEC_OK != sbrDecoder_Open ( &aacDec->hSbrDecoder )) {
+ err = -1;
+ goto bail;
+ }
+ aacDec->qmfModeUser = NOT_DEFINED;
+ transportDec_RegisterSbrCallback(aacDec->hInput, (cbSbr_t)sbrDecoder_Header, (void*)aacDec->hSbrDecoder);
+
+
+ pcmDmx_Open( &aacDec->hPcmUtils );
+ if (aacDec->hPcmUtils == NULL) {
+ err = -1;
+ goto bail;
+ }
+
+
+
+ /* Assure that all modules have same delay */
+ if ( setConcealMethod(aacDec, CConcealment_GetMethod(&aacDec->concealCommonData)) ) {
+ err = -1;
+ goto bail;
+ }
+
+bail:
+ if (err == -1) {
+ aacDecoder_Close(aacDec);
+ aacDec = NULL;
+ }
+ return aacDec;
+}
+
+LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Fill(
+ HANDLE_AACDECODER self,
+ UCHAR *pBuffer[],
+ const UINT bufferSize[],
+ UINT *pBytesValid
+ )
+{
+ TRANSPORTDEC_ERROR tpErr;
+ /* loop counter for layers; if not TT_MP4_RAWPACKETS used as index for only
+ available layer */
+ INT layer = 0;
+ INT nrOfLayers = self->nrOfLayers;
+
+ {
+ for (layer = 0; layer < nrOfLayers; layer++){
+ {
+ tpErr = transportDec_FillData( self->hInput, pBuffer[layer], bufferSize[layer], &pBytesValid[layer], layer );
+ if (tpErr != TRANSPORTDEC_OK) {
+ return AAC_DEC_UNKNOWN; /* Must be an internal error */
+ }
+ }
+ }
+ }
+
+ return AAC_DEC_OK;
+}
+
+
+static void aacDecoder_SignalInterruption(HANDLE_AACDECODER self)
+{
+ CAacDecoder_SignalInterruption(self);
+
+ if ( self->hSbrDecoder != NULL ) {
+ sbrDecoder_SetParam(self->hSbrDecoder, SBR_BS_INTERRUPTION, 0);
+ }
+}
+
+static void aacDecoder_UpdateBitStreamCounters(CStreamInfo *pSi, HANDLE_FDK_BITSTREAM hBs, int nBits, AAC_DECODER_ERROR ErrorStatus)
+{
+ /* calculate bit difference (amount of bits moved forward) */
+ nBits = nBits - FDKgetValidBits(hBs);
+
+ /* Note: The amount of bits consumed might become negative when parsing a
+ bit stream with several sub frames, and we find out at the last sub frame
+ that the total frame length does not match the sum of sub frame length.
+ If this happens, the transport decoder might want to rewind to the supposed
+ ending of the transport frame, and this position might be before the last
+ access unit beginning. */
+
+ /* Calc bitrate. */
+ if (pSi->frameSize > 0) {
+ pSi->bitRate = (nBits * pSi->sampleRate)/pSi->frameSize;
+ }
+
+ /* bit/byte counters */
+ {
+ int nBytes;
+
+ nBytes = nBits>>3;
+ pSi->numTotalBytes += nBytes;
+ if (IS_OUTPUT_VALID(ErrorStatus)) {
+ pSi->numTotalAccessUnits++;
+ }
+ if (IS_DECODE_ERROR(ErrorStatus)) {
+ pSi->numBadBytes += nBytes;
+ pSi->numBadAccessUnits++;
+ }
+ }
+}
+
+static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self)
+{
+ INT n;
+
+ transportDec_GetMissingAccessUnitCount( &n, self->hInput);
+
+ return n;
+}
+
+LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
+ HANDLE_AACDECODER self,
+ INT_PCM *pTimeData,
+ const INT timeDataSize,
+ const UINT flags)
+{
+ AAC_DECODER_ERROR ErrorStatus;
+ INT layer;
+ INT nBits;
+ INT interleaved = self->outputInterleaved;
+ HANDLE_FDK_BITSTREAM hBs;
+ int fTpInterruption = 0; /* Transport originated interruption detection. */
+ int fTpConceal = 0; /* Transport originated concealment. */
+
+
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+
+ if (flags & AACDEC_INTR) {
+ self->streamInfo.numLostAccessUnits = 0;
+ }
+
+ hBs = transportDec_GetBitstream(self->hInput, 0);
+
+ /* Get current bits position for bitrate calculation. */
+ nBits = FDKgetValidBits(hBs);
+ if (! (flags & (AACDEC_CONCEAL | AACDEC_FLUSH) ) )
+ {
+ TRANSPORTDEC_ERROR err;
+
+ for(layer = 0; layer < self->nrOfLayers; layer++)
+ {
+ err = transportDec_ReadAccessUnit(self->hInput, layer);
+ if (err != TRANSPORTDEC_OK) {
+ switch (err) {
+ case TRANSPORTDEC_NOT_ENOUGH_BITS:
+ ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS;
+ goto bail;
+ case TRANSPORTDEC_SYNC_ERROR:
+ self->streamInfo.numLostAccessUnits = aacDecoder_EstimateNumberOfLostFrames(self);
+ fTpInterruption = 1;
+ break;
+ case TRANSPORTDEC_NEED_TO_RESTART:
+ ErrorStatus = AAC_DEC_NEED_TO_RESTART;
+ goto bail;
+ case TRANSPORTDEC_CRC_ERROR:
+ fTpConceal = 1;
+ break;
+ default:
+ ErrorStatus = AAC_DEC_UNKNOWN;
+ goto bail;
+ }
+ }
+ }
+ } else {
+ if (self->streamInfo.numLostAccessUnits > 0) {
+ self->streamInfo.numLostAccessUnits--;
+ }
+ }
+
+ /* Signal bit stream interruption to other modules if required. */
+ if ( fTpInterruption || (flags & (AACDEC_INTR|AACDEC_CLRHIST)) )
+ {
+ aacDecoder_SignalInterruption(self);
+ if ( ! (flags & AACDEC_INTR) ) {
+ ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR;
+ goto bail;
+ }
+ }
+
+ /* Empty bit buffer in case of flush request. */
+ if (flags & AACDEC_FLUSH)
+ {
+ transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1);
+ self->streamInfo.numLostAccessUnits = 0;
+ self->streamInfo.numBadBytes = 0;
+ self->streamInfo.numTotalBytes = 0;
+ }
+
+
+ ErrorStatus = CAacDecoder_DecodeFrame(self,
+ flags | (fTpConceal ? AACDEC_CONCEAL : 0),
+ pTimeData,
+ timeDataSize,
+ interleaved);
+
+ if (!(flags & (AACDEC_CONCEAL|AACDEC_FLUSH))) {
+ TRANSPORTDEC_ERROR tpErr;
+ tpErr = transportDec_EndAccessUnit(self->hInput);
+ if (tpErr != TRANSPORTDEC_OK) {
+ self->frameOK = 0;
+ }
+ }
+
+ /* If the current pTimeData does not contain a valid signal, there nothing else we can do, so bail. */
+ if ( ! IS_OUTPUT_VALID(ErrorStatus) ) {
+ goto bail;
+ }
+
+ {
+ /* Export data into streaminfo structure */
+ self->streamInfo.sampleRate = self->streamInfo.aacSampleRate;
+ self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame;
+ self->streamInfo.numChannels = self->aacChannels;
+ }
+
+
+
+ CAacDecoder_SyncQmfMode(self);
+
+/* sbr decoder */
+
+ if (ErrorStatus || (flags & AACDEC_CONCEAL) || self->pAacDecoderStaticChannelInfo[0]->concealmentInfo.concealState > ConcealState_FadeIn)
+ {
+ self->frameOK = 0; /* if an error has occured do concealment in the SBR decoder too */
+ }
+
+ if (self->sbrEnabled)
+ {
+ SBR_ERROR sbrError = SBRDEC_OK;
+
+ /* set params */
+ sbrDecoder_SetParam ( self->hSbrDecoder,
+ SBR_SYSTEM_BITSTREAM_DELAY,
+ self->sbrParams.bsDelay);
+
+ if ( self->streamInfo.aot == AOT_ER_AAC_ELD ) {
+ /* Configure QMF */
+ sbrDecoder_SetParam ( self->hSbrDecoder,
+ SBR_LD_QMF_TIME_ALIGN,
+ (self->flags & AC_LD_MPS) ? 1 : 0 );
+ }
+
+
+
+
+ /* apply SBR processing */
+ sbrError = sbrDecoder_Apply ( self->hSbrDecoder,
+ pTimeData,
+ &self->streamInfo.numChannels,
+ &self->streamInfo.sampleRate,
+ self->channelOutputMapping[self->aacChannels-1],
+ interleaved,
+ self->frameOK,
+ &self->psPossible);
+
+
+ if (sbrError == SBRDEC_OK) {
+
+ /* Update data in streaminfo structure. Assume that the SBR upsampling factor is either 1 or 2 */
+ self->flags |= AC_SBR_PRESENT;
+ if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) {
+ if (self->streamInfo.frameSize == 768) {
+ self->streamInfo.frameSize = (self->streamInfo.aacSamplesPerFrame * 8) / 3;
+ } else {
+ self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame << 1;
+ }
+ }
+
+ if (self->psPossible) {
+ self->flags |= AC_PS_PRESENT;
+ self->channelType[0] = ACT_FRONT;
+ self->channelType[1] = ACT_FRONT;
+ self->channelIndices[0] = 0;
+ self->channelIndices[1] = 1;
+ } else {
+ self->flags &= ~AC_PS_PRESENT;
+ }
+ }
+ }
+
+
+ if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) {
+ /* delete data from the past (e.g. mixdown coeficients) */
+ pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA );
+ }
+ /* do PCM post processing */
+ pcmDmx_ApplyFrame (
+ self->hPcmUtils,
+ pTimeData,
+ self->streamInfo.frameSize,
+ &self->streamInfo.numChannels,
+ interleaved,
+ self->channelType,
+ self->channelIndices,
+ self->channelOutputMapping
+ );
+
+
+
+ /* Signal interruption to take effect in next frame. */
+ if ( flags & AACDEC_FLUSH ) {
+ aacDecoder_SignalInterruption(self);
+ }
+
+ /* Update externally visible copy of flags */
+ self->streamInfo.flags = self->flags;
+
+bail:
+
+ /* Update Statistics */
+ aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, ErrorStatus);
+
+ return ErrorStatus;
+}
+
+LINKSPEC_CPP void aacDecoder_Close ( HANDLE_AACDECODER self )
+{
+ if (self == NULL)
+ return;
+
+
+
+ if (self->hPcmUtils != NULL) {
+ pcmDmx_Close( &self->hPcmUtils );
+ }
+
+
+
+ if (self->hSbrDecoder != NULL) {
+ sbrDecoder_Close(&self->hSbrDecoder);
+ }
+
+ if (self->hInput != NULL) {
+ transportDec_Close(&self->hInput);
+ }
+
+ CAacDecoder_Close(self);
+}
+
+
+LINKSPEC_CPP CStreamInfo* aacDecoder_GetStreamInfo ( HANDLE_AACDECODER self )
+{
+ return CAacDecoder_GetStreamInfo(self);
+}
+
+LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info )
+{
+ int i;
+
+ if (info == NULL) {
+ return -1;
+ }
+
+ sbrDecoder_GetLibInfo( info );
+ transportDec_GetLibInfo( info );
+ FDK_toolsGetLibInfo( info );
+ pcmDmx_GetLibInfo( info );
+
+ /* search for next free tab */
+ for (i = 0; i < FDK_MODULE_LAST; i++) {
+ if (info[i].module_id == FDK_NONE) break;
+ }
+ if (i == FDK_MODULE_LAST) {
+ return -1;
+ }
+ info += i;
+
+ info->module_id = FDK_AACDEC;
+ /* build own library info */
+ info->version = LIB_VERSION(AACDECODER_LIB_VL0, AACDECODER_LIB_VL1, AACDECODER_LIB_VL2);
+ LIB_VERSION_STRING(info);
+ info->build_date = AACDECODER_LIB_BUILD_DATE;
+ info->build_time = AACDECODER_LIB_BUILD_TIME;
+ info->title = AACDECODER_LIB_TITLE;
+
+ /* Set flags */
+ info->flags = 0
+ | CAPF_AAC_LC
+ | CAPF_AAC_VCB11
+ | CAPF_AAC_HCR
+ | CAPF_AAC_RVLC
+ | CAPF_ER_AAC_LD
+ | CAPF_ER_AAC_ELD
+ | CAPF_AAC_CONCEALMENT
+ | CAPF_AAC_DRC
+
+ | CAPF_AAC_MPEG4
+
+
+ | CAPF_AAC_1024
+ | CAPF_AAC_960
+
+ | CAPF_AAC_512
+
+ | CAPF_AAC_480
+
+ ;
+ /* End of flags */
+
+ return 0;
+}
+
+
+
+
diff --git a/libAACdec/src/arm/block_arm.cpp b/libAACdec/src/arm/block_arm.cpp
new file mode 100644
index 0000000..d9d0cf8
--- /dev/null
+++ b/libAACdec/src/arm/block_arm.cpp
@@ -0,0 +1,77 @@
+/******************************** Fraunhofer IIS ***************************
+
+ (C) Copyright Fraunhofer IIS (2010)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Arthur Tritthart
+ Description: (ARM optimised) Scaling of spectral data
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+
+#define FUNCTION_CBlock_ScaleSpectralData_func1
+
+/* Note: This loop is only separated for ARM in order to save cycles
+ by loop unrolling. The ARM core provides by default a 5-cycle
+ loop overhead per sample, that goes down to 1-cycle per sample
+ with an optimal 4x-loop construct (do - 4x - while).
+*/
+
+FDK_INLINE static void CBlock_ScaleSpectralData_func1(
+ FIXP_DBL *pSpectrum,
+ int max_band,
+ const SHORT * RESTRICT BandOffsets,
+ int SpecScale_window,
+ const SHORT * RESTRICT pSfbScale,
+ int window)
+{
+ int band_offset = 0;
+ for (int band=0; band < max_band; band++)
+ {
+ int runs = band_offset;
+ band_offset = BandOffsets[band+1];
+ runs = band_offset - runs; /* is always a multiple of 4 */
+ int scale = SpecScale_window-pSfbScale[window*16+band];
+ if (scale)
+ {
+ do
+ {
+ FIXP_DBL tmp0, tmp1, tmp2, tmp3;
+ tmp0 = pSpectrum[0];
+ tmp1 = pSpectrum[1];
+ tmp2 = pSpectrum[2];
+ tmp3 = pSpectrum[3];
+ tmp0 >>= scale;
+ tmp1 >>= scale;
+ tmp2 >>= scale;
+ tmp3 >>= scale;
+ *pSpectrum++ = tmp0;
+ *pSpectrum++ = tmp1;
+ *pSpectrum++ = tmp2;
+ *pSpectrum++ = tmp3;
+ } while ((runs = runs-4) != 0);
+ }
+ else
+ {
+ pSpectrum+= runs;
+ }
+ }
+}
diff --git a/libAACdec/src/block.cpp b/libAACdec/src/block.cpp
new file mode 100644
index 0000000..d17e9c4
--- /dev/null
+++ b/libAACdec/src/block.cpp
@@ -0,0 +1,703 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: long/short-block decoding
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "block.h"
+
+#include "aac_rom.h"
+#include "FDK_bitstream.h"
+#include "FDK_tools_rom.h"
+
+
+
+
+#include "aacdec_hcr.h"
+#include "rvlc.h"
+
+
+#if defined(__arm__)
+#include "arm/block_arm.cpp"
+#endif
+
+/*!
+ \brief Read escape sequence of codeword
+
+ The function reads the escape sequence from the bitstream,
+ if the absolute value of the quantized coefficient has the
+ value 16.
+
+ \return quantized coefficient
+*/
+LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */
+ const LONG q) /*!< quantized coefficient */
+{
+ LONG i, off, neg ;
+
+ if (q < 0)
+ {
+ if (q != -16) return q;
+ neg = 1;
+ }
+ else
+ {
+ if (q != +16) return q;
+ neg = 0;
+ }
+
+ for (i=4; ; i++)
+ {
+ if (FDKreadBits(bs,1) == 0)
+ break;
+ }
+
+ if (i > 16)
+ {
+ if (i - 16 > CACHE_BITS) { /* cannot read more than "CACHE_BITS" bits at once in the function FDKreadBits() */
+ return (MAX_QUANTIZED_VALUE + 1); /* returning invalid value that will be captured later */
+ }
+
+ off = FDKreadBits(bs,i-16) << 16;
+ off |= FDKreadBits(bs,16);
+ }
+ else
+ {
+ off = FDKreadBits(bs,i);
+ }
+
+ i = off + (1 << i);
+
+ if (neg) i = -i;
+
+ return i;
+}
+
+AAC_DECODER_ERROR CBlock_ReadScaleFactorData(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs,
+ UINT flags
+ )
+{
+ int temp;
+ int band;
+ int group;
+ int position = 0; /* accu for intensity delta coding */
+ int factor = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain; /* accu for scale factor delta coding */
+ UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ const CodeBookDescription *hcb =&AACcodeBookDescriptionTable[BOOKSCL];
+
+ int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ for (group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
+ {
+ for (band=0; band < ScaleFactorBandsTransmitted; band++)
+ {
+ switch (pCodeBook[group*16+band]) {
+
+ case ZERO_HCB: /* zero book */
+ pScaleFactor[group*16+band] = 0;
+ break;
+
+ default: /* decode scale factor */
+ {
+ temp = CBlock_DecodeHuffmanWord(bs,hcb);
+ factor += temp - 60; /* MIDFAC 1.5 dB */
+ }
+ pScaleFactor[group*16+band] = factor - 100;
+ break;
+
+ case INTENSITY_HCB: /* intensity steering */
+ case INTENSITY_HCB2:
+ temp = CBlock_DecodeHuffmanWord(bs,hcb);
+ position += temp - 60;
+ pScaleFactor[group*16+band] = position - 100;
+ break;
+
+ case NOISE_HCB: /* PNS */
+ if (flags & (AC_MPS_RES|AC_USAC|AC_RSVD50)) {
+ return AAC_DEC_PARSE_ERROR;
+ }
+ CPns_Read( &pAacDecoderChannelInfo->data.aac.PnsData, bs, hcb, pAacDecoderChannelInfo->pDynData->aScaleFactor, pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain, band, group);
+ break;
+ }
+ }
+ }
+
+ return AAC_DEC_OK;
+}
+
+void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo)
+{
+ int band;
+ int window;
+ const SHORT * RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale;
+ SHORT * RESTRICT pSpecScale = pAacDecoderChannelInfo->specScale;
+ int groupwin,group;
+ const SHORT * RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+ SPECTRAL_PTR RESTRICT pSpectralCoefficient = pAacDecoderChannelInfo->pSpectralCoefficient;
+
+
+ FDKmemclear(pSpecScale, 8*sizeof(SHORT));
+
+ int max_band = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ for (window=0, group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
+ {
+ for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++, window++)
+ {
+ int SpecScale_window = pSpecScale[window];
+ FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength);
+
+ /* find scaling for current window */
+ for (band=0; band < max_band; band++)
+ {
+ SpecScale_window = fMax(SpecScale_window, (int)pSfbScale[window*16+band]);
+ }
+
+ if (pAacDecoderChannelInfo->pDynData->TnsData.Active) {
+ SpecScale_window += TNS_SCALE;
+ }
+
+ /* store scaling of current window */
+ pSpecScale[window] = SpecScale_window;
+
+#ifdef FUNCTION_CBlock_ScaleSpectralData_func1
+
+ CBlock_ScaleSpectralData_func1(pSpectrum, max_band, BandOffsets, SpecScale_window, pSfbScale, window);
+
+#else /* FUNCTION_CBlock_ScaleSpectralData_func1 */
+ for (band=0; band < max_band; band++)
+ {
+ int scale = SpecScale_window - pSfbScale[window*16+band];
+ if (scale)
+ {
+ /* following relation can be used for optimizations: (BandOffsets[i]%4) == 0 for all i */
+ int max_index = BandOffsets[band+1];
+ for (int index = BandOffsets[band]; index < max_index; index++)
+ {
+ pSpectrum[index] >>= scale;
+ }
+ }
+ }
+#endif /* FUNCTION_CBlock_ScaleSpectralData_func1 */
+ }
+ }
+
+}
+
+AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags)
+{
+ int top, band;
+ int sect_len, sect_len_incr;
+ int group;
+ UCHAR sect_cb;
+ UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ /* HCR input (long) */
+ SHORT *pNumLinesInSec = pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr;
+ int numLinesInSecIdx = 0;
+ UCHAR *pHcrCodeBook = pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr;
+ const SHORT *BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection = 0;
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+
+ FDKmemclear(pCodeBook, sizeof(UCHAR)*(8*16));
+
+ const int nbits = (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) == 1) ? 5 : 3;
+
+ int sect_esc_val = (1 << nbits) - 1 ;
+
+ UCHAR ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ for (group=0; group<GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
+ {
+ for (band=0; band < ScaleFactorBandsTransmitted; )
+ {
+ sect_len = 0;
+ if ( flags & AC_ER_VCB11 ) {
+ sect_cb = (UCHAR) FDKreadBits(bs,5);
+ }
+ else
+ sect_cb = (UCHAR) FDKreadBits(bs,4);
+
+ if ( ((flags & AC_ER_VCB11) == 0) || ( sect_cb < 11 ) || ((sect_cb > 11) && (sect_cb < 16)) ) {
+ sect_len_incr = FDKreadBits(bs, nbits);
+ while (sect_len_incr == sect_esc_val)
+ {
+ sect_len += sect_esc_val;
+ sect_len_incr = FDKreadBits(bs, nbits);
+ }
+ }
+ else {
+ sect_len_incr = 1;
+ }
+
+ sect_len += sect_len_incr;
+
+
+ top = band + sect_len;
+
+ if (flags & AC_ER_HCR) {
+ /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */
+ pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band];
+ numLinesInSecIdx++;
+ if (numLinesInSecIdx >= MAX_SFB_HCR) {
+ return AAC_DEC_PARSE_ERROR;
+ }
+ if (
+ (sect_cb == BOOKSCL) )
+ {
+ return AAC_DEC_INVALID_CODE_BOOK;
+ } else {
+ *pHcrCodeBook++ = sect_cb;
+ }
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection++;
+ }
+
+ /* Check spectral line limits */
+ if (IsLongBlock( &(pAacDecoderChannelInfo->icsInfo) ))
+ {
+ if (top > 64) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ } else { /* short block */
+ if (top + group*16 > (8 * 16)) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ }
+
+ /* Check if decoded codebook index is feasible */
+ if ( (sect_cb == BOOKSCL)
+ || ( (sect_cb == INTENSITY_HCB || sect_cb == INTENSITY_HCB2) && pAacDecoderChannelInfo->pDynData->RawDataInfo.CommonWindow == 0)
+ )
+ {
+ return AAC_DEC_INVALID_CODE_BOOK;
+ }
+
+ /* Store codebook index */
+ for (; band < top; band++)
+ {
+ pCodeBook[group*16+band] = sect_cb;
+ }
+ }
+ }
+
+
+ return ErrorStatus;
+}
+
+/* mso: provides a faster way to i-quantize a whole band in one go */
+
+/**
+ * \brief inverse quantize one sfb. Each value of the sfb is processed according to the
+ * formula: spectrum[i] = Sign(spectrum[i]) * Matissa(spectrum[i])^(4/3) * 2^(lsb/4).
+ * \param spectrum pointer to first line of the sfb to be inverse quantized.
+ * \param noLines number of lines belonging to the sfb.
+ * \param lsb last 2 bits of the scale factor of the sfb.
+ * \param scale max allowed shift scale for the sfb.
+ */
+static
+void InverseQuantizeBand( FIXP_DBL * RESTRICT spectrum,
+ INT noLines,
+ INT lsb,
+ INT scale )
+{
+ const FIXP_DBL * RESTRICT InverseQuantTabler=(FIXP_DBL *)InverseQuantTable;
+ const FIXP_DBL * RESTRICT MantissaTabler=(FIXP_DBL *)MantissaTable[lsb];
+ const SCHAR* RESTRICT ExponentTabler=(SCHAR*)ExponentTable[lsb];
+
+ FIXP_DBL *ptr = spectrum;
+ FIXP_DBL signedValue;
+
+ FDK_ASSERT(noLines>2);
+ for (INT i=noLines; i--; )
+ {
+ if ((signedValue = *ptr++) != FL2FXCONST_DBL(0))
+ {
+ FIXP_DBL value = fAbs(signedValue);
+ UINT freeBits = CntLeadingZeros(value);
+ UINT exponent = 32 - freeBits;
+
+ UINT x = (UINT) (LONG)value << (INT) freeBits;
+ x <<= 1; /* shift out sign bit to avoid masking later on */
+ UINT tableIndex = x >> 24;
+ x = (x >> 20) & 0x0F;
+
+ UINT r0=(UINT)(LONG)InverseQuantTabler[tableIndex+0];
+ UINT r1=(UINT)(LONG)InverseQuantTabler[tableIndex+1];
+ UINT temp= (r1 - r0)*x + (r0 << 4);
+
+ value = fMultDiv2((FIXP_DBL)temp, MantissaTabler[exponent]);
+
+ /* + 1 compensates fMultDiv2() */
+ scaleValueInPlace(&value, scale + ExponentTabler[exponent] + 1);
+
+ signedValue = (signedValue < (FIXP_DBL)0) ? -value : value;
+ ptr[-1] = signedValue;
+ }
+ }
+}
+
+AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo)
+{
+ int window, group, groupwin, band;
+ int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale;
+ SHORT *RESTRICT pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+
+ FDKmemclear(pAacDecoderChannelInfo->pDynData->aSfbScale, (8*16)*sizeof(SHORT));
+
+ for (window=0, group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
+ {
+ for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++, window++)
+ {
+ /* inverse quantization */
+ for (band=0; band < ScaleFactorBandsTransmitted; band++)
+ {
+ FIXP_DBL *pSpectralCoefficient = SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength) + BandOffsets[band];
+
+ int noLines = BandOffsets[band+1] - BandOffsets[band];
+ int bnds = group*16+band;
+ int i;
+
+ if ((pCodeBook[bnds] == ZERO_HCB)
+ || (pCodeBook[bnds] == INTENSITY_HCB)
+ || (pCodeBook[bnds] == INTENSITY_HCB2)
+ )
+ continue;
+
+ if (pCodeBook[bnds] == NOISE_HCB)
+ {
+ /* Leave headroom for PNS values. + 1 because ceil(log2(2^(0.25*3))) = 1,
+ worst case of additional headroom required because of the scalefactor. */
+ pSfbScale[window*16+band] = (pScaleFactor [bnds] >> 2) + 1 ;
+ continue;
+ }
+
+ /* Find max spectral line value of the current sfb */
+ FIXP_DBL locMax = (FIXP_DBL)0;
+
+ for (i = noLines; i-- ; ) {
+ /* Expensive memory access */
+ locMax = fMax(fixp_abs(pSpectralCoefficient[i]), locMax);
+ }
+
+ /* Cheap robustness improvement - Do not remove!!! */
+ if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+
+ /*
+ The inverse quantized spectral lines are defined by:
+ pSpectralCoefficient[i] = Sign(pSpectralCoefficient[i]) * 2^(0.25*pScaleFactor[bnds]) * pSpectralCoefficient[i]^(4/3)
+ This is equivalent to:
+ pSpectralCoefficient[i] = Sign(pSpectralCoefficient[i]) * (2^(pScaleFactor[bnds] % 4) * pSpectralCoefficient[i]^(4/3))
+ pSpectralCoefficient_e[i] += pScaleFactor[bnds]/4
+ */
+ {
+ int msb = pScaleFactor [bnds] >> 2 ;
+ int lsb = pScaleFactor [bnds] & 0x03 ;
+
+ int scale = GetScaleFromValue(locMax, lsb);
+
+ pSfbScale[window*16+band] = msb - scale;
+ InverseQuantizeBand(pSpectralCoefficient, noLines, lsb, scale);
+ }
+ }
+ }
+ }
+
+
+ return AAC_DEC_OK;
+}
+
+
+AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags)
+{
+ int i,index;
+ int window,group,groupwin,groupoffset,band;
+ UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+ const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
+
+ SPECTRAL_PTR pSpectralCoefficient = pAacDecoderChannelInfo->pSpectralCoefficient;
+ FIXP_DBL locMax;
+
+ int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+
+ FDK_ASSERT(BandOffsets != NULL);
+
+ FDKmemclear(pSpectralCoefficient, sizeof(SPECTRUM));
+
+ if ( (flags & AC_ER_HCR) == 0 )
+ {
+ groupoffset = 0;
+
+ /* plain huffman decoder short */
+ for (group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
+ {
+ for (band=0; band < ScaleFactorBandsTransmitted; band++)
+ {
+ int bnds = group*16+band;
+ UCHAR currentCB = pCodeBook[bnds];
+
+ /* patch to run plain-huffman-decoder with vcb11 input codebooks (LAV-checking might be possible below using the virtual cb and a LAV-table) */
+ if ((currentCB >= 16) && (currentCB <= 31)) {
+ pCodeBook[bnds] = currentCB = 11;
+ }
+ if ( !((currentCB == ZERO_HCB)
+ || (currentCB == NOISE_HCB)
+ || (currentCB == INTENSITY_HCB)
+ || (currentCB == INTENSITY_HCB2)) )
+ {
+ const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[currentCB];
+ int step = hcb->Dimension;
+ int offset = hcb->Offset;
+ int bits = hcb->numBits;
+ int mask = (1<<bits)-1;
+
+ for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++)
+ {
+ window = groupoffset + groupwin;
+
+ FIXP_DBL *mdctSpectrum = SPEC(pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength);
+
+ locMax = (FIXP_DBL)0 ;
+
+ for (index=BandOffsets[band]; index < BandOffsets[band+1]; index+=step)
+ {
+ int idx = CBlock_DecodeHuffmanWord(bs,hcb);
+
+ for (i=0; i<step; i++) {
+ FIXP_DBL tmp;
+
+ tmp = (FIXP_DBL)((idx & mask)-offset);
+ idx >>= bits;
+
+ if (offset == 0) {
+ if (tmp != FIXP_DBL(0))
+ tmp = (FDKreadBits(bs,1))? -tmp : tmp;
+ }
+ mdctSpectrum[index+i] = tmp;
+ }
+
+ if (currentCB == ESCBOOK)
+ {
+ mdctSpectrum[index+0] = (FIXP_DBL)CBlock_GetEscape(bs, (LONG)mdctSpectrum[index+0]);
+ mdctSpectrum[index+1] = (FIXP_DBL)CBlock_GetEscape(bs, (LONG)mdctSpectrum[index+1]);
+
+ }
+ }
+ }
+ }
+ }
+ groupoffset += GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group);
+ }
+ /* plain huffman decoding (short) finished */
+ }
+ /* HCR - Huffman Codeword Reordering short */
+ else /* if ( flags & AC_ER_HCR ) */
+ {
+ H_HCR_INFO hHcr = &pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo;
+ int hcrStatus = 0;
+ int hcrConcealWholeFrame = 0;
+
+ /* advanced Huffman decoding starts here (HCR decoding :) */
+ if ( pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData != 0 ) {
+
+ /* HCR initialization short */
+ hcrStatus = HcrInit(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
+
+ if (hcrStatus != 0) {
+#if HCR_ERROR_CONCEALMENT
+ hcrConcealWholeFrame = 1;
+ return AAC_DEC_DECODE_FRAME_ERROR; /* concealment is muting in the first step, therefore return now */
+ // hcr decoding is not skipped because of returning above
+#else
+ return AAC_DEC_DECODE_FRAME_ERROR;
+#endif
+ }
+
+ /* HCR decoding short */
+ hcrStatus = HcrDecoder(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
+
+
+#if HCR_ERROR_CONCEALMENT
+ HcrMuteErroneousLines(hHcr);
+#else
+ return AAC_DEC_DECODE_FRAME_ERROR;
+#endif /* HCR_ERROR_CONCEALMENT */
+
+ FDKpushFor (bs, pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData);
+ }
+ }
+ /* HCR - Huffman Codeword Reordering short finished */
+
+
+
+ if ( IsLongBlock(&pAacDecoderChannelInfo->icsInfo) && !(flags & (AC_ELD|AC_SCALABLE)) )
+ {
+ /* apply pulse data */
+ CPulseData_Apply(&pAacDecoderChannelInfo->pDynData->specificTo.aac.PulseData,
+ GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo),
+ SPEC_LONG(pSpectralCoefficient));
+ }
+
+
+ return AAC_DEC_OK;
+}
+
+
+
+void ApplyTools ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags,
+ const int channel )
+{
+
+ if ( !(flags & (AC_USAC|AC_RSVD50|AC_MPS_RES)) ) {
+ CPns_Apply(
+ &pAacDecoderChannelInfo[channel]->data.aac.PnsData,
+ &pAacDecoderChannelInfo[channel]->icsInfo,
+ pAacDecoderChannelInfo[channel]->pSpectralCoefficient,
+ pAacDecoderChannelInfo[channel]->specScale,
+ pAacDecoderChannelInfo[channel]->pDynData->aScaleFactor,
+ pSamplingRateInfo,
+ pAacDecoderChannelInfo[channel]->granuleLength,
+ channel
+ );
+ }
+
+ CTns_Apply (
+ &pAacDecoderChannelInfo[channel]->pDynData->TnsData,
+ &pAacDecoderChannelInfo[channel]->icsInfo,
+ pAacDecoderChannelInfo[channel]->pSpectralCoefficient,
+ pSamplingRateInfo,
+ pAacDecoderChannelInfo[channel]->granuleLength
+ );
+}
+
+static
+int getWindow2Nr(int length, int shape)
+{
+ int nr = 0;
+
+ if (shape == 2) {
+ /* Low Overlap, 3/4 zeroed */
+ nr = (length * 3)>>2;
+ }
+
+ return nr;
+}
+
+void CBlock_FrequencyToTime(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ INT_PCM outSamples[],
+ const SHORT frameLen,
+ const int stride,
+ const int frameOk,
+ FIXP_DBL *pWorkBuffer1 )
+{
+ int fr, fl, tl, nSamples, nSpec;
+
+ /* Determine left slope length (fl), right slope length (fr) and transform length (tl).
+ USAC: The slope length may mismatch with the previous frame in case of LPD / FD
+ transitions. The adjustment is handled by the imdct implementation.
+ */
+ tl = frameLen;
+ nSpec = 1;
+
+ switch( pAacDecoderChannelInfo->icsInfo.WindowSequence ) {
+ default:
+ case OnlyLongSequence:
+ fl = frameLen;
+ fr = frameLen - getWindow2Nr(frameLen, GetWindowShape(&pAacDecoderChannelInfo->icsInfo));
+ break;
+ case LongStopSequence:
+ fl = frameLen >> 3;
+ fr = frameLen;
+ break;
+ case LongStartSequence: /* or StopStartSequence */
+ fl = frameLen;
+ fr = frameLen >> 3;
+ break;
+ case EightShortSequence:
+ fl = fr = frameLen >> 3;
+ tl >>= 3;
+ nSpec = 8;
+ break;
+ }
+
+ {
+ int i;
+
+ {
+ FIXP_DBL *tmp = pAacDecoderChannelInfo->pComData->workBufferCore1->mdctOutTemp;
+
+ nSamples = imdct_block(
+ &pAacDecoderStaticChannelInfo->IMdct,
+ tmp,
+ SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
+ pAacDecoderChannelInfo->specScale,
+ nSpec,
+ frameLen,
+ tl,
+ FDKgetWindowSlope(fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
+ fl,
+ FDKgetWindowSlope(fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
+ fr,
+ (FIXP_DBL)0 );
+
+ for (i=0; i<frameLen; i++) {
+ outSamples[i*stride] = IMDCT_SCALE(tmp[i]);
+ }
+ }
+ }
+
+ FDK_ASSERT(nSamples == frameLen);
+
+}
+
+#include "ldfiltbank.h"
+void CBlock_FrequencyToTimeLowDelay( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ INT_PCM outSamples[],
+ const short frameLen,
+ const char stride )
+{
+ InvMdctTransformLowDelay_fdk (
+ SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
+ pAacDecoderChannelInfo->specScale[0],
+ outSamples,
+ pAacDecoderStaticChannelInfo->pOverlapBuffer,
+ stride,
+ frameLen
+ );
+}
diff --git a/libAACdec/src/block.h b/libAACdec/src/block.h
new file mode 100644
index 0000000..a4ba085
--- /dev/null
+++ b/libAACdec/src/block.h
@@ -0,0 +1,260 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: long/short-block decoding
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef BLOCK_H
+#define BLOCK_H
+
+#include "common_fix.h"
+
+#include "channelinfo.h"
+#include "FDK_bitstream.h"
+
+/* PNS (of block) */
+void CPns_Read (CPnsData *pPnsData,
+ HANDLE_FDK_BITSTREAM bs,
+ const CodeBookDescription *hcb,
+ SHORT *pScaleFactor,
+ UCHAR global_gain,
+ int band,
+ int group);
+
+
+void CPns_Apply (const CPnsData *pPnsData,
+ const CIcsInfo *pIcsInfo,
+ SPECTRAL_PTR pSpectrum,
+ const SHORT *pSpecScale,
+ const SHORT *pScaleFactor,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const INT granuleLength,
+ const int channel);
+
+
+
+/* TNS (of block) */
+/*!
+ \brief Read tns data-present flag from bitstream
+
+ The function reads the data-present flag for tns from
+ the bitstream.
+
+ \return none
+*/
+void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs,
+ CTnsData *pTnsData);
+
+void CTns_ReadDataPresentUsac(
+ HANDLE_FDK_BITSTREAM hBs,
+ CTnsData *pTnsData0,
+ CTnsData *pTnsData1,
+ const CIcsInfo *pIcsInfo,
+ const UINT flags,
+ const int fCommonWindow
+ );
+
+AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs,
+ CTnsData *pTnsData,
+ const CIcsInfo *pIcsInfo,
+ const UINT flags);
+
+void CTns_Apply ( CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */
+ const CIcsInfo *pIcsInfo,
+ SPECTRAL_PTR pSpectralCoefficient,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const INT granuleLength);
+
+/* Block */
+
+LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, const LONG q);
+
+/**
+ * \brief Read scale factor data. See chapter 4.6.2.3.2 of ISO/IEC 14496-3.
+ * The SF_OFFSET = 100 value referenced in chapter 4.6.2.3.3 is already substracted
+ * from the scale factor values. Also includes PNS data reading.
+ * \param bs bit stream handle data source
+ * \param pAacDecoderChannelInfo channel context info were decoded data is stored into.
+ * \param flags the decoder flags.
+ */
+AAC_DECODER_ERROR CBlock_ReadScaleFactorData(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs,
+ const UINT flags
+ );
+
+/**
+ * \brief Read Huffman encoded spectral data.
+ * \param pAacDecoderChannelInfo channel context info.
+ * \param pSamplingRateInfo sampling rate info (sfb offsets).
+ * \param flags syntax flags.
+ */
+AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags);
+
+
+AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags);
+
+/**
+ * \brief find a common exponent (shift factor) for all sfb in each Spectral window, and store them into
+ * CAacDecoderChannelInfo::specScale.
+ * \param pAacDecoderChannelInfo channel context info.
+ * \param pSamplingRateInfo sampling rate info (sfb offsets).
+ */
+void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo);
+
+/**
+ * \brief Apply TNS and PNS tools.
+ */
+void ApplyTools ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags,
+ const int channel );
+
+/**
+ * \brief Transform MDCT spectral data into time domain
+ */
+void CBlock_FrequencyToTime(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ INT_PCM outSamples[],
+ const SHORT frameLen,
+ const int stride,
+ const int frameOk,
+ FIXP_DBL *pWorkBuffer1);
+
+/**
+ * \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain.
+ */
+void CBlock_FrequencyToTimeLowDelay(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ INT_PCM outSamples[],
+ const short frameLen,
+ const char stride);
+
+AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo);
+
+/**
+ * \brief Calculate 2^(lsb/4) * value^(4/3)
+ * \param pValue pointer to quantized value. The inverse quantized result is stored back here.
+ * \param lsb 2 LSBs of the scale factor (scaleFactor % 4) applied as power 2 factor to the
+ * resulting inverse quantized value.
+ * \return the exponent of the result (mantissa) stored into *pValue.
+ */
+FDK_INLINE
+int EvaluatePower43 ( FIXP_DBL *pValue,
+ UINT lsb )
+{
+ FIXP_DBL value;
+ UINT freeBits;
+ UINT exponent;
+
+ value = *pValue;
+ freeBits = fNormz (value) ;
+ exponent = DFRACT_BITS - freeBits ;
+ FDK_ASSERT (exponent < 14);
+
+ UINT x = (((int)value << freeBits) >> 19) ;
+ UINT tableIndex = (x & 0x0FFF) >> 4 ;
+ FIXP_DBL invQVal ;
+
+ x = x & 0x0F;
+
+ UINT r0=(LONG)InverseQuantTable [tableIndex+0];
+ UINT r1=(LONG)InverseQuantTable [tableIndex+1];
+ USHORT nx=16-x;
+ UINT temp=(r0)*nx+(r1)*x;
+ invQVal = (FIXP_DBL)temp;
+
+ FDK_ASSERT(lsb < 4);
+ *pValue = fMultDiv2 (invQVal, MantissaTable [lsb][exponent]) ;
+
+ /* + 1 compensates fMultDiv2(). */
+ return ExponentTable [lsb][exponent] + 1;
+}
+
+/**
+ * \brief determine the required shift scale for the given quantized value and scale (factor % 4) value.
+ */
+FDK_INLINE int GetScaleFromValue (FIXP_DBL value, unsigned int lsb)
+{
+ if (value!=(FIXP_DBL)0)
+ {
+ int scale = EvaluatePower43 (&value, lsb) ;
+ return CntLeadingZeros (value) - scale - 2 ;
+ }
+ else
+ return 0; /* Return zero, because its useless to scale a zero value, saves workload and avoids scaling overshifts. */
+}
+
+
+//#ifdef AACDEC_HUFFMANDECODER_ENABLE
+
+/*!
+ \brief Read huffman codeword
+
+ The function reads the huffman codeword from the bitstream and
+ returns the index value.
+
+ \return index value
+*/
+inline int CBlock_DecodeHuffmanWord( HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */
+ const CodeBookDescription *hcb ) /*!< pointer to codebook description */
+{
+ UINT val;
+ UINT index = 0;
+ const USHORT (*CodeBook) [HuffmanEntries] = hcb->CodeBook;
+
+ while (1)
+ {
+ val = CodeBook[index][FDKreadBits(bs,HuffmanBits)]; /* Expensive memory access */
+
+ if ((val & 1) == 0)
+ {
+ index = val>>2;
+ continue;
+ }
+ else
+ {
+ if (val & 2)
+ {
+ FDKpushBackCache(bs,1);
+ }
+
+ val >>= 2;
+ break;
+ }
+ }
+
+ return val;
+}
+
+//#endif /* AACDEC_HUFFMANDECODER_ENABLE */
+
+#endif /* #ifndef BLOCK_H */
diff --git a/libAACdec/src/channel.cpp b/libAACdec/src/channel.cpp
new file mode 100644
index 0000000..3e1ffb6
--- /dev/null
+++ b/libAACdec/src/channel.cpp
@@ -0,0 +1,389 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "channel.h"
+#include "aacdecoder.h"
+#include "block.h"
+#include "aacdec_tns.h"
+#include "FDK_bitstream.h"
+#include "FDK_tools_rom.h"
+
+#include "conceal.h"
+
+#include "rvlc.h"
+
+#include "aacdec_hcr.h"
+
+
+static
+void MapMidSideMaskToPnsCorrelation (CAacDecoderChannelInfo *pAacDecoderChannelInfo[2])
+{
+ int group;
+
+ for (group = 0 ; group < pAacDecoderChannelInfo[L]->icsInfo.WindowGroups; group++) {
+ UCHAR groupMask = 1 << group;
+
+ for (UCHAR band = 0 ; band < pAacDecoderChannelInfo[L]->icsInfo.MaxSfBands; band++) {
+ if (pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] & groupMask) { /* channels are correlated */
+ CPns_SetCorrelation(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band, 0);
+
+ if (CPns_IsPnsUsed(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band) &&
+ CPns_IsPnsUsed(&pAacDecoderChannelInfo[R]->data.aac.PnsData, group, band))
+ pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] ^= groupMask; /* clear the groupMask-bit */
+ }
+ }
+ }
+}
+
+/*!
+ \brief Decode channel pair element
+
+ The function decodes a channel pair element.
+
+ \return none
+*/
+void CChannelElement_Decode( CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], /*!< pointer to aac decoder channel info */
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
+ SamplingRateInfo *pSamplingRateInfo,
+ UINT flags,
+ int el_channels)
+{
+ int ch, maybe_jstereo = 0;
+
+ maybe_jstereo = (el_channels > 1);
+
+ for (ch = 0; ch < el_channels; ch++) {
+ if ( pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_IMDCT
+ || pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_ELDFB )
+ {
+ CBlock_InverseQuantizeSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo);
+ }
+ }
+
+
+
+ if (maybe_jstereo) {
+ /* apply ms */
+ if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) {
+ int maxSfBandsL = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo);
+ int maxSfBandsR = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[R]->icsInfo);
+ if (pAacDecoderChannelInfo[L]->data.aac.PnsData.PnsActive || pAacDecoderChannelInfo[R]->data.aac.PnsData.PnsActive) {
+ MapMidSideMaskToPnsCorrelation(pAacDecoderChannelInfo);
+ }
+
+ CJointStereo_ApplyMS(pAacDecoderChannelInfo,
+ GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo),
+ GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo),
+ GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo),
+ maxSfBandsL,
+ maxSfBandsR);
+ }
+
+ /* apply intensity stereo */ /* modifies pAacDecoderChannelInfo[]->aSpecSfb */
+ CJointStereo_ApplyIS(pAacDecoderChannelInfo,
+ GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo),
+ GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo),
+ GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo),
+ GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo),
+ pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow ? 1 : 0);
+
+ }
+
+ for (ch = 0; ch < el_channels; ch++)
+ {
+ {
+ /* write pAacDecoderChannelInfo[ch]->specScale */
+ CBlock_ScaleSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo);
+
+ ApplyTools (pAacDecoderChannelInfo, pSamplingRateInfo, flags, ch);
+ }
+
+ }
+
+ CRvlc_ElementCheck(
+ pAacDecoderChannelInfo,
+ pAacDecoderStaticChannelInfo,
+ flags,
+ el_channels
+ );
+}
+
+void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo)
+{
+ int b, w, maxBands, maxWindows;
+ int maxSfb = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
+
+ if ( IsLongBlock(&pAacDecoderChannelInfo->icsInfo) ) {
+ maxBands = 64;
+ maxWindows = 1;
+ } else {
+ maxBands = 16;
+ maxWindows = 8;
+ }
+
+ for (w = 0; w<maxWindows; w++) {
+ for (b = 0; b < maxSfb; b++) {
+ pCodeBook[b] = ESCBOOK;
+ }
+ for (; b<maxBands; b++) {
+ pCodeBook[b] = ZERO_HCB;
+ }
+ pCodeBook += maxBands;
+ }
+}
+
+
+/*
+ * Arbitrary order bitstream parser
+ */
+
+AAC_DECODER_ERROR CChannelElement_Read(HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ const AUDIO_OBJECT_TYPE aot,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags,
+ const UINT frame_length,
+ const UCHAR numberOfChannels,
+ const SCHAR epConfig,
+ HANDLE_TRANSPORTDEC pTpDec
+ )
+{
+ AAC_DECODER_ERROR error = AAC_DEC_OK;
+ const element_list_t *list;
+ int i, ch, decision_bit;
+ int crcReg1 = -1, crcReg2 = -1;
+
+ FDK_ASSERT( (numberOfChannels == 1) || (numberOfChannels == 2) );
+
+ /* Get channel element sequence table */
+ list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0);
+ if (list == NULL) {
+ error = AAC_DEC_UNSUPPORTED_FORMAT;
+ goto bail;
+ }
+
+ CTns_Reset(&pAacDecoderChannelInfo[0]->pDynData->TnsData);
+ if (numberOfChannels == 2) {
+ CTns_Reset(&pAacDecoderChannelInfo[1]->pDynData->TnsData);
+ }
+
+ if (flags & (AC_ELD|AC_SCALABLE)) {
+ pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 1;
+ if (numberOfChannels == 2) {
+ pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
+ }
+ if (numberOfChannels == 2) {
+ pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
+ }
+ }
+
+ /* Iterate through sequence table */
+ i = 0;
+ ch = 0;
+ decision_bit = 0;
+ do {
+ switch (list->id[i]) {
+ case element_instance_tag:
+ pAacDecoderChannelInfo[0]->ElementInstanceTag = FDKreadBits(hBs, 4);
+ if (numberOfChannels == 2) {
+ pAacDecoderChannelInfo[1]->ElementInstanceTag = pAacDecoderChannelInfo[0]->ElementInstanceTag;
+ }
+ break;
+ case common_window:
+ decision_bit = pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow = FDKreadBits(hBs, 1);
+ if (numberOfChannels == 2) {
+ pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
+ }
+ break;
+ case ics_info:
+ /* Read individual channel info */
+ error = IcsRead( hBs,
+ &pAacDecoderChannelInfo[ch]->icsInfo,
+ pSamplingRateInfo,
+ flags );
+
+ if (numberOfChannels == 2 && pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) {
+ pAacDecoderChannelInfo[1]->icsInfo = pAacDecoderChannelInfo[0]->icsInfo;
+ }
+ break;
+
+
+ case ltp_data_present:
+ if (FDKreadBits(hBs, 1) != 0) {
+ error = AAC_DEC_UNSUPPORTED_PREDICTION;
+ }
+ break;
+
+ case ms:
+ if ( CJointStereo_Read(
+ hBs,
+ &pAacDecoderChannelInfo[0]->pComData->jointStereoData,
+ GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo),
+ GetScaleMaxFactorBandsTransmitted(&pAacDecoderChannelInfo[0]->icsInfo,
+ &pAacDecoderChannelInfo[1]->icsInfo),
+ flags) )
+ {
+ error = AAC_DEC_PARSE_ERROR;
+ }
+ break;
+
+ case global_gain:
+ pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.GlobalGain = (UCHAR) FDKreadBits(hBs,8);
+ break;
+
+ case section_data:
+ error = CBlock_ReadSectionData( hBs,
+ pAacDecoderChannelInfo[ch],
+ pSamplingRateInfo,
+ flags );
+ break;
+
+
+ case scale_factor_data:
+ if (flags & AC_ER_RVLC) {
+ /* read RVLC data from bitstream (error sens. cat. 1) */
+ CRvlc_Read(pAacDecoderChannelInfo[ch], hBs);
+ }
+ else
+ {
+ error = CBlock_ReadScaleFactorData(pAacDecoderChannelInfo[ch], hBs, flags);
+ }
+ break;
+
+ case pulse:
+ if ( CPulseData_Read( hBs,
+ &pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.PulseData,
+ pSamplingRateInfo->ScaleFactorBands_Long, /* pulse data is only allowed to be present in long blocks! */
+ (void*)&pAacDecoderChannelInfo[ch]->icsInfo,
+ frame_length
+ ) != 0 )
+ {
+ error = AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ break;
+ case tns_data_present:
+ CTns_ReadDataPresentFlag(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData);
+ break;
+ case tns_data:
+ /* tns_data_present is checked inside CTns_Read(). */
+ error = CTns_Read(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData, &pAacDecoderChannelInfo[ch]->icsInfo, flags);
+ break;
+
+ case gain_control_data:
+ break;
+
+ case gain_control_data_present:
+ if (FDKreadBits(hBs, 1)) {
+ error = AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA;
+ }
+ break;
+
+ case esc2_rvlc:
+ if (flags & AC_ER_RVLC) {
+ CRvlc_Decode(
+ pAacDecoderChannelInfo[ch],
+ pAacDecoderStaticChannelInfo[ch],
+ hBs
+ );
+ }
+ break;
+
+ case esc1_hcr:
+ if (flags & AC_ER_HCR) {
+ CHcr_Read(hBs, pAacDecoderChannelInfo[ch] );
+ }
+ break;
+
+ case spectral_data:
+ error = CBlock_ReadSpectralData( hBs,
+ pAacDecoderChannelInfo[ch],
+ pSamplingRateInfo,
+ flags );
+ if (flags & AC_ELD) {
+ pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_ELDFB;
+ } else {
+ pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT;
+ }
+ break;
+
+
+ /* CRC handling */
+ case adtscrc_start_reg1:
+ if (pTpDec != NULL) {
+ crcReg1 = transportDec_CrcStartReg(pTpDec, 192);
+ }
+ break;
+ case adtscrc_start_reg2:
+ if (pTpDec != NULL) {
+ crcReg2 = transportDec_CrcStartReg(pTpDec, 128);
+ }
+ break;
+ case adtscrc_end_reg1:
+ case drmcrc_end_reg:
+ if (pTpDec != NULL) {
+ transportDec_CrcEndReg(pTpDec, crcReg1);
+ }
+ break;
+ case adtscrc_end_reg2:
+ if (pTpDec != NULL) {
+ transportDec_CrcEndReg(pTpDec, crcReg2);
+ }
+ break;
+ case drmcrc_start_reg:
+ if (pTpDec != NULL) {
+ crcReg1 = transportDec_CrcStartReg(pTpDec, 0);
+ }
+ break;
+
+ /* Non data cases */
+ case next_channel:
+ ch = (ch + 1) % numberOfChannels;
+ break;
+ case link_sequence:
+ list = list->next[decision_bit];
+ i=-1;
+ break;
+
+ default:
+ error = AAC_DEC_UNSUPPORTED_FORMAT;
+ break;
+ }
+
+ if (error != AAC_DEC_OK) {
+ goto bail;
+ }
+
+ i++;
+
+ } while (list->id[i] != end_of_sequence);
+
+bail:
+ return error;
+}
diff --git a/libAACdec/src/channel.h b/libAACdec/src/channel.h
new file mode 100644
index 0000000..6c5441f
--- /dev/null
+++ b/libAACdec/src/channel.h
@@ -0,0 +1,86 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef CHANNEL_H
+#define CHANNEL_H
+
+#include "common_fix.h"
+
+#include "FDK_bitstream.h"
+#include "channelinfo.h"
+#include "tpdec_lib.h"
+
+/**
+ * \brief Init codeBook SFB indices (section data) with HCB_ESC. Useful for bitstreams
+ * which do not have any section data, but still SFB's (scale factor bands). This has
+ * the effect that upto the amount of transmitted SFB are treated as non-zero.
+ * \param pAacDecoderChannelInfo channel info structure containing a valid icsInfo struct.
+ */
+void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo);
+
+/**
+ * \brief decode a channel element. To be called after CChannelElement_Read()
+ * \param pAacDecoderChannelInfo pointer to channel data struct. Depending on el_channels either one or two.
+ * \param pSamplingRateInfo pointer to sample rate information structure
+ * \param el_channels amount of channels of the element to be decoded.
+ * \param output pointer to time domain output buffer (ACELP)
+ * \param stride factor for accessing output
+ */
+void CChannelElement_Decode ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
+ SamplingRateInfo *pSamplingRateInfo,
+ UINT flags,
+ int el_channels );
+
+
+/**
+ * \brief Read channel element of given type from bitstream.
+ * \param hBs bitstream handle to access bitstream data.
+ * \param pAacDecoderChannelInfo pointer array to store channel information.
+ * \param aot Audio Object Type
+ * \param pSamplingRateInfo sampling rate info table.
+ * \param flags parser guidance flags
+ * \param numberOfChannels amoun of channels contained in the object to be parsed.
+ * \param epConfig the current epConfig value obtained from the Audio Specific Config.
+ * \param pTp transport decoder handle required for ADTS CRC checking.
+ * ...
+ * \return an AAC_DECODER_ERROR error code.
+ */
+AAC_DECODER_ERROR CChannelElement_Read(HANDLE_FDK_BITSTREAM hBs,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ const AUDIO_OBJECT_TYPE aot,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const UINT flags,
+ const UINT frame_length,
+ const UCHAR numberOfChannels,
+ const SCHAR epConfig,
+ HANDLE_TRANSPORTDEC pTpDec
+ );
+
+#endif /* #ifndef CHANNEL_H */
diff --git a/libAACdec/src/channelinfo.cpp b/libAACdec/src/channelinfo.cpp
new file mode 100644
index 0000000..5c113aa
--- /dev/null
+++ b/libAACdec/src/channelinfo.cpp
@@ -0,0 +1,214 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: individual channel stream info
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "channelinfo.h"
+#include "aac_rom.h"
+#include "aac_ram.h"
+#include "FDK_bitstream.h"
+
+
+AAC_DECODER_ERROR IcsReadMaxSfb (
+ HANDLE_FDK_BITSTREAM bs,
+ CIcsInfo *pIcsInfo,
+ const SamplingRateInfo *pSamplingRateInfo
+ )
+{
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+ int nbits;
+
+ if (IsLongBlock(pIcsInfo)) {
+ nbits = 6;
+ pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
+ } else {
+ nbits = 4;
+ pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
+ }
+ pIcsInfo->MaxSfBands = (UCHAR) FDKreadBits(bs, nbits);
+
+ if (pIcsInfo->MaxSfBands > pIcsInfo->TotalSfBands){
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ }
+
+ return ErrorStatus;
+}
+
+
+
+AAC_DECODER_ERROR IcsRead(HANDLE_FDK_BITSTREAM bs,
+ CIcsInfo *pIcsInfo,
+ const SamplingRateInfo* pSamplingRateInfo,
+ const UINT flags)
+{
+ AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
+
+ pIcsInfo->Valid = 0;
+
+ if (flags & AC_ELD){
+ pIcsInfo->WindowSequence = OnlyLongSequence;
+ pIcsInfo->WindowShape = 0;
+ }
+ else {
+ if ( !(flags & (AC_USAC|AC_RSVD50)) ) {
+ FDKreadBits(bs,1);
+ }
+ pIcsInfo->WindowSequence = (UCHAR) FDKreadBits(bs,2);
+ pIcsInfo->WindowShape = (UCHAR) FDKreadBits(bs,1);
+ if (flags & AC_LD) {
+ if (pIcsInfo->WindowShape) {
+ pIcsInfo->WindowShape = 2; /* select low overlap instead of KBD */
+ }
+ }
+ }
+
+ /* Sanity check */
+ if ( (flags & (AC_ELD|AC_LD)) && pIcsInfo->WindowSequence != OnlyLongSequence) {
+ pIcsInfo->WindowSequence = OnlyLongSequence;
+ ErrorStatus = AAC_DEC_PARSE_ERROR;
+ goto bail;
+ }
+
+ ErrorStatus = IcsReadMaxSfb(bs, pIcsInfo, pSamplingRateInfo);
+ if (ErrorStatus != AAC_DEC_OK) {
+ goto bail;
+ }
+
+ if (IsLongBlock(pIcsInfo))
+ {
+ if ( !(flags & (AC_ELD|AC_SCALABLE|AC_BSAC|AC_USAC|AC_RSVD50)) ) /* If not ELD nor Scalable nor BSAC nor USAC syntax then ... */
+ {
+ if ((UCHAR)FDKreadBits(bs,1) != 0 ) /* UCHAR PredictorDataPresent */
+ {
+ ErrorStatus = AAC_DEC_UNSUPPORTED_PREDICTION;
+ goto bail;
+ }
+ }
+
+ pIcsInfo->WindowGroups = 1;
+ pIcsInfo->WindowGroupLength[0] = 1;
+ }
+ else
+ {
+ INT i;
+ UINT mask;
+
+ pIcsInfo->ScaleFactorGrouping = (UCHAR) FDKreadBits(bs,7);
+
+ pIcsInfo->WindowGroups = 0 ;
+
+ for (i=0; i < (8-1); i++)
+ {
+ mask = 1 << (6 - i);
+ pIcsInfo->WindowGroupLength[i] = 1;
+
+ if (pIcsInfo->ScaleFactorGrouping & mask)
+ {
+ pIcsInfo->WindowGroupLength[pIcsInfo->WindowGroups]++;
+ }
+ else
+ {
+ pIcsInfo->WindowGroups++;
+ }
+ }
+
+ /* loop runs to i < 7 only */
+ pIcsInfo->WindowGroupLength[8-1] = 1;
+ pIcsInfo->WindowGroups++;
+ }
+
+
+bail:
+ if (ErrorStatus == AAC_DEC_OK)
+ pIcsInfo->Valid = 1;
+
+ return ErrorStatus;
+}
+
+
+/*
+ interleave codebooks the following way
+
+ 9 (84w) | 1 (51w)
+ 10 (82w) | 2 (39w)
+ SCL (65w) | 4 (38w)
+ 3 (39w) | 5 (41w)
+ | 6 (40w)
+ | 7 (31w)
+ | 8 (31w)
+ (270w) (271w)
+*/
+
+
+/*
+ Table entries are sorted as following:
+ | num_swb_long_window | sfbands_long | num_swb_short_window | sfbands_short |
+*/
+AAC_DECODER_ERROR getSamplingRateInfo(
+ SamplingRateInfo *t,
+ UINT samplesPerFrame,
+ UINT samplingRateIndex,
+ UINT samplingRate
+ )
+{
+ int index = 0;
+
+
+ t->samplingRateIndex = samplingRateIndex;
+ t->samplingRate = samplingRate;
+
+ switch (samplesPerFrame) {
+ case 1024:
+ index = 0;
+ break;
+ case 960:
+ index = 1;
+ break;
+ case 512:
+ index = 3;
+ break;
+ case 480:
+ index = 4;
+ break;
+
+ default:
+ return AAC_DEC_UNSUPPORTED_FORMAT;
+ }
+
+ t->ScaleFactorBands_Long = sfbOffsetTables[index][samplingRateIndex].sfbOffsetLong;
+ t->ScaleFactorBands_Short = sfbOffsetTables[index][samplingRateIndex].sfbOffsetShort;
+ t->NumberOfScaleFactorBands_Long = sfbOffsetTables[index][samplingRateIndex].numberOfSfbLong;
+ t->NumberOfScaleFactorBands_Short = sfbOffsetTables[index][samplingRateIndex].numberOfSfbShort;
+
+ if (t->ScaleFactorBands_Long == NULL || t->NumberOfScaleFactorBands_Long == 0) {
+ return AAC_DEC_UNSUPPORTED_FORMAT;
+ }
+
+ FDK_ASSERT(t->ScaleFactorBands_Long[t->NumberOfScaleFactorBands_Long] == samplesPerFrame);
+ FDK_ASSERT(t->ScaleFactorBands_Short == NULL || t->ScaleFactorBands_Short[t->NumberOfScaleFactorBands_Short]*8 == samplesPerFrame);
+
+ return AAC_DEC_OK;
+}
diff --git a/libAACdec/src/channelinfo.h b/libAACdec/src/channelinfo.h
new file mode 100644
index 0000000..f74583d
--- /dev/null
+++ b/libAACdec/src/channelinfo.h
@@ -0,0 +1,388 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: individual channel stream info
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef CHANNELINFO_H
+#define CHANNELINFO_H
+
+#include "common_fix.h"
+
+#include "aac_rom.h"
+#include "aacdecoder_lib.h"
+#include "FDK_bitstream.h"
+#include "overlapadd.h"
+
+#include "mdct.h"
+#include "stereo.h"
+#include "pulsedata.h"
+#include "aacdec_tns.h"
+
+#include "aacdec_pns.h"
+
+#include "aacdec_hcr_types.h"
+#include "rvlc_info.h"
+
+
+#include "conceal_types.h"
+
+ #include "aacdec_drc_types.h"
+
+/* Output rendering mode */
+typedef enum {
+ AACDEC_RENDER_INVALID = 0,
+ AACDEC_RENDER_IMDCT,
+ AACDEC_RENDER_ELDFB,
+ AACDEC_RENDER_LPD,
+ AACDEC_RENDER_INTIMDCT
+} AACDEC_RENDER_MODE;
+
+enum {
+ MAX_QUANTIZED_VALUE = 8191
+};
+
+enum
+{
+ OnlyLongSequence = 0,
+ LongStartSequence,
+ EightShortSequence,
+ LongStopSequence
+};
+
+
+typedef struct
+{
+ const SHORT *ScaleFactorBands_Long;
+ const SHORT *ScaleFactorBands_Short;
+ UCHAR NumberOfScaleFactorBands_Long;
+ UCHAR NumberOfScaleFactorBands_Short;
+ UINT samplingRateIndex;
+ UINT samplingRate;
+} SamplingRateInfo;
+
+typedef struct
+{
+ UCHAR CommonWindow;
+ UCHAR GlobalGain;
+
+} CRawDataInfo;
+
+typedef struct
+{
+ UCHAR WindowGroupLength[8];
+ UCHAR WindowGroups;
+ UCHAR Valid;
+
+ UCHAR WindowShape; /* 0: sine window, 1: KBD, 2: low overlap */
+ UCHAR WindowSequence; /* See enum above, 0: long, 1: start, 2: short, 3: stop */
+ UCHAR MaxSfBands;
+ UCHAR ScaleFactorGrouping;
+
+ UCHAR TotalSfBands;
+
+} CIcsInfo;
+
+
+enum
+{
+ ZERO_HCB = 0,
+ ESCBOOK = 11,
+ NSPECBOOKS = ESCBOOK + 1,
+ BOOKSCL = NSPECBOOKS,
+ NOISE_HCB = 13,
+ INTENSITY_HCB2 = 14,
+ INTENSITY_HCB = 15,
+ LAST_HCB
+};
+
+#define TNS_SCALE 3
+
+/*
+ * This struct must be allocated one for every channel and must be persistent.
+ */
+typedef struct
+{
+ FIXP_DBL *pOverlapBuffer;
+ mdct_t IMdct;
+
+
+
+ CDrcChannelData drcData;
+ CConcealmentInfo concealmentInfo;
+
+} CAacDecoderStaticChannelInfo;
+
+
+/*
+ * This union must be allocated for every element (up to 2 channels).
+ */
+typedef struct {
+
+ /* Common bit stream data */
+ SHORT aScaleFactor[(8*16)]; /* Spectral scale factors for each sfb in each window. */
+ SHORT aSfbScale[(8*16)]; /* could be free after ApplyTools() */
+ UCHAR aCodeBook[(8*16)]; /* section data: codebook for each window and sfb. */
+ CTnsData TnsData;
+ CRawDataInfo RawDataInfo;
+
+ shouldBeUnion {
+
+ struct {
+ CPulseData PulseData;
+ SHORT aNumLineInSec4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for Drm syntax */
+ UCHAR aCodeBooks4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for Drm syntax. Same as "aCodeBook" ? */
+ SHORT lenOfReorderedSpectralData;
+ SCHAR lenOfLongestCodeword;
+ SCHAR numberSection;
+ SCHAR rvlcCurrentScaleFactorOK;
+ SCHAR rvlcIntensityUsed;
+ } aac;
+ } specificTo;
+
+} CAacDecoderDynamicData;
+
+typedef shouldBeUnion {
+ CAacDecoderDynamicData pAacDecoderDynamicData[2];
+
+ /* Common signal data, can be used once the bit stream data from above is not used anymore. */
+ FIXP_DBL mdctOutTemp[1024];
+ FIXP_DBL sbrWorkBuffer[1024*2];
+
+} CWorkBufferCore1;
+
+/* Common data referenced by all channels */
+typedef struct {
+
+ CWorkBufferCore1 *workBufferCore1;
+ FIXP_DBL* workBufferCore2;
+
+ CPnsInterChannelData pnsInterChannelData;
+ INT pnsCurrentSeed;
+ INT pnsRandomSeed[(8*16)];
+
+ CJointStereoData jointStereoData; /* One for one element */
+
+ shouldBeUnion {
+ struct {
+ CErHcrInfo erHcrInfo;
+ CErRvlcInfo erRvlcInfo;
+ SHORT aRvlcScfEsc[RVLC_MAX_SFB]; /* needed once for all channels */
+ SHORT aRvlcScfFwd[RVLC_MAX_SFB]; /* needed once for all channels */
+ SHORT aRvlcScfBwd[RVLC_MAX_SFB]; /* needed once for all channels */
+ } aac;
+
+ } overlay;
+
+} CAacDecoderCommonData;
+
+
+/*
+ * This struct must be allocated one for every channels of every element and must be persistent.
+ * Among its members, the following memory areas can be overwritten under the given conditions:
+ * - pSpectralCoefficient The memory pointed to can be overwritten after time signal rendering.
+ * - data can be overwritten after time signal rendering.
+ * - pDynData memory pointed to can be overwritten after each CChannelElement_Decode() call.
+ * - pComData->overlay memory pointed to can be overwritten after each CChannelElement_Decode() call..
+ */
+typedef struct
+{
+ SPECTRAL_PTR pSpectralCoefficient; /* Spectral coefficients of each window */
+ SHORT specScale[8]; /* Scale shift values of each spectrum window */
+ CIcsInfo icsInfo;
+ INT granuleLength; /* Size of smallest spectrum piece */
+ UCHAR ElementInstanceTag;
+
+ AACDEC_RENDER_MODE renderMode; /* Output signal rendering mode */
+
+ shouldBeUnion {
+ struct {
+ CPnsData PnsData; /* Not required for USAC */
+ } aac;
+
+ struct {
+ } usac;
+ } data;
+
+ CAacDecoderDynamicData *pDynData; /* Data required for one element and discarded after decoding */
+ CAacDecoderCommonData *pComData; /* Data required for one channel at a time during decode */
+
+} CAacDecoderChannelInfo;
+
+/* channelinfo.cpp */
+
+AAC_DECODER_ERROR getSamplingRateInfo(SamplingRateInfo *t, UINT samplesPerFrame, UINT samplingRateIndex, UINT samplingRate);
+
+/**
+ * \brief Read max SFB from bit stream and assign TotalSfBands according
+ * to the window sequence and sample rate.
+ * \param hBs bit stream handle as data source
+ * \param pIcsInfo IcsInfo structure to read the window sequence and store MaxSfBands and TotalSfBands
+ * \param pSamplingRateInfo read only
+ */
+AAC_DECODER_ERROR IcsReadMaxSfb (
+ HANDLE_FDK_BITSTREAM hBs,
+ CIcsInfo *pIcsInfo,
+ const SamplingRateInfo *pSamplingRateInfo
+ );
+
+AAC_DECODER_ERROR IcsRead(
+ HANDLE_FDK_BITSTREAM bs,
+ CIcsInfo *pIcsInfo,
+ const SamplingRateInfo* SamplingRateInfoTable,
+ const UINT flags
+ );
+
+/* stereo.cpp, only called from this file */
+
+/*!
+ \brief Applies MS stereo.
+
+ The function applies MS stereo.
+
+ \param pAacDecoderChannelInfo aac channel info.
+ \param pScaleFactorBandOffsets pointer to scalefactor band offsets.
+ \param pWindowGroupLength pointer to window group length array.
+ \param windowGroups number of window groups.
+ \param scaleFactorBandsTransmittedL number of transmitted scalefactor bands in left channel.
+ \param scaleFactorBandsTransmittedR number of transmitted scalefactor bands in right channel.
+ May differ from scaleFactorBandsTransmittedL only for USAC.
+ \return none
+*/
+void CJointStereo_ApplyMS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
+ const short *pScaleFactorBandOffsets,
+ const UCHAR *pWindowGroupLength,
+ const int windowGroups,
+ const int scaleFactorBandsTransmittedL,
+ const int scaleFactorBandsTransmittedR);
+
+/*!
+ \brief Applies intensity stereo
+
+ The function applies intensity stereo.
+
+ \param pAacDecoderChannelInfo aac channel info.
+ \param pScaleFactorBandOffsets pointer to scalefactor band offsets.
+ \param pWindowGroupLength pointer to window group length array.
+ \param windowGroups number of window groups.
+ \param scaleFactorBandsTransmitted number of transmitted scalefactor bands.
+ \param CommonWindow common window bit.
+ \return none
+*/
+void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
+ const short *pScaleFactorBandOffsets,
+ const UCHAR *pWindowGroupLength,
+ const int windowGroups,
+ const int scaleFactorBandsTransmitted,
+ const UINT CommonWindow);
+
+
+/* aacdec_pns.cpp */
+int CPns_IsPnsUsed (const CPnsData *pPnsData,
+ const int group,
+ const int band);
+
+void CPns_SetCorrelation(CPnsData *pPnsData,
+ const int group,
+ const int band,
+ const int outofphase);
+
+/****************** inline functions ******************/
+
+inline UCHAR IsValid(const CIcsInfo *pIcsInfo)
+{
+ return pIcsInfo->Valid;
+}
+
+inline UCHAR IsLongBlock(const CIcsInfo *pIcsInfo)
+{
+ return (pIcsInfo->WindowSequence != EightShortSequence);
+}
+
+inline UCHAR GetWindowShape(const CIcsInfo *pIcsInfo)
+{
+ return pIcsInfo->WindowShape;
+}
+
+inline UCHAR GetWindowSequence(const CIcsInfo *pIcsInfo)
+{
+ return pIcsInfo->WindowSequence;
+}
+
+inline const SHORT *GetScaleFactorBandOffsets(const CIcsInfo *pIcsInfo, const SamplingRateInfo* samplingRateInfo)
+{
+ if (IsLongBlock(pIcsInfo))
+ {
+ return samplingRateInfo->ScaleFactorBands_Long;
+ }
+ else
+ {
+ return samplingRateInfo->ScaleFactorBands_Short;
+ }
+}
+
+inline int GetWindowsPerFrame(const CIcsInfo *pIcsInfo)
+{
+ return (pIcsInfo->WindowSequence == EightShortSequence) ? 8 : 1;
+}
+
+inline UCHAR GetWindowGroups(const CIcsInfo *pIcsInfo)
+{
+ return pIcsInfo->WindowGroups;
+}
+
+inline UCHAR GetWindowGroupLength(const CIcsInfo *pIcsInfo, const INT index)
+{
+ return pIcsInfo->WindowGroupLength[index];
+}
+
+inline const UCHAR *GetWindowGroupLengthTable(const CIcsInfo *pIcsInfo)
+{
+ return pIcsInfo->WindowGroupLength;
+}
+
+inline UCHAR GetScaleFactorBandsTransmitted(const CIcsInfo *pIcsInfo)
+{
+ return pIcsInfo->MaxSfBands;
+}
+
+inline UCHAR GetScaleMaxFactorBandsTransmitted(const CIcsInfo *pIcsInfo0, const CIcsInfo *pIcsInfo1)
+{
+ return fMax(pIcsInfo0->MaxSfBands, pIcsInfo1->MaxSfBands);
+}
+
+inline UCHAR GetScaleFactorBandsTotal(const CIcsInfo *pIcsInfo)
+{
+ return pIcsInfo->TotalSfBands;
+}
+
+/* Note: This function applies to AAC-LC only ! */
+inline UCHAR GetMaximumTnsBands(const CIcsInfo *pIcsInfo, const int samplingRateIndex)
+{
+ return tns_max_bands_tbl[samplingRateIndex][!IsLongBlock(pIcsInfo)];
+}
+
+#endif /* #ifndef CHANNELINFO_H */
+
diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp
new file mode 100644
index 0000000..9fb2ed3
--- /dev/null
+++ b/libAACdec/src/conceal.cpp
@@ -0,0 +1,1763 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: independent channel concealment
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+/*!
+ \page concealment AAC core concealment
+
+ This AAC core implementation includes a concealment function, which can be enabled
+ using the several defines during compilation.
+
+ There are various tests inside the core, starting with simple CRC tests and ending in
+ a variety of plausibility checks. If such a check indicates an invalid bitstream, then
+ concealment is applied.
+
+ Concealment is also applied when the calling main program indicates a distorted or missing
+ data frame using the frameOK flag. This is used for error detection on the transport layer.
+ (See below)
+
+ There are three concealment-modes:
+
+ 1) Muting: The spectral data is simply set to zero in case of an detected error.
+
+ 2) Noise substitution: In case of an detected error, concealment copies the last frame and adds
+ attenuates the spectral data. For this mode you have to set the #CONCEAL_NOISE define.
+ Noise substitution adds no additional delay.
+
+ 3) Interpolation: The interpolation routine swaps the spectral data from the previous and the
+ current frame just before the final frequency to time conversion. In case a single frame is
+ corrupted, concealmant interpolates between the last good and the first good frame to create
+ the spectral data for the missing frame. If multiple frames are corrupted, concealment
+ implements first a fade out based on slightly modified spectral values from the last good
+ frame. As soon as good frames are available, concealmant fades in the new spectral data.
+ For this mode you have to set the #CONCEAL_INTER define. Note that in this case, you also
+ need to set #SBR_BS_DELAY_ENABLE, which basically adds approriate delay in the SBR decoder.
+ Note that the Interpolating-Concealment increases the delay of your decoder by one frame
+ and that it does require additional resources such as memory and computational complexity.
+
+ <h2>How concealment can be used with errors on the transport layer</h2>
+
+ Many errors can or have to be detected on the transport layer. For example in IP based systems
+ packet loss can occur. The transport protocol used should indicate such packet loss by inserting
+ an empty frame with frameOK=0.
+*/
+
+#include "conceal.h"
+
+#include "aac_rom.h"
+#include "genericStds.h"
+
+
+/* PNS (of block) */
+#include "aacdec_pns.h"
+#include "block.h"
+
+#include "FDK_tools_rom.h"
+
+#define CONCEAL_DFLT_COMF_NOISE_LEVEL ( 46 ) /* ~= -70 dB */
+
+
+/* default settings */
+#define CONCEAL_DFLT_FADEOUT_FRAMES ( 5 )
+#define CONCEAL_DFLT_FADEIN_FRAMES ( 5 )
+#define CONCEAL_DFLT_MUTE_RELEASE_FRAMES ( 3 )
+
+#define CONCEAL_DFLT_FADE_FACTOR ( 0.707106781186548f ) /* 1/sqrt(2) */
+
+/* some often used constants: */
+#define FIXP_ZERO FL2FXCONST_DBL(0.0f)
+#define FIXP_ONE FL2FXCONST_DBL(1.0f)
+#define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f)
+
+/* For parameter conversion */
+#define CONCEAL_PARAMETER_BITS ( 8 )
+#define CONCEAL_MAX_QUANT_FACTOR ( (1<<CONCEAL_PARAMETER_BITS)-1 )
+/*#define CONCEAL_MIN_ATTENUATION_FACTOR_025 ( FL2FXCONST_DBL(0.971627951577106174) )*/ /* -0.25 dB */
+#define CONCEAL_MIN_ATTENUATION_FACTOR_025_LD FL2FXCONST_DBL(-0.041524101186092029596853445212299)
+/*#define CONCEAL_MIN_ATTENUATION_FACTOR_050 ( FL2FXCONST_DBL(0.944060876285923380) )*/ /* -0.50 dB */
+#define CONCEAL_MIN_ATTENUATION_FACTOR_050_LD FL2FXCONST_DBL(-0.083048202372184059253597008145293)
+
+typedef enum {
+ CConcealment_NoExpand,
+ CConcealment_Expand,
+ CConcealment_Compress
+}
+CConcealmentExpandType;
+
+static const FIXP_SGL facMod4Table[4] = {
+ FL2FXCONST_SGL(0.500000000f), /* FIXP_SGL(0x4000), 2^-(1-0,00) */
+ FL2FXCONST_SGL(0.594603558f), /* FIXP_SGL(0x4c1b), 2^-(1-0,25) */
+ FL2FXCONST_SGL(0.707106781f), /* FIXP_SGL(0x5a82), 2^-(1-0,50) */
+ FL2FXCONST_SGL(0.840896415f) /* FIXP_SGL(0x6ba2) 2^-(1-0,75) */
+};
+
+
+
+
+static void
+ CConcealment_CalcBandEnergy (
+ FIXP_DBL *spectrum,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int blockType,
+ CConcealmentExpandType ex,
+ int *sfbEnergy
+ );
+
+static void
+ CConcealment_InterpolateBuffer (
+ FIXP_DBL *spectrum,
+ SHORT *pSpecScalePrev,
+ SHORT *pSpecScaleAct,
+ SHORT *pSpecScaleOut,
+ int *enPrv,
+ int *enAct,
+ int sfbCnt,
+ const SHORT *pSfbOffset
+ );
+
+static int
+ CConcealment_ApplyInter (
+ CConcealmentInfo *pConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int samplesPerFrame,
+ const int improveTonal,
+ const int frameOk
+ );
+
+
+
+static int
+ CConcealment_ApplyNoise (
+ CConcealmentInfo *pConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int samplesPerFrame,
+ const UINT flags
+ );
+
+static void
+ CConcealment_UpdateState (
+ CConcealmentInfo *pConcealmentInfo,
+ int frameOk
+ );
+
+static void
+ CConcealment_ApplyRandomSign (
+ int iRandomPhase,
+ FIXP_DBL *spec,
+ int samplesPerFrame
+ );
+
+
+static int CConcealment_GetWinSeq(int prevWinSeq)
+{
+ int newWinSeq = OnlyLongSequence;
+
+ /* Try to have only long blocks */
+ if ( prevWinSeq == LongStartSequence
+ || prevWinSeq == EightShortSequence )
+ {
+ newWinSeq = LongStopSequence;
+ }
+
+ return (newWinSeq);
+}
+
+
+/*!
+ \brief Init common concealment information data
+
+ \pConcealCommonData Pointer to the concealment common data structure.
+
+ \return none
+*/
+void
+ CConcealment_InitCommonData (CConcealParams *pConcealCommonData)
+{
+ if (pConcealCommonData != NULL)
+ {
+ int i;
+
+ /* Set default error concealment technique */
+ pConcealCommonData->method = ConcealMethodInter;
+
+ pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES;
+ pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES;
+ pConcealCommonData->numMuteReleaseFrames = CONCEAL_DFLT_MUTE_RELEASE_FRAMES;
+
+ pConcealCommonData->comfortNoiseLevel = CONCEAL_DFLT_COMF_NOISE_LEVEL;
+
+ /* Init fade factors (symetric) */
+ pConcealCommonData->fadeOutFactor[0] = FL2FXCONST_SGL( CONCEAL_DFLT_FADE_FACTOR );
+ pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0];
+
+ for (i = 1; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
+ pConcealCommonData->fadeOutFactor[i] = FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i-1],FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR)));
+ pConcealCommonData->fadeInFactor[i] = pConcealCommonData->fadeOutFactor[i];
+ }
+ }
+}
+
+
+
+/*!
+ \brief Get current concealment method.
+
+ \pConcealCommonData Pointer to common concealment data (for all channels)
+
+ \return Concealment method.
+*/
+CConcealmentMethod
+ CConcealment_GetMethod( CConcealParams *pConcealCommonData )
+{
+ CConcealmentMethod method = ConcealMethodNone;
+
+ if (pConcealCommonData != NULL) {
+ method = pConcealCommonData->method;
+ }
+
+ return (method);
+}
+
+
+/*!
+ \brief Init concealment information for each channel
+
+ The function initializes the concealment information. Two methods can be chosen:
+ 0 = interpolation method (adds delay)
+ 1 = noise substitution (no delay, low complexity)
+
+ \return none
+*/
+void
+ CConcealment_InitChannelData (
+ CConcealmentInfo *pConcealChannelInfo,
+ CConcealParams *pConcealCommonData,
+ int samplesPerFrame )
+{
+ int i;
+
+ pConcealChannelInfo->pConcealParams = pConcealCommonData;
+
+ FDKmemclear(pConcealChannelInfo->spectralCoefficient, 1024 * sizeof(FIXP_CNCL));
+
+ for (i = 0; i < 8; i++) {
+ pConcealChannelInfo->specScale[i] = 0;
+ }
+
+ pConcealChannelInfo->iRandomPhase = 0;
+
+ pConcealChannelInfo->windowSequence = 0;
+ pConcealChannelInfo->windowShape = 0;
+
+ pConcealChannelInfo->prevFrameOk[0] = 1;
+ pConcealChannelInfo->prevFrameOk[1] = 1;
+
+ pConcealChannelInfo->cntFadeFrames = 0;
+ pConcealChannelInfo->cntValidFrames = 0;
+
+ pConcealChannelInfo->concealState = ConcealState_Ok;
+
+}
+
+
+/*!
+ \brief Set error concealment parameters
+
+ \concealParams
+ \method
+ \fadeOutSlope
+ \fadeInSlope
+ \muteRelease
+ \comfNoiseLevel
+
+ \return none
+*/
+AAC_DECODER_ERROR
+ CConcealment_SetParams (
+ CConcealParams *concealParams,
+ int method,
+ int fadeOutSlope,
+ int fadeInSlope,
+ int muteRelease,
+ int comfNoiseLevel )
+{
+ /* set concealment technique */
+ if (method != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
+ switch ((CConcealmentMethod)method)
+ {
+ case ConcealMethodMute:
+ case ConcealMethodNoise:
+ case ConcealMethodInter:
+ /* Be sure to enable delay adjustment of SBR decoder! */
+ if (concealParams == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ } else {
+ /* set param */
+ concealParams->method = (CConcealmentMethod)method;
+ }
+ break;
+
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+
+ /* set number of frames for fade-out slope */
+ if (fadeOutSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
+ if ( (fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS)
+ && (fadeOutSlope >= 0) )
+ {
+ if (concealParams == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ } else {
+ /* set param */
+ concealParams->numFadeOutFrames = fadeOutSlope;
+ }
+ } else {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+
+ /* set number of frames for fade-in slope */
+ if (fadeInSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
+ if ( (fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS)
+ && (fadeInSlope >= 1) )
+ {
+ if (concealParams == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ } else {
+ /* set param */
+ concealParams->numFadeInFrames = fadeInSlope;
+ }
+ } else {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+
+ /* set number of error-free frames after which the muting will be released */
+ if (muteRelease != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
+ if ( (muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS<<1))
+ && (muteRelease >= 0) )
+ {
+ if (concealParams == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ } else {
+ /* set param */
+ concealParams->numMuteReleaseFrames = muteRelease;
+ }
+ } else {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+
+ /* set confort noise level which will be inserted while in state 'muting' */
+ if (comfNoiseLevel != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
+ if ( (comfNoiseLevel < 0)
+ || (comfNoiseLevel > 127) ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (concealParams == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ } else {
+ concealParams->comfortNoiseLevel = comfNoiseLevel;
+ }
+ }
+
+ return (AAC_DEC_OK);
+}
+
+
+/*!
+ \brief Set fade-out/in attenuation factor vectors
+
+ \concealParams
+ \fadeOutAttenuationVector
+ \fadeInAttenuationVector
+
+ \return 0 if OK all other values indicate errors
+*/
+AAC_DECODER_ERROR
+ CConcealment_SetAttenuation (
+ CConcealParams *concealParams,
+ SHORT *fadeOutAttenuationVector,
+ SHORT *fadeInAttenuationVector )
+{
+ if ( (fadeOutAttenuationVector == NULL)
+ && (fadeInAttenuationVector == NULL) ) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+
+ /* Fade-out factors */
+ if (fadeOutAttenuationVector != NULL)
+ {
+ int i;
+
+ /* check quantized factors first */
+ for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
+ if ((fadeOutAttenuationVector[i] < 0) || (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+ if (concealParams == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+
+ /* now dequantize factors */
+ for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++)
+ {
+ concealParams->fadeOutFactor[i] =
+ FX_DBL2FX_SGL( fLdPow( CONCEAL_MIN_ATTENUATION_FACTOR_025_LD,
+ 0,
+ (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0/2.0)>>(CONCEAL_PARAMETER_BITS-1)) * (INT)fadeOutAttenuationVector[i]),
+ CONCEAL_PARAMETER_BITS
+ )
+ );
+ }
+ }
+
+ /* Fade-in factors */
+ if (fadeInAttenuationVector != NULL)
+ {
+ int i;
+
+ /* check quantized factors first */
+ for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
+ if ((fadeInAttenuationVector[i] < 0) || (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+ if (concealParams == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+
+ /* now dequantize factors */
+ for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++)
+ {
+ concealParams->fadeInFactor[i] =
+ FX_DBL2FX_SGL( fLdPow( CONCEAL_MIN_ATTENUATION_FACTOR_025_LD,
+ 0,
+ (FIXP_DBL)((INT)(FIXP_ONE>>CONCEAL_PARAMETER_BITS) * (INT)fadeInAttenuationVector[i]),
+ CONCEAL_PARAMETER_BITS
+ )
+ );
+ }
+ }
+
+ return (AAC_DEC_OK);
+}
+
+
+/*!
+ \brief Get state of concealment module.
+
+ \pConcealChannelInfo
+
+ \return Concealment state.
+*/
+CConcealmentState
+ CConcealment_GetState (
+ CConcealmentInfo *pConcealChannelInfo
+ )
+{
+ CConcealmentState state = ConcealState_Ok;
+
+ if (pConcealChannelInfo != NULL) {
+ state = pConcealChannelInfo->concealState;
+ }
+
+ return (state);
+}
+
+
+static void CConcealment_fakePnsData (
+ CPnsData *pPnsData,
+ CIcsInfo *pIcsInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ SHORT *pSpecScale,
+ SHORT *pScaleFactor,
+ const int level )
+{
+ CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
+
+ int pnsBand, band, group, win;
+ //int delta = 0;
+ int windowsPerFrame = GetWindowsPerFrame(pIcsInfo);
+ int refLevel = (windowsPerFrame > 1) ? 82 : 91;
+
+ FDK_ASSERT(level >= 0 && level <= 127);
+
+ for (win = 0; win < windowsPerFrame; win++) {
+ pSpecScale[win] = 31;
+ }
+
+ /* fake ICS info if necessary */
+ if (!IsValid(pIcsInfo)) {
+ pIcsInfo->WindowGroups = 1;
+ if (IsLongBlock(pIcsInfo)) {
+ pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
+ pIcsInfo->WindowGroupLength[0] = 1;
+ }
+ else {
+ pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
+ pIcsInfo->WindowGroupLength[0] = 8;
+ }
+ pIcsInfo->MaxSfBands = pIcsInfo->TotalSfBands;
+ }
+
+ /* global activate PNS */
+ pPnsData->PnsActive = 1;
+ /* set energy level */
+ pPnsData->CurrentEnergy = fixMax( 0, refLevel - level );
+
+ /*
+ value: | Avg. RMS power | Avg. RMS power |
+ | specScale = 22 | specScale = 31 |
+ -------+----------------+----------------+
+ 5 | | -99.0 dB
+ 15 | | -90.0 dB
+ 25 | | -89.7 dB
+ 35 | | -85.3 dB
+ ... | ... | ...
+ 45 | -69.9 dB | -70.0 dB
+ 50 | -62.2 dB |
+ 55 | -55.6 dB | -54.6 dB
+ 60 | -47.0 dB |
+ 65 | -39.5 dB | -39.5 dB
+ 70 | -31.9 dB |
+ 75 | -24.4 dB | -24.4 dB
+ 80 | -16.9 dB |
+ 85 | -9.4 dB (c) | -9.4 dB
+ 90 | -3.9 dB (c) |
+ 95 | | -2.1 dB
+ 100 | | -1.6 dB
+ 105 | | -1.4 dB
+ */
+
+ for (group=0; group < GetWindowGroups(pIcsInfo); group++)
+ {
+ for (band=0; band < GetScaleFactorBandsTransmitted(pIcsInfo); band++)
+ {
+ pnsBand = group * 16 + band;
+
+ if (pnsBand >= NO_OFBANDS) {
+ return;
+ }
+ //pPnsData->CurrentEnergy += delta ;
+ pScaleFactor[pnsBand] = pPnsData->CurrentEnergy;
+ pInterChannelData->correlated[pnsBand] = 0;
+ pPnsData->pnsUsed[pnsBand] = 1;
+ }
+ }
+}
+
+
+/*!
+ \brief Store data for concealment techniques applied later
+
+ Interface function to store data for different concealment strategies
+
+ \return none
+ */
+void
+ CConcealment_Store (
+ CConcealmentInfo *hConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo )
+{
+ if ( !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD
+ ) )
+ {
+ FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
+ SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+
+ SHORT tSpecScale[8];
+ UCHAR tWindowShape, tWindowSequence;
+
+ /* store old window infos for swapping */
+ tWindowSequence = hConcealmentInfo->windowSequence;
+ tWindowShape = hConcealmentInfo->windowShape;
+
+ /* store old scale factors for swapping */
+ FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8*sizeof(SHORT));
+
+ /* store new window infos */
+ hConcealmentInfo->windowSequence = GetWindowSequence(pIcsInfo);
+ hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo);
+ hConcealmentInfo->lastWinGrpLen = *(GetWindowGroupLengthTable(pIcsInfo)+GetWindowGroups(pIcsInfo)-1);
+
+ /* store new scale factors */
+ FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8*sizeof(SHORT));
+
+ if (CConcealment_GetDelay(hConcealmentInfo->pConcealParams) == 0)
+ {
+ /* store new spectral bins */
+#if (CNCL_FRACT_BITS == DFRACT_BITS)
+ FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL));
+#else
+ FIXP_CNCL *RESTRICT pCncl = &hConcealmentInfo->spectralCoefficient[1024-1];
+ FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024-1];
+ int i;
+
+ for (i = 1024; i != 0; i--) {
+ *pCncl-- = FX_DBL2FX_CNCL(*pSpec--);
+ }
+#endif
+ }
+ else
+ {
+ FIXP_CNCL *RESTRICT pCncl = &hConcealmentInfo->spectralCoefficient[1024-1];
+ FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024-1];
+ int i;
+
+ /* swap spectral data */
+ for (i = 1024; i != 0; i--) {
+ FIXP_DBL tSpec = *pSpec;
+ *pSpec-- = FX_CNCL2FX_DBL(*pCncl);
+ *pCncl-- = FX_DBL2FX_CNCL( tSpec);
+ }
+
+ /* complete swapping of window infos */
+ pIcsInfo->WindowSequence = tWindowSequence;
+ pIcsInfo->WindowShape = tWindowShape;
+
+ /* complete swapping of scale factors */
+ FDKmemcpy(pSpecScale, tSpecScale, 8*sizeof(SHORT));
+ }
+ }
+
+}
+
+
+/*!
+ \brief Apply concealment
+
+ Interface function to different concealment strategies
+
+ \return none
+ */
+int
+ CConcealment_Apply (
+ CConcealmentInfo *hConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int samplesPerFrame,
+ const UCHAR lastLpdMode,
+ const int frameOk,
+ const UINT flags)
+{
+ int appliedProcessing = 0;
+
+ if ( (frameOk == 0)
+ && (pAacDecoderChannelInfo->renderMode != (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode) ) {
+ /* restore the last render mode to stay in the same domain which allows to do a proper concealment */
+ pAacDecoderChannelInfo->renderMode = (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode;
+ } else {
+ /* otherwise store the current mode */
+ hConcealmentInfo->lastRenderMode = (SCHAR)pAacDecoderChannelInfo->renderMode;
+ }
+
+ if ( frameOk )
+ {
+ /* Rescue current data for concealment in future frames */
+ CConcealment_Store ( hConcealmentInfo,
+ pAacDecoderChannelInfo,
+ pAacDecoderStaticChannelInfo );
+ /* Reset index to random sign vector to make sign calculation frame agnostic
+ (only depends on number of subsequently concealed spectral blocks) */
+ hConcealmentInfo->iRandomPhase = 0;
+ }
+
+ /* hand current frame status to the state machine */
+ CConcealment_UpdateState( hConcealmentInfo,
+ frameOk );
+
+ if ( !frameOk )
+ {
+ /* Create data for signal rendering according to the selected concealment method and decoder operating mode. */
+
+
+ if ( !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD
+ )
+ )
+ {
+ switch (hConcealmentInfo->pConcealParams->method)
+ {
+ default:
+ case ConcealMethodMute:
+ /* Mute spectral data in case of errors */
+ FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
+ /* Set last window shape */
+ pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
+ appliedProcessing = 1;
+ break;
+
+ case ConcealMethodNoise:
+ /* Noise substitution error concealment technique */
+ appliedProcessing =
+ CConcealment_ApplyNoise (hConcealmentInfo,
+ pAacDecoderChannelInfo,
+ pAacDecoderStaticChannelInfo,
+ pSamplingRateInfo,
+ samplesPerFrame,
+ flags);
+ break;
+
+ case ConcealMethodInter:
+ /* Energy interpolation concealment based on 3GPP */
+ appliedProcessing =
+ CConcealment_ApplyInter (hConcealmentInfo,
+ pAacDecoderChannelInfo,
+ pSamplingRateInfo,
+ samplesPerFrame,
+ 0, /* don't use tonal improvement */
+ 0);
+ break;
+
+ }
+ }
+ }
+ /* update history */
+ hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1];
+ hConcealmentInfo->prevFrameOk[1] = frameOk;
+
+ return appliedProcessing;
+}
+
+/*!
+\brief Apply concealment noise substitution
+
+ In case of frame lost this function produces a noisy frame with respect to the
+ energies values of past frame.
+
+\return none
+ */
+static int
+ CConcealment_ApplyNoise (CConcealmentInfo *pConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int samplesPerFrame,
+ const UINT flags)
+{
+ CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
+
+ FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
+ SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+
+ int appliedProcessing = 0;
+
+ FDK_ASSERT((samplesPerFrame>=480) && (samplesPerFrame<=1024));
+ FDK_ASSERT((samplesPerFrame&0x1F) == 0);
+
+ switch (pConcealmentInfo->concealState)
+ {
+ case ConcealState_Ok:
+ /* Nothing to do here! */
+ break;
+
+ case ConcealState_Single:
+ case ConcealState_FadeOut:
+ {
+ /* restore frequency coefficients from buffer with a specific muting */
+ FIXP_SGL fac;
+ int win, numWindows = 1;
+ int windowLen = samplesPerFrame;
+ int tFadeFrames, lastWindow = 0;
+ int win_idx_stride = 1;
+
+ FDK_ASSERT(pConcealmentInfo != NULL);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames <= pConcealCommonData->numFadeOutFrames);
+
+ /* get attenuation factor */
+ tFadeFrames = pConcealmentInfo->cntFadeFrames;
+ fac = pConcealCommonData->fadeOutFactor[tFadeFrames];
+
+ /* set old window parameters */
+ {
+ pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
+ pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
+
+ if (pConcealmentInfo->windowSequence == 2) {
+ /* short block handling */
+ numWindows = 8;
+ windowLen = samplesPerFrame >> 3;
+ lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen;
+ }
+ }
+
+ for (win = 0; win < numWindows; win++) {
+ FIXP_CNCL *pCncl = pConcealmentInfo->spectralCoefficient + (lastWindow * windowLen);
+ FIXP_DBL *pOut = pSpectralCoefficient + (win * windowLen);
+ int i;
+
+ FDK_ASSERT((lastWindow * windowLen + windowLen) <= samplesPerFrame);
+
+ /* restore frequency coefficients from buffer with a specific attenuation */
+ for (i = 0; i < windowLen; i++) {
+ pOut[i] = fMult(pCncl[i], fac);
+ }
+
+ /* apply random change of sign for spectral coefficients */
+ CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase,
+ pOut,
+ windowLen );
+
+ /* Increment random phase index to avoid repetition artifacts. */
+ pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
+
+ /* set old scale factors */
+ pSpecScale[win*win_idx_stride] = pConcealmentInfo->specScale[win_idx_stride*lastWindow++];
+
+ if ( (lastWindow >= numWindows)
+ && (numWindows > 1) )
+ {
+ /* end of sequence -> rewind */
+ lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen;
+ /* update the attenuation factor to get a faster fade-out */
+ tFadeFrames += 1;
+ if (tFadeFrames < pConcealCommonData->numFadeOutFrames) {
+ fac = pConcealCommonData->fadeOutFactor[tFadeFrames];
+ } else {
+ fac = (FIXP_SGL)0;
+ }
+ }
+ }
+
+ /* store temp vars */
+ pConcealmentInfo->cntFadeFrames = tFadeFrames;
+ appliedProcessing = 1;
+ }
+ break;
+
+ case ConcealState_Mute:
+ {
+ /* set dummy window parameters */
+ pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
+ pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */
+ pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
+ pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */
+
+ /* mute spectral data */
+ FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
+
+ if ( !(flags & (AC_USAC|AC_RSVD50))
+ && pConcealCommonData->comfortNoiseLevel >= 0
+ && pConcealCommonData->comfortNoiseLevel <= 61 /* -90dB */)
+ {
+ /* insert comfort noise using PNS */
+ CConcealment_fakePnsData (
+ &pAacDecoderChannelInfo->data.aac.PnsData,
+ pIcsInfo,
+ pSamplingRateInfo,
+ pAacDecoderChannelInfo->pDynData->aSfbScale,
+ pAacDecoderChannelInfo->pDynData->aScaleFactor,
+ pConcealCommonData->comfortNoiseLevel
+ );
+
+ CPns_Apply (
+ &pAacDecoderChannelInfo->data.aac.PnsData,
+ pIcsInfo,
+ pAacDecoderChannelInfo->pSpectralCoefficient,
+ pAacDecoderChannelInfo->specScale,
+ pAacDecoderChannelInfo->pDynData->aScaleFactor,
+ pSamplingRateInfo,
+ pAacDecoderChannelInfo->granuleLength,
+ 0 /* always apply to first channel */
+ );
+ }
+ appliedProcessing = 1;
+ }
+ break;
+
+ case ConcealState_FadeIn:
+ {
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames);
+
+ /* attenuate signal to get a smooth fade-in */
+ FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1];
+ FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames];
+ int i;
+
+ for (i = samplesPerFrame; i != 0; i--) {
+ *pOut = fMult(*pOut, fac);
+ pOut--;
+ }
+ appliedProcessing = 1;
+ }
+ break;
+
+ default:
+ /* we shouldn't come here anyway */
+ FDK_ASSERT(0);
+ break;
+ }
+
+ return appliedProcessing;
+}
+
+
+/*!
+ \brief Apply concealment interpolation
+
+ The function swaps the data from the current and the previous frame. If an
+ error has occured, frame interpolation is performed to restore the missing
+ frame. In case of multiple faulty frames, fade-in and fade-out is applied.
+
+ \return none
+*/
+static int
+ CConcealment_ApplyInter (
+ CConcealmentInfo *pConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int samplesPerFrame,
+ const int improveTonal,
+ const int frameOk )
+{
+ CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
+
+ FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
+ CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
+ SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
+
+
+ int sfbEnergyPrev[64];
+ int sfbEnergyAct [64];
+
+ int i, appliedProcessing = 0;
+
+ /* clear/init */
+ FDKmemclear(sfbEnergyPrev, 64 * sizeof(int));
+ FDKmemclear(sfbEnergyAct, 64 * sizeof(int));
+
+
+ if (!frameOk)
+ {
+ /* Restore last frame from concealment buffer */
+ pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
+ pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
+
+ /* Restore spectral data */
+ for (i = 0; i < samplesPerFrame; i++) {
+ pSpectralCoefficient[i] = FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]);
+ }
+
+ /* Restore scale factors */
+ FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8*sizeof(SHORT));
+ }
+
+ /* if previous frame was not ok */
+ if (!pConcealmentInfo->prevFrameOk[1]) {
+
+ /* if current frame (f_n) is ok and the last but one frame (f_(n-2))
+ was ok, too, then interpolate both frames in order to generate
+ the current output frame (f_(n-1)). Otherwise, use the last stored
+ frame (f_(n-2) or f_(n-3) or ...). */
+ if (frameOk && pConcealmentInfo->prevFrameOk[0])
+ {
+ appliedProcessing = 1;
+
+
+ /* Interpolate both frames in order to generate the current output frame (f_(n-1)). */
+ if (pIcsInfo->WindowSequence == EightShortSequence) {
+ /* f_(n-2) == EightShortSequence */
+ /* short--??????--short, short--??????--long interpolation */
+ /* short--short---short, short---long---long interpolation */
+
+ int wnd;
+
+ if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */
+ /* short--short---short interpolation */
+
+ int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
+ const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
+ pIcsInfo->WindowShape = 1;
+ pIcsInfo->WindowSequence = EightShortSequence;
+
+ for (wnd = 0; wnd < 8; wnd++)
+ {
+ CConcealment_CalcBandEnergy(
+ &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-2) */
+ pSamplingRateInfo,
+ EightShortSequence,
+ CConcealment_NoExpand,
+ sfbEnergyPrev);
+
+ CConcealment_CalcBandEnergy(
+ &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_n */
+ pSamplingRateInfo,
+ EightShortSequence,
+ CConcealment_NoExpand,
+ sfbEnergyAct);
+
+ CConcealment_InterpolateBuffer(
+ &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-1) */
+ &pSpecScale[wnd],
+ &pConcealmentInfo->specScale[wnd],
+ &pSpecScale[wnd],
+ sfbEnergyPrev,
+ sfbEnergyAct,
+ scaleFactorBandsTotal,
+ pSfbOffset);
+
+ }
+ } else { /* f_n != EightShortSequence */
+ /* short---long---long interpolation */
+
+ int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
+ const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
+ SHORT specScaleOut;
+
+ CConcealment_CalcBandEnergy(&pSpectralCoefficient[samplesPerFrame - (samplesPerFrame / 8)], /* [wnd] spec_(n-2) */
+ pSamplingRateInfo,
+ EightShortSequence,
+ CConcealment_Expand,
+ sfbEnergyAct);
+
+ CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */
+ pSamplingRateInfo,
+ OnlyLongSequence,
+ CConcealment_NoExpand,
+ sfbEnergyPrev);
+
+ pIcsInfo->WindowShape = 0;
+ pIcsInfo->WindowSequence = LongStopSequence;
+
+ for (i = 0; i < samplesPerFrame ; i++) {
+ pSpectralCoefficient[i] = pConcealmentInfo->spectralCoefficient[i]; /* spec_n */
+ }
+
+ for (i = 0; i < 8; i++) { /* search for max(specScale) */
+ if (pSpecScale[i] > pSpecScale[0]) {
+ pSpecScale[0] = pSpecScale[i];
+ }
+ }
+
+ CConcealment_InterpolateBuffer(
+ pSpectralCoefficient, /* spec_(n-1) */
+ &pConcealmentInfo->specScale[0],
+ &pSpecScale[0],
+ &specScaleOut,
+ sfbEnergyPrev,
+ sfbEnergyAct,
+ scaleFactorBandsTotal,
+ pSfbOffset);
+
+ pSpecScale[0] = specScaleOut;
+ }
+ } else {
+ /* long--??????--short, long--??????--long interpolation */
+ /* long---long---short, long---long---long interpolation */
+
+ int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
+ const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
+ SHORT specScaleAct = pConcealmentInfo->specScale[0];
+
+ CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */
+ pSamplingRateInfo,
+ OnlyLongSequence,
+ CConcealment_NoExpand,
+ sfbEnergyPrev);
+
+ if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */
+ /* long---long---short interpolation */
+
+ pIcsInfo->WindowShape = 1;
+ pIcsInfo->WindowSequence = LongStartSequence;
+
+ for (i = 1; i < 8; i++) { /* search for max(specScale) */
+ if (pConcealmentInfo->specScale[i] > specScaleAct) {
+ specScaleAct = pConcealmentInfo->specScale[i];
+ }
+ }
+
+ /* Expand first short spectrum */
+ CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */
+ pSamplingRateInfo,
+ EightShortSequence,
+ CConcealment_Expand, /* !!! */
+ sfbEnergyAct);
+ } else {
+ /* long---long---long interpolation */
+
+ pIcsInfo->WindowShape = 0;
+ pIcsInfo->WindowSequence = OnlyLongSequence;
+
+ CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */
+ pSamplingRateInfo,
+ OnlyLongSequence,
+ CConcealment_NoExpand,
+ sfbEnergyAct);
+ }
+
+ CConcealment_InterpolateBuffer(
+ pSpectralCoefficient, /* spec_(n-1) */
+ &pSpecScale[0],
+ &specScaleAct,
+ &pSpecScale[0],
+ sfbEnergyPrev,
+ sfbEnergyAct,
+ scaleFactorBandsTotal,
+ pSfbOffset);
+
+ }
+ }
+
+ /* Noise substitution of sign of the output spectral coefficients */
+ CConcealment_ApplyRandomSign (pConcealmentInfo->iRandomPhase,
+ pSpectralCoefficient,
+ samplesPerFrame);
+ /* Increment random phase index to avoid repetition artifacts. */
+ pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
+ }
+
+ /* scale spectrum according to concealment state */
+ switch (pConcealmentInfo->concealState)
+ {
+ case ConcealState_Single:
+ appliedProcessing = 1;
+ break;
+
+ case ConcealState_FadeOut:
+ {
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeOutFrames);
+
+ /* restore frequency coefficients from buffer with a specific muting */
+ FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1];
+ FIXP_SGL fac = pConcealCommonData->fadeOutFactor[pConcealmentInfo->cntFadeFrames];
+
+ for (i = samplesPerFrame; i != 0; i--) {
+ *pOut = fMult(*pOut, fac);
+ pOut--;
+ }
+ appliedProcessing = 1;
+ }
+ break;
+
+ case ConcealState_FadeIn:
+ {
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
+ FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames);
+
+ /* attenuate signal to get a smooth fade-in */
+ FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1];
+ FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames];
+
+ for (i = samplesPerFrame; i != 0; i--) {
+ *pOut = fMult(*pOut, fac);
+ pOut--;
+ }
+ appliedProcessing = 1;
+ }
+ break;
+
+ case ConcealState_Mute:
+ {
+ int fac = pConcealCommonData->comfortNoiseLevel;
+
+ /* set dummy window parameters */
+ pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
+ pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */
+ pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
+ pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */
+
+ /* mute spectral data */
+ FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
+
+ if (fac >= 0 && fac <= 61) {
+ /* insert comfort noise using PNS */
+ CConcealment_fakePnsData (
+ &pAacDecoderChannelInfo->data.aac.PnsData,
+ pIcsInfo,
+ pSamplingRateInfo,
+ pAacDecoderChannelInfo->specScale,
+ pAacDecoderChannelInfo->pDynData->aScaleFactor,
+ fac
+ );
+
+ CPns_Apply (
+ &pAacDecoderChannelInfo->data.aac.PnsData,
+ pIcsInfo,
+ pAacDecoderChannelInfo->pSpectralCoefficient,
+ pAacDecoderChannelInfo->specScale,
+ pAacDecoderChannelInfo->pDynData->aScaleFactor,
+ pSamplingRateInfo,
+ pAacDecoderChannelInfo->granuleLength,
+ 0 /* always apply to first channel */
+ );
+ }
+ appliedProcessing = 1;
+ }
+ break;
+
+ default:
+ /* nothing to do here */
+ break;
+ }
+
+ return appliedProcessing;
+}
+
+
+/*!
+ \brief Calculate the spectral energy
+
+ The function calculates band-wise the spectral energy. This is used for
+ frame interpolation.
+
+ \return none
+*/
+static void
+ CConcealment_CalcBandEnergy (
+ FIXP_DBL *spectrum,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int blockType,
+ CConcealmentExpandType expandType,
+ int *sfbEnergy )
+{
+ const SHORT *pSfbOffset;
+ int line, sfb, scaleFactorBandsTotal = 0;
+
+ /* In the following calculations, enAccu is initialized with LSB-value in order to avoid zero energy-level */
+
+ line = 0;
+
+ switch(blockType) {
+
+ case OnlyLongSequence:
+ case LongStartSequence:
+ case LongStopSequence:
+
+ if (expandType == CConcealment_NoExpand) {
+ /* standard long calculation */
+ scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
+ pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
+
+ for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
+ FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
+ int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
+ /* scaling depends on sfb width. */
+ for ( ; line < pSfbOffset[sfb+1]; line++) {
+ enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
+ }
+ *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
+ }
+ }
+ else {
+ /* compress long to short */
+ scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
+ pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
+
+ for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
+ FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
+ int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
+ /* scaling depends on sfb width. */
+ for (; line < pSfbOffset[sfb+1] << 3; line++) {
+ enAccu += (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3;
+ }
+ *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
+ }
+ }
+ break;
+
+ case EightShortSequence:
+
+ if (expandType == CConcealment_NoExpand) {
+ /* standard short calculation */
+ scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
+ pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
+
+ for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
+ FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
+ int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
+ /* scaling depends on sfb width. */
+ for ( ; line < pSfbOffset[sfb+1]; line++) {
+ enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
+ }
+ *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
+ }
+ }
+ else {
+ /* expand short to long spectrum */
+ scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
+ pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
+
+ for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
+ FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
+ int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
+ /* scaling depends on sfb width. */
+ for ( ; line < pSfbOffset[sfb+1]; line++) {
+ enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale;
+ }
+ *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
+ }
+ }
+ break;
+ }
+}
+
+
+/*!
+ \brief Interpolate buffer
+
+ The function creates the interpolated spectral data according to the
+ energy of the last good frame and the current (good) frame.
+
+ \return none
+*/
+static void
+ CConcealment_InterpolateBuffer (
+ FIXP_DBL *spectrum,
+ SHORT *pSpecScalePrv,
+ SHORT *pSpecScaleAct,
+ SHORT *pSpecScaleOut,
+ int *enPrv,
+ int *enAct,
+ int sfbCnt,
+ const SHORT *pSfbOffset )
+{
+ int sfb, line = 0;
+ int fac_shift;
+ int fac_mod;
+ FIXP_DBL accu;
+
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+
+ fac_shift = enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1);
+ fac_mod = fac_shift & 3;
+ fac_shift = (fac_shift >> 2) + 1;
+ fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct);
+
+ for (; line < pSfbOffset[sfb+1]; line++) {
+ accu = fMult(*(spectrum+line), facMod4Table[fac_mod]);
+ if (fac_shift < 0) {
+ accu >>= -fac_shift;
+ } else {
+ accu <<= fac_shift;
+ }
+ *(spectrum+line) = accu;
+ }
+ }
+ *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct);
+}
+
+
+
+
+static INT findEquiFadeFrame (
+ CConcealParams *pConcealCommonData,
+ INT actFadeIndex,
+ int direction )
+{
+ FIXP_SGL *pFactor;
+ FIXP_SGL referenceVal;
+ FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL;
+
+ INT numFrames = 0;
+ INT nextFadeIndex = 0;
+
+ int i;
+
+ /* init depending on direction */
+ if (direction == 0) { /* FADE-OUT => FADE-IN */
+ numFrames = pConcealCommonData->numFadeInFrames;
+ referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1;
+ pFactor = pConcealCommonData->fadeInFactor;
+ }
+ else { /* FADE-IN => FADE-OUT */
+ numFrames = pConcealCommonData->numFadeOutFrames;
+ referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1;
+ pFactor = pConcealCommonData->fadeOutFactor;
+ }
+
+ /* search for minimum difference */
+ for (i = 0; i < numFrames; i++) {
+ FIXP_SGL diff = fixp_abs((pFactor[i]>>1) - referenceVal);
+ if (diff < minDiff) {
+ minDiff = diff;
+ nextFadeIndex = i;
+ }
+ }
+
+ /* check and adjust depending on direction */
+ if (direction == 0) { /* FADE-OUT => FADE-IN */
+ if (((pFactor[nextFadeIndex]>>1) <= referenceVal) && (nextFadeIndex > 0)) {
+ nextFadeIndex -= 1;
+ }
+ }
+ else { /* FADE-IN => FADE-OUT */
+ if (((pFactor[nextFadeIndex]>>1) >= referenceVal) && (nextFadeIndex < numFrames-1)) {
+ nextFadeIndex += 1;
+ }
+ }
+
+ return (nextFadeIndex);
+}
+
+
+/*!
+ \brief Update the concealment state
+
+ The function updates the state of the concealment state-machine. The
+ states are: mute, fade-in, fade-out, interpolate and frame-ok.
+
+ \return none
+*/
+static void
+ CConcealment_UpdateState (
+ CConcealmentInfo *pConcealmentInfo,
+ int frameOk )
+{
+ CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
+
+ switch (pConcealCommonData->method)
+ {
+ case ConcealMethodNoise:
+ {
+ if (pConcealmentInfo->concealState != ConcealState_Ok) {
+ /* count the valid frames during concealment process */
+ if (frameOk) {
+ pConcealmentInfo->cntValidFrames += 1;
+ } else {
+ pConcealmentInfo->cntValidFrames = 0;
+ }
+ }
+
+ /* -- STATE MACHINE for Noise Substitution -- */
+ switch (pConcealmentInfo->concealState)
+ {
+ case ConcealState_Ok:
+ if (!frameOk) {
+ /* change to state SINGLE-FRAME-LOSS */
+ pConcealmentInfo->concealState = ConcealState_Single;
+ pConcealmentInfo->cntFadeFrames = 0;
+ pConcealmentInfo->cntValidFrames = 0;
+ }
+ break;
+
+ case ConcealState_Single: /* Just a pre-stage before fade-out begins. Stay here only one frame! */
+ pConcealmentInfo->cntFadeFrames += 1;
+ if (frameOk) {
+ if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
+ /* change to state FADE-IN */
+ pConcealmentInfo->concealState = ConcealState_FadeIn;
+ pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
+ pConcealmentInfo->cntFadeFrames-1,
+ 0 /* FadeOut -> FadeIn */);
+ } else {
+ /* change to state OK */
+ pConcealmentInfo->concealState = ConcealState_Ok;
+ }
+ } else {
+ if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
+ /* change to state MUTE */
+ pConcealmentInfo->concealState = ConcealState_Mute;
+ } else {
+ /* change to state FADE-OUT */
+ pConcealmentInfo->concealState = ConcealState_FadeOut;
+ }
+ }
+ break;
+
+ case ConcealState_FadeOut:
+ pConcealmentInfo->cntFadeFrames += 1; /* used to address the fade-out factors */
+ if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
+ /* change to state FADE-IN */
+ pConcealmentInfo->concealState = ConcealState_FadeIn;
+ pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
+ pConcealmentInfo->cntFadeFrames-1,
+ 0 /* FadeOut -> FadeIn */);
+ } else {
+ if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
+ /* change to state MUTE */
+ pConcealmentInfo->concealState = ConcealState_Mute;
+ }
+ }
+ break;
+
+ case ConcealState_Mute:
+ if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
+ /* change to state FADE-IN */
+ pConcealmentInfo->concealState = ConcealState_FadeIn;
+ pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
+ }
+ break;
+
+ case ConcealState_FadeIn:
+ pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */
+ if (frameOk) {
+ if (pConcealmentInfo->cntFadeFrames < 0) {
+ /* change to state OK */
+ pConcealmentInfo->concealState = ConcealState_Ok;
+ }
+ } else {
+ /* change to state FADE-OUT */
+ pConcealmentInfo->concealState = ConcealState_FadeOut;
+ pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
+ pConcealmentInfo->cntFadeFrames+1,
+ 1 /* FadeIn -> FadeOut */);
+ }
+ break;
+
+ default:
+ FDK_ASSERT(0);
+ break;
+ }
+ }
+ break;
+
+ case ConcealMethodInter:
+ case ConcealMethodTonal:
+ {
+ if (pConcealmentInfo->concealState != ConcealState_Ok) {
+ /* count the valid frames during concealment process */
+ if ( pConcealmentInfo->prevFrameOk[1] ||
+ (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk) ) {
+ /* The frame is OK even if it can be estimated by the energy interpolation algorithm */
+ pConcealmentInfo->cntValidFrames += 1;
+ } else {
+ pConcealmentInfo->cntValidFrames = 0;
+ }
+ }
+
+ /* -- STATE MACHINE for energy interpolation -- */
+ switch (pConcealmentInfo->concealState)
+ {
+ case ConcealState_Ok:
+ if (!(pConcealmentInfo->prevFrameOk[1] ||
+ (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk))) {
+ /* Fade out only if the energy interpolation algorithm can not be applied! */
+ pConcealmentInfo->concealState = ConcealState_FadeOut;
+ pConcealmentInfo->cntFadeFrames = 0;
+ pConcealmentInfo->cntValidFrames = 0;
+ }
+ break;
+
+ case ConcealState_Single:
+ pConcealmentInfo->concealState = ConcealState_Ok;
+ break;
+
+ case ConcealState_FadeOut:
+ pConcealmentInfo->cntFadeFrames += 1;
+
+ if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
+ /* change to state FADE-IN */
+ pConcealmentInfo->concealState = ConcealState_FadeIn;
+ pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
+ pConcealmentInfo->cntFadeFrames-1,
+ 0 /* FadeOut -> FadeIn */);
+ } else {
+ if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
+ /* change to state MUTE */
+ pConcealmentInfo->concealState = ConcealState_Mute;
+ }
+ }
+ break;
+
+ case ConcealState_Mute:
+ if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
+ /* change to state FADE-IN */
+ pConcealmentInfo->concealState = ConcealState_FadeIn;
+ pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
+ }
+ break;
+
+ case ConcealState_FadeIn:
+ pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */
+
+ if (frameOk || pConcealmentInfo->prevFrameOk[1]) {
+ if (pConcealmentInfo->cntFadeFrames < 0) {
+ /* change to state OK */
+ pConcealmentInfo->concealState = ConcealState_Ok;
+ }
+ } else {
+ /* change to state FADE-OUT */
+ pConcealmentInfo->concealState = ConcealState_FadeOut;
+ pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
+ pConcealmentInfo->cntFadeFrames+1,
+ 1 /* FadeIn -> FadeOut */);
+ }
+ break;
+ } /* End switch(pConcealmentInfo->concealState) */
+ }
+ break;
+
+ default:
+ /* Don't need a state machine for other concealment methods. */
+ break;
+ }
+
+}
+
+
+/*!
+\brief Randomizes the sign of the spectral data
+
+ The function toggles the sign of the spectral data randomly. This is
+ useful to ensure the quality of the concealed frames.
+
+\return none
+ */
+static
+void CConcealment_ApplyRandomSign (int randomPhase,
+ FIXP_DBL *spec,
+ int samplesPerFrame
+ )
+{
+ int i;
+ USHORT packedSign=0;
+
+ /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit */
+
+ /* read current packed sign word */
+ packedSign = randomSign[randomPhase>>4];
+ packedSign >>= (randomPhase&0xf);
+
+ for (i = 0; i < samplesPerFrame ; i++) {
+ if ((randomPhase & 0xf) == 0) {
+ packedSign = randomSign[randomPhase>>4];
+ }
+
+ if (packedSign & 0x1) {
+ spec[i] = -spec[i];
+ }
+ packedSign >>= 1;
+
+ randomPhase = (randomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
+ }
+}
+
+
+/*!
+ \brief Get fadeing factor for current concealment state.
+
+ The function returns the factor used for fading that belongs to the current internal state.
+
+ \return Fade factor
+ */
+FIXP_DBL
+ CConcealment_GetFadeFactor (
+ CConcealmentInfo *hConcealmentInfo,
+ const int fPreviousFactor
+ )
+{
+ FIXP_DBL fac = (FIXP_DBL)0;
+
+ CConcealParams *pConcealCommonData = hConcealmentInfo->pConcealParams;
+
+ if (hConcealmentInfo->pConcealParams->method > ConcealMethodMute) {
+ switch (hConcealmentInfo->concealState) {
+ default:
+ case ConcealState_Mute:
+ /* Nothing to do here */
+ break;
+ case ConcealState_Ok:
+ fac = (FIXP_DBL)MAXVAL_DBL;
+ break;
+ case ConcealState_Single:
+ case ConcealState_FadeOut:
+ {
+ int idx = hConcealmentInfo->cntFadeFrames - ((fPreviousFactor != 0) ? 1 : 0);
+ fac = (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(pConcealCommonData->fadeOutFactor[idx]);
+ }
+ break;
+ case ConcealState_FadeIn:
+ {
+ int idx = hConcealmentInfo->cntFadeFrames + ((fPreviousFactor != 0) ? 1 : 0);
+ fac = (idx >= hConcealmentInfo->pConcealParams->numFadeInFrames) ? (FIXP_DBL)0 : FX_SGL2FX_DBL(pConcealCommonData->fadeInFactor[idx]);
+ }
+ break;
+ }
+ }
+
+ return (fac);
+}
+
+
+/*!
+ \brief Get fadeing factor for current concealment state.
+
+ The function returns the state (ok or not) of the previous frame.
+ If called before the function CConcealment_Apply() set the fBeforeApply
+ flag to get the correct value.
+
+ \return Frame OK flag of previous frame.
+ */
+int
+ CConcealment_GetLastFrameOk (
+ CConcealmentInfo *hConcealmentInfo,
+ const int fBeforeApply
+ )
+{
+ int prevFrameOk = 1;
+
+ if (hConcealmentInfo != NULL) {
+ prevFrameOk = hConcealmentInfo->prevFrameOk[fBeforeApply & 0x1];
+ }
+
+ return prevFrameOk;
+}
+
+/*!
+ \brief Get the number of delay frames introduced by concealment technique.
+
+ \return Number of delay frames.
+ */
+UINT
+ CConcealment_GetDelay (
+ CConcealParams *pConcealCommonData
+ )
+{
+ UINT frameDelay = 0;
+
+ if (pConcealCommonData != NULL) {
+ switch (pConcealCommonData->method) {
+ case ConcealMethodTonal:
+ case ConcealMethodInter:
+ frameDelay = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return frameDelay;
+}
+
diff --git a/libAACdec/src/conceal.h b/libAACdec/src/conceal.h
new file mode 100644
index 0000000..95736b9
--- /dev/null
+++ b/libAACdec/src/conceal.h
@@ -0,0 +1,86 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: independent channel concealment
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef _CONCEAL_H_
+#define _CONCEAL_H_
+
+#include "aacdecoder_lib.h"
+
+#include "channelinfo.h"
+
+#define AACDEC_CONCEAL_PARAM_NOT_SPECIFIED ( 0xFFFE )
+
+void CConcealment_InitCommonData (CConcealParams *pConcealCommonData);
+
+void CConcealment_InitChannelData (CConcealmentInfo *hConcealmentInfo,
+ CConcealParams *pConcealCommonData,
+ int samplesPerFrame);
+
+CConcealmentMethod
+ CConcealment_GetMethod (CConcealParams *pConcealCommonData);
+
+UINT
+ CConcealment_GetDelay (CConcealParams *pConcealCommonData);
+
+AAC_DECODER_ERROR
+ CConcealment_SetParams (CConcealParams *concealParams,
+ int method,
+ int fadeOutSlope,
+ int fadeInSlope,
+ int muteRelease,
+ int comfNoiseLevel);
+
+CConcealmentState
+ CConcealment_GetState (CConcealmentInfo *hConcealmentInfo);
+
+AAC_DECODER_ERROR
+ CConcealment_SetAttenuation (CConcealParams *concealParams,
+ SHORT *fadeOutAttenuationVector,
+ SHORT *fadeInAttenuationVector);
+
+void CConcealment_Store (CConcealmentInfo *hConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo );
+
+int CConcealment_Apply (CConcealmentInfo *hConcealmentInfo,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ const SamplingRateInfo *pSamplingRateInfo,
+ const int samplesPerFrame,
+ const UCHAR lastLpdMode,
+ const int FrameOk,
+ const UINT flags);
+
+FIXP_DBL
+ CConcealment_GetFadeFactor (CConcealmentInfo *hConcealmentInfo,
+ const int fPreviousFactor);
+
+int CConcealment_GetLastFrameOk (CConcealmentInfo *hConcealmentInfo,
+ const int fBeforeApply);
+
+#endif /* #ifndef _CONCEAL_H_ */
diff --git a/libAACdec/src/conceal_types.h b/libAACdec/src/conceal_types.h
new file mode 100644
index 0000000..5b5eb81
--- /dev/null
+++ b/libAACdec/src/conceal_types.h
@@ -0,0 +1,116 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Christian Griebel
+ Description: Error concealment structs and types
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef CONCEAL_TYPES_H
+#define CONCEAL_TYPES_H
+
+
+
+#include "machine_type.h"
+#include "common_fix.h"
+
+#include "rvlc_info.h"
+
+
+#define CONCEAL_MAX_NUM_FADE_FACTORS ( 16 )
+
+ #define FIXP_CNCL FIXP_DBL
+ #define FL2FXCONST_CNCL FL2FXCONST_DBL
+ #define FX_DBL2FX_CNCL
+ #define FX_CNCL2FX_DBL
+ #define CNCL_FRACT_BITS DFRACT_BITS
+
+/* Warning: Do not ever change these values. */
+typedef enum
+{
+ ConcealMethodNone = -1,
+ ConcealMethodMute = 0,
+ ConcealMethodNoise = 1,
+ ConcealMethodInter = 2,
+ ConcealMethodTonal = 3
+
+} CConcealmentMethod;
+
+
+typedef enum
+{
+ ConcealState_Ok,
+ ConcealState_Single,
+ ConcealState_FadeIn,
+ ConcealState_Mute,
+ ConcealState_FadeOut
+
+} CConcealmentState;
+
+
+typedef struct
+{
+ FIXP_SGL fadeOutFactor[CONCEAL_MAX_NUM_FADE_FACTORS];
+ FIXP_SGL fadeInFactor [CONCEAL_MAX_NUM_FADE_FACTORS];
+
+ CConcealmentMethod method;
+
+ int numFadeOutFrames;
+ int numFadeInFrames;
+ int numMuteReleaseFrames;
+ int comfortNoiseLevel;
+
+} CConcealParams;
+
+
+
+typedef struct
+{
+ CConcealParams *pConcealParams;
+
+ FIXP_CNCL spectralCoefficient[1024];
+ SHORT specScale[8];
+
+ INT iRandomPhase;
+ INT prevFrameOk[2];
+ INT cntFadeFrames;
+ INT cntValidFrames;
+
+ SHORT aRvlcPreviousScaleFactor[RVLC_MAX_SFB]; /* needed once per channel */
+ UCHAR aRvlcPreviousCodebook[RVLC_MAX_SFB]; /* needed once per channel */
+ SCHAR rvlcPreviousScaleFactorOK;
+ SCHAR rvlcPreviousBlockType;
+
+
+ SCHAR lastRenderMode;
+
+ UCHAR windowShape;
+ UCHAR windowSequence;
+ UCHAR lastWinGrpLen;
+
+ CConcealmentState concealState;
+
+} CConcealmentInfo;
+
+
+#endif /* #ifndef CONCEAL_TYPES_H */
diff --git a/libAACdec/src/debug.h b/libAACdec/src/debug.h
new file mode 100644
index 0000000..8f57d80
--- /dev/null
+++ b/libAACdec/src/debug.h
@@ -0,0 +1,35 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: debug output
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include "machine_type.h"
+
+
+#endif
diff --git a/libAACdec/src/ldfiltbank.cpp b/libAACdec/src/ldfiltbank.cpp
new file mode 100644
index 0000000..7a59926
--- /dev/null
+++ b/libAACdec/src/ldfiltbank.cpp
@@ -0,0 +1,148 @@
+/***************************************************************************\
+ *
+ * (C) copyright Fraunhofer - IIS (2006)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+*
+ * filename: ldfiltbank.c
+ * project : MPEG-4 Audio Decoder
+ * contents/description: low delay filterbank
+ *
+ * This software and/or program is protected by copyright law and
+ * international treaties. Any reproduction or distribution of this
+ * software and/or program, or any portion of it, may result in severe
+ * civil and criminal penalties, and will be prosecuted to the maximum
+ * extent possible under law.
+ *
+ * $Id$
+ *
+\***************************************************************************/
+
+#include "ldfiltbank.h"
+
+
+#include "aac_rom.h"
+#include "dct.h"
+#include "FDK_tools_rom.h"
+#include "mdct.h"
+
+#define LDFB_HEADROOM 2
+
+static void multE2_DinvF_fdk(INT_PCM *output, FIXP_DBL* x, const FIXP_WTB* fb, FIXP_DBL* z, const int N, const int stride)
+{
+ int i, scale;
+
+ /* scale for FIXP_DBL -> INT_PCM conversion. */
+ scale = (DFRACT_BITS - SAMPLE_BITS) - LDFB_HEADROOM;
+
+ for(i=0;i<N/4;i++)
+ {
+ FIXP_DBL z0, z2, tmp;
+
+ z2 = x[N/2+i];
+ z0 = z2 + ( fMultDiv2(z[N/2+i], fb[2*N + i]) >> (-WTS2-1) );
+
+ z[N/2+i] = x[N/2-1-i] + ( fMultDiv2(z[N + i], fb[2*N + N/2 + i]) >> (-WTS2-1) );
+
+ tmp = ( fMultDiv2(z[N/2+i], fb[N+N/2-1-i]) + fMultDiv2(z[i], fb[N+N/2+i]) ) ;
+
+#if (SAMPLE_BITS <= 16)
+ FDK_ASSERT( (-WTS1-1 + scale) >= 0);
+ output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp, -WTS1-1 + scale, SAMPLE_BITS);
+#else
+ FDK_ASSERT( (WTS1+1 - scale) >= 0);
+ output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp, WTS1+1 - scale, SAMPLE_BITS);
+#endif
+
+ z[i] = z0;
+ z[N + i] = z2;
+ }
+
+ for(i=N/4;i<N/2;i++)
+ {
+ FIXP_DBL z0, z2, tmp0, tmp1;
+
+ z2 = x[N/2+i];
+ z0 = z2 + ( fMultDiv2(z[N/2+i], fb[2*N + i]) >> (-WTS2-1) );
+
+ z[N/2+i] = x[N/2-1-i] + ( fMultDiv2(z[N + i], fb[2*N + N/2 + i]) >> (-WTS2-1) );
+
+ tmp0 = ( fMultDiv2(z[N/2+i], fb[N/2-1-i]) + fMultDiv2(z[i], fb[N/2+i]) ) ;
+ tmp1 = ( fMultDiv2(z[N/2+i], fb[N+N/2-1-i]) + fMultDiv2(z[i], fb[N+N/2+i]) ) ;
+
+#if (SAMPLE_BITS <= 16)
+ FDK_ASSERT( (-WTS0-1 + scale) >= 0);
+ output[(i-N/4)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp0, -WTS0-1 + scale, SAMPLE_BITS);
+ output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp1, -WTS1-1 + scale, SAMPLE_BITS);
+#else
+ FDK_ASSERT( (WTS0+1 - scale) >= 0);
+ output[(i-N/4)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0+1 - scale, SAMPLE_BITS);
+ output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp1, WTS1+1 - scale, SAMPLE_BITS);
+#endif
+ z[i] = z0;
+ z[N + i] = z2;
+ }
+
+ /* Exchange quarter parts of x to bring them in the "right" order */
+ for(i=0;i<N/4;i++)
+ {
+ FIXP_DBL tmp0 = fMultDiv2(z[i], fb[N/2+i]);
+
+#if (SAMPLE_BITS <= 16)
+ FDK_ASSERT( (-WTS0-1 + scale) >= 0);
+ output[(N*3/4 + i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp0, -WTS0-1 + scale, SAMPLE_BITS);
+#else
+ FDK_ASSERT( (WTS0+1 - scale) >= 0);
+ output[(N*3/4 + i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0+1 - scale, SAMPLE_BITS);
+#endif
+ }
+}
+
+int InvMdctTransformLowDelay_fdk (FIXP_DBL *mdctData, const int mdctData_e, INT_PCM *output, FIXP_DBL *fs_buffer, const int stride, const int N) {
+
+ const FIXP_WTB *coef;
+ FIXP_DBL gain = (FIXP_DBL)0;
+ int scale = mdctData_e + MDCT_OUT_HEADROOM - LDFB_HEADROOM; /* The LDFB_HEADROOM is compensated inside multE2_DinvF_fdk() below */
+
+ /* Select LD window slope */
+ if (N == 512)
+ coef = (FIXP_WTB*)LowDelaySynthesis512;
+ else
+ coef = (FIXP_WTB*)LowDelaySynthesis480;
+
+ /*
+ Apply exponent and 1/N factor.
+ Note: "scale" is off by one because for LD_MDCT the window length is twice
+ the window length of a regular MDCT. This is corrected inside multE2_DinvF_fdk().
+ Refer to ISO/IEC 14496-3:2009 page 277, chapter 4.6.20.2 "Low Delay Window".
+ */
+ imdct_gain(&gain, &scale, N);
+
+ dct_IV(mdctData, N, &scale);
+
+ if (gain != (FIXP_DBL)0) {
+ scaleValuesWithFactor(mdctData, gain, N, scale);
+ } else {
+ scaleValues(mdctData, N, scale);
+ }
+
+ /* Since all exponent and factors have been applied, current exponent is zero. */
+ multE2_DinvF_fdk(output, mdctData, coef, fs_buffer, N, stride);
+
+ return (1);
+}
+
+
+
+
diff --git a/libAACdec/src/ldfiltbank.h b/libAACdec/src/ldfiltbank.h
new file mode 100644
index 0000000..2eee093
--- /dev/null
+++ b/libAACdec/src/ldfiltbank.h
@@ -0,0 +1,48 @@
+/***************************************************************************\
+ *
+ * (C) copyright Fraunhofer - IIS (2006)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+*
+ * filename: ldfiltbank.h
+ * project : MPEG-4 Audio Decoder
+ * contents/description: low delay filterbank interface
+ *
+ * This software and/or program is protected by copyright law and
+ * international treaties. Any reproduction or distribution of this
+ * software and/or program, or any portion of it, may result in severe
+ * civil and criminal penalties, and will be prosecuted to the maximum
+ * extent possible under law.
+ *
+ * $Header: /home/cvs/amm/menc/mp4objdec/src/aac_eld/ldfiltbank.h,v 1.3 2006/11/07 22:21:27 haertlml Exp $
+ *
+\***************************************************************************/
+
+#ifndef _LDFILTBANK_H
+#define _LDFILTBANK_H
+
+#include "common_fix.h"
+
+
+int InvMdctTransformLowDelay_fdk (
+ FIXP_DBL *mdctdata_m,
+ const int mdctdata_e,
+ INT_PCM *mdctOut,
+ FIXP_DBL *fs_buffer,
+ const int stride,
+ const int frameLength
+ );
+
+
+#endif
diff --git a/libAACdec/src/overlapadd.h b/libAACdec/src/overlapadd.h
new file mode 100644
index 0000000..b301888
--- /dev/null
+++ b/libAACdec/src/overlapadd.h
@@ -0,0 +1,43 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description:
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef OVERLAPADD_H
+#define OVERLAPADD_H
+
+#include "common_fix.h"
+
+#define OverlapBufferSize (1024*2)
+
+typedef FIXP_DBL SPECTRUM[1024];
+typedef FIXP_DBL * SPECTRAL_PTR;
+
+#define SPEC_LONG(ptr) (ptr)
+#define SPEC(ptr,w,gl) ((ptr)+((w)*(gl)))
+
+
+#endif /* #ifndef OVERLAPADD_H */
diff --git a/libAACdec/src/pulsedata.cpp b/libAACdec/src/pulsedata.cpp
new file mode 100644
index 0000000..062437a
--- /dev/null
+++ b/libAACdec/src/pulsedata.cpp
@@ -0,0 +1,96 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: pulse data tool
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "pulsedata.h"
+
+
+#include "channelinfo.h"
+
+
+INT CPulseData_Read(
+ HANDLE_FDK_BITSTREAM bs,
+ CPulseData *const PulseData,
+ const SHORT *sfb_startlines,
+ const void *pIcsInfo,
+ const SHORT frame_length
+ )
+{
+ int i, k=0;
+ const UINT MaxSfBands = GetScaleFactorBandsTransmitted((CIcsInfo*)pIcsInfo);
+
+ /* reset pulse data flag */
+ PulseData->PulseDataPresent = 0;
+
+ if ((PulseData->PulseDataPresent = (UCHAR) FDKreadBit(bs)) != 0) {
+ if (!IsLongBlock((CIcsInfo*)pIcsInfo)) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+
+ PulseData->NumberPulse = (UCHAR) FDKreadBits(bs,2);
+ PulseData->PulseStartBand = (UCHAR) FDKreadBits(bs,6);
+
+ if (PulseData->PulseStartBand >= MaxSfBands) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+
+ k = sfb_startlines[PulseData->PulseStartBand];
+
+ for (i=0; i<=PulseData->NumberPulse; i++) {
+ PulseData->PulseOffset[i] = (UCHAR) FDKreadBits(bs,5);
+ PulseData->PulseAmp[i] = (UCHAR) FDKreadBits(bs,4);
+ k += PulseData->PulseOffset[i];
+ }
+
+ if (k >= frame_length) {
+ return AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ }
+
+
+ return 0;
+}
+
+void CPulseData_Apply(CPulseData *PulseData, /*!< pointer to pulse data side info */
+ const short *pScaleFactorBandOffsets, /*!< pointer to scalefactor band offsets */
+ FIXP_DBL *coef) /*!< pointer to spectrum */
+{
+ int i,k;
+
+ if (PulseData->PulseDataPresent)
+ {
+ k = pScaleFactorBandOffsets[PulseData->PulseStartBand];
+
+ for (i=0; i<=PulseData->NumberPulse; i++)
+ {
+ k += PulseData->PulseOffset[i];
+ if (coef [k] > (FIXP_DBL)0) coef[k] += (FIXP_DBL)(int)PulseData->PulseAmp[i];
+ else coef[k] -= (FIXP_DBL)(int)PulseData->PulseAmp[i];
+ }
+ }
+}
+
diff --git a/libAACdec/src/pulsedata.h b/libAACdec/src/pulsedata.h
new file mode 100644
index 0000000..075a0c4
--- /dev/null
+++ b/libAACdec/src/pulsedata.h
@@ -0,0 +1,83 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: pulse data tool
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef PULSEDATA_H
+#define PULSEDATA_H
+
+
+
+#include "common_fix.h"
+#include "FDK_bitstream.h"
+
+#define N_MAX_LINES 4
+
+typedef struct
+{
+ UCHAR PulseDataPresent;
+ UCHAR NumberPulse;
+ UCHAR PulseStartBand;
+ UCHAR PulseOffset[N_MAX_LINES];
+ UCHAR PulseAmp[N_MAX_LINES];
+} CPulseData;
+
+/**
+ * \brief Read pulse data from bitstream
+ *
+ * The function reads the elements for pulse data from
+ * the bitstream.
+ *
+ * \param bs bit stream handle data source.
+ * \param PulseData pointer to a CPulseData were the decoded data is stored into.
+ * \param MaxSfBands max number of scale factor bands.
+ * \return 0 on success, != 0 on parse error.
+ */
+INT CPulseData_Read(
+ const HANDLE_FDK_BITSTREAM bs,
+ CPulseData *const PulseData,
+ const SHORT *sfb_startlines,
+ const void *pIcsInfo,
+ const SHORT frame_length
+ );
+
+/**
+ * \brief Apply pulse data to spectral lines
+ *
+ * The function applies the pulse data to the
+ * specified spectral lines.
+ *
+ * \param PulseData pointer to the previously decoded pulse data.
+ * \param pScaleFactorBandOffsets scale factor band line offset table.
+ * \param coef pointer to the spectral data were pulse data should be applied to.
+ * \return none
+*/
+void CPulseData_Apply(CPulseData *PulseData,
+ const short *pScaleFactorBandOffsets,
+ FIXP_DBL *coef);
+
+
+#endif /* #ifndef PULSEDATA_H */
diff --git a/libAACdec/src/rvlc.cpp b/libAACdec/src/rvlc.cpp
new file mode 100644
index 0000000..f2c6203
--- /dev/null
+++ b/libAACdec/src/rvlc.cpp
@@ -0,0 +1,1157 @@
+/****************************************************************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+ $Id$
+
+****************************************************************************/
+/*!
+ \file
+ \brief RVLC Decoder
+ \author Robert Weidner
+*/
+
+#include "rvlc.h"
+
+
+#include "block.h"
+
+#include "aac_rom.h"
+#include "rvlcbit.h"
+#include "rvlcconceal.h"
+#include "aacdec_hcr.h"
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcInit
+
+ description: init RVLC by data from channelinfo, which was decoded previously and
+ set up pointers
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - pointer bitstream structure
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static
+void rvlcInit (CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ /* RVLC common initialization part 2 of 2 */
+ SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
+ SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd;
+ SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
+ SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
+ int bnds;
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = 0;
+
+ pRvlc->numDecodedEscapeWordsEsc = 0;
+ pRvlc->numDecodedEscapeWordsFwd = 0;
+ pRvlc->numDecodedEscapeWordsBwd = 0;
+
+ pRvlc->intensity_used = 0;
+ pRvlc->errorLogRvlc = 0;
+
+ pRvlc->conceal_max = CONCEAL_MAX_INIT;
+ pRvlc->conceal_min = CONCEAL_MIN_INIT;
+
+ pRvlc->conceal_max_esc = CONCEAL_MAX_INIT;
+ pRvlc->conceal_min_esc = CONCEAL_MIN_INIT;
+
+ pRvlc->pHuffTreeRvlcEscape = aHuffTreeRvlcEscape;
+ pRvlc->pHuffTreeRvlCodewds = aHuffTreeRvlCodewds;
+
+ /* init scf arrays (for savety (in case of there are only zero codebooks)) */
+ for (bnds = 0; bnds < RVLC_MAX_SFB; bnds++) {
+ pScfFwd[bnds] = 0;
+ pScfBwd[bnds] = 0;
+ pScfEsc[bnds] = 0;
+ pScaleFactor[bnds] = 0;
+ }
+
+ /* set base bitstream ptr to the RVL-coded part (start of RVLC data (ESC 2)) */
+ FDKsyncCache (bs);
+
+ pRvlc->bitstreamIndexRvlFwd = FDKgetBitCnt(bs); /* first bit within RVL coded block as start address for forward decoding */
+ pRvlc->bitstreamIndexRvlBwd = FDKgetBitCnt(bs) + pRvlc->length_of_rvlc_sf - 1; /* last bit within RVL coded block as start address for backward decoding */
+
+ /* skip RVLC-bitstream-part -- pointing now to escapes (if present) or to TNS data (if present) */
+ FDKpushFor (bs, pRvlc->length_of_rvlc_sf);
+
+ if ( pRvlc->sf_escapes_present != 0 ) {
+
+ /* locate internal bitstream ptr at escapes (which is the second part) */
+ FDKsyncCache (bs);
+ pRvlc->bitstreamIndexEsc = FDKgetBitCnt(bs);
+
+ /* skip escapeRVLC-bitstream-part -- pointing to TNS data (if present) to make decoder continue */
+ /* decoding of RVLC should work despite this second pushFor during initialization because */
+ /* bitstream initialization is valid for both ESC2 data parts (RVL-coded values and ESC-coded values) */
+ FDKpushFor (bs, pRvlc->length_of_rvlc_escapes);
+ }
+
+#if VERBOSE_RVLC_INIT
+ DebugOutputInit(pRvlc,pAacDecoderChannelInfo);
+#endif
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcCheckIntensityCb
+
+ description: Check if a intensity codebook is used in the current channel.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+-----------------------------------------------------------------------------------------------
+ output: - intensity_used: 0 no intensity codebook is used
+ 1 intensity codebook is used
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static
+void rvlcCheckIntensityCb (CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo)
+{
+ int group, band, bnds;
+
+ pRvlc->intensity_used = 0;
+
+ for (group=0; group < pRvlc->numWindowGroups; group++) {
+ for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ if ( (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == INTENSITY_HCB) || (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == INTENSITY_HCB2) ) {
+ pRvlc->intensity_used = 1;
+ break;
+ }
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeEscapeWord
+
+ description: Decode a huffman coded RVLC Escape-word. This value is part of a DPCM coded
+ scalefactor.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+-----------------------------------------------------------------------------------------------
+ return: - a single RVLC-Escape value which had to be applied to a DPCM value (which
+ has a absolute value of 7)
+-------------------------------------------------------------------------------------------- */
+
+static
+SCHAR rvlcDecodeEscapeWord (CErRvlcInfo *pRvlc,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ int i;
+ SCHAR value;
+ UCHAR carryBit;
+ UINT treeNode;
+ UINT branchValue;
+ UINT branchNode;
+
+ USHORT* pBitstreamIndexEsc;
+ const UINT* pEscTree;
+
+ pEscTree = pRvlc->pHuffTreeRvlcEscape;
+ pBitstreamIndexEsc = &(pRvlc->bitstreamIndexEsc);
+ treeNode = *pEscTree; /* init at starting node */
+
+ for (i=MAX_LEN_RVLC_ESCAPE_WORD-1; i >= 0; i--) {
+ carryBit = rvlcReadBitFromBitstream(bs, /* get next bit */
+ pBitstreamIndexEsc,
+ FWD);
+
+ CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in huffman decoding tree */
+ treeNode,
+ &branchValue,
+ &branchNode);
+
+ if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-escape-word is completely decoded */
+ value = (SCHAR) branchNode & CLR_BIT_10;
+ pRvlc->length_of_rvlc_escapes -= (MAX_LEN_RVLC_ESCAPE_WORD - i);
+
+ if (pRvlc->length_of_rvlc_escapes < 0) {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
+ value = -1;
+ }
+
+ return value;
+ }
+ else {
+ treeNode = *(pEscTree + branchValue); /* update treeNode for further step in decoding tree */
+ }
+ }
+
+ pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
+
+ return -1; /* should not be reached */
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeEscapes
+
+ description: Decodes all huffman coded RVLC Escape Words.
+ Here a difference to the pseudo-code-implementation from standard can be
+ found. A while loop (and not two nested for loops) is used for two reasons:
+
+ 1. The plain huffman encoded escapes are decoded before the RVL-coded
+ scalefactors. Therefore the escapes are present in the second step
+ when decoding the RVL-coded-scalefactor values in forward and
+ backward direction.
+
+ When the RVL-coded scalefactors are decoded and there a escape is
+ needed, then it is just taken out of the array in ascending order.
+
+ 2. It's faster.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - handle to FDK bitstream
+-----------------------------------------------------------------------------------------------
+ return: - 0 ok the decoded escapes seem to be valid
+ - 1 error there was a error detected during decoding escapes
+ --> all escapes are invalid
+-------------------------------------------------------------------------------------------- */
+
+static
+void rvlcDecodeEscapes (CErRvlcInfo *pRvlc,
+ SHORT *pEsc,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ SCHAR escWord;
+ SCHAR escCnt=0;
+ SHORT* pEscBitCntSum;
+
+ pEscBitCntSum = &(pRvlc->length_of_rvlc_escapes);
+
+ /* Decode all RVLC-Escape words with a plain Huffman-Decoder */
+ while ( *pEscBitCntSum > 0 ) {
+ escWord = rvlcDecodeEscapeWord(pRvlc, bs);
+
+ if (escWord >= 0) {
+
+ pEsc[escCnt] = escWord;
+ escCnt++;
+ }
+ else {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID;
+ pRvlc->numDecodedEscapeWordsEsc = escCnt;
+
+ return;
+ }
+ } /* all RVLC escapes decoded */
+
+ pRvlc->numDecodedEscapeWordsEsc = escCnt;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: decodeRVLCodeword
+
+ description: Decodes a RVL-coded dpcm-word (-part).
+-----------------------------------------------------------------------------------------------
+ input: - FDK bitstream handle
+ - pointer rvlc structure
+-----------------------------------------------------------------------------------------------
+ return: - a dpcm value which is within range [0,1,..,14] in case of no errors.
+ The offset of 7 must be subtracted to get a valid dpcm scalefactor value.
+ In case of errors a forbidden codeword is detected --> returning -1
+-------------------------------------------------------------------------------------------- */
+
+SCHAR decodeRVLCodeword (HANDLE_FDK_BITSTREAM bs, CErRvlcInfo *pRvlc)
+{
+ int i;
+ SCHAR value;
+ UCHAR carryBit;
+ UINT branchValue;
+ UINT branchNode;
+
+ const UINT *pRvlCodeTree = pRvlc->pHuffTreeRvlCodewds;
+ UCHAR direction = pRvlc->direction;
+ USHORT *pBitstrIndxRvl = pRvlc->pBitstrIndxRvl_RVL;
+ UINT treeNode = *pRvlCodeTree;
+
+ for (i=MAX_LEN_RVLC_CODE_WORD-1; i >= 0; i--) {
+ carryBit = rvlcReadBitFromBitstream(bs, /* get next bit */
+ pBitstrIndxRvl,
+ direction);
+
+ CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in huffman decoding tree */
+ treeNode,
+ &branchValue,
+ &branchNode);
+
+ if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-codeword is completely decoded */
+ value = (SCHAR) (branchNode & CLR_BIT_10);
+ *pRvlc->pRvlBitCnt_RVL -= (MAX_LEN_RVLC_CODE_WORD - i);
+
+ /* check available bits for decoding */
+ if (*pRvlc->pRvlBitCnt_RVL < 0) {
+ if (direction == FWD) {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD; }
+ else {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD; }
+ value = -1; /* signalize an error in return value, because too many bits was decoded */
+ }
+
+ /* check max value of dpcm value */
+ if (value > MAX_ALLOWED_DPCM_INDEX) {
+ if (direction == FWD) {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD;
+ }
+ else {
+ pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD;
+ }
+ value = -1; /* signalize an error in return value, because a forbidden cw was detected*/
+ }
+
+ return value; /* return a dpcm value with offset +7 or an error status */
+ }
+ else {
+ treeNode = *(pRvlCodeTree + branchValue); /* update treeNode for further step in decoding tree */
+ }
+ }
+
+ return -1;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeForward
+
+ description: Decode RVL-coded codewords in forward direction.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - handle to FDK bitstream
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static
+void rvlcDecodeForward (CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ int band = 0;
+ int group = 0;
+ int bnds = 0;
+
+ SHORT dpcm;
+
+ SHORT factor = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET;
+ SHORT position = - SF_OFFSET;
+ SHORT noisenrg = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256;
+
+ SHORT* pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd;
+ SHORT* pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
+ UCHAR* pEscFwdCnt = &(pRvlc->numDecodedEscapeWordsFwd);
+
+ pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_fwd);
+ pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlFwd);
+
+ *pEscFwdCnt = 0;
+ pRvlc->direction = FWD;
+ pRvlc->noise_used = 0;
+ pRvlc->sf_used = 0;
+ pRvlc->lastScf = 0;
+ pRvlc->lastNrg = 0;
+ pRvlc->lastIs = 0;
+
+ rvlcCheckIntensityCb(pRvlc,pAacDecoderChannelInfo);
+
+ /* main loop fwd long */
+ for (group=0; group < pRvlc->numWindowGroups; group++) {
+ for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+
+ case ZERO_HCB :
+ pScfFwd[bnds] = 0;
+ break;
+
+ case INTENSITY_HCB2 :
+ case INTENSITY_HCB :
+ /* store dpcm_is_position */
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if ( dpcm < 0 ) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++;
+ }
+ else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ position += dpcm;
+ pScfFwd[bnds] = position;
+ pRvlc->lastIs = position;
+ break;
+
+ case NOISE_HCB :
+ if (pRvlc->noise_used == 0) {
+ pRvlc->noise_used = 1;
+ pRvlc->first_noise_band = bnds;
+ noisenrg += pRvlc->dpcm_noise_nrg;
+ pScfFwd[bnds] = 100 + noisenrg;
+ pRvlc->lastNrg = noisenrg;
+ }
+ else {
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if ( dpcm < 0 ) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++;
+ }
+ else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ noisenrg += dpcm;
+ pScfFwd[bnds] = 100 + noisenrg;
+ pRvlc->lastNrg = noisenrg;
+ }
+ pAacDecoderChannelInfo->data.aac.PnsData.pnsUsed[bnds] = 1;
+ break ;
+
+ default :
+ pRvlc->sf_used = 1;
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if ( dpcm < 0 ) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++; }
+ else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ factor += dpcm;
+ pScfFwd[bnds] = factor;
+ pRvlc->lastScf = factor;
+ break;
+ }
+ }
+ }
+
+ /* postfetch fwd long */
+ if (pRvlc->intensity_used) {
+ dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */
+ if ( dpcm < 0 ) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_max = bnds;
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc++;
+ }
+ else {
+ dpcm += *pScfEsc++;
+ }
+ (*pEscFwdCnt)++;
+ if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) {
+ pRvlc->conceal_max_esc = bnds;
+ }
+ }
+ }
+ pRvlc->dpcm_is_last_position = dpcm;
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcDecodeBackward
+
+ description: Decode RVL-coded codewords in backward direction.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - handle FDK bitstream
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static
+void rvlcDecodeBackward (CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ SHORT band, group, dpcm, offset;
+ SHORT bnds = pRvlc->maxSfbTransmitted-1;
+
+ SHORT factor = pRvlc->rev_global_gain - SF_OFFSET;
+ SHORT position = pRvlc->dpcm_is_last_position - SF_OFFSET;
+ SHORT noisenrg = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256;
+
+ SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
+ SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
+ UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc);
+ UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd);
+
+ pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd);
+ pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlBwd);
+
+ *pEscBwdCnt = 0;
+ pRvlc->direction = BWD;
+ pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */
+ pRvlc->firstScf = 0;
+ pRvlc->firstNrg = 0;
+ pRvlc->firstIs = 0;
+
+ /* prefetch long BWD */
+ if (pRvlc->intensity_used) {
+ dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */
+ if ( dpcm < 0 ) {
+ pRvlc->dpcm_is_last_position = 0;
+ pRvlc->conceal_min = bnds;
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pRvlc->conceal_min = bnds;
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ }
+ else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = bnds;
+ }
+ }
+ }
+ pRvlc->dpcm_is_last_position = dpcm;
+ }
+
+ /* main loop long BWD */
+ for (group=pRvlc->numWindowGroups-1; group >= 0; group--) {
+ for (band=pRvlc->maxSfbTransmitted-1; band >= 0; band--) {
+ bnds = 16*group+band;
+ if ((band == 0) && (pRvlc->numWindowGroups != 1))
+ offset = 16 - pRvlc->maxSfbTransmitted + 1;
+ else
+ offset = 1;
+
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+
+ case ZERO_HCB :
+ pScfBwd[bnds] = 0;
+ break;
+
+ case INTENSITY_HCB2 :
+ case INTENSITY_HCB :
+ /* store dpcm_is_position */
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if ( dpcm < 0 ) {
+ pScfBwd[bnds] = position;
+ pRvlc->conceal_min = FDKmax(0,bnds-offset);
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pScfBwd[bnds] = position;
+ pRvlc->conceal_min = FDKmax(0,bnds-offset);
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ }
+ else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = FDKmax(0,bnds-offset);
+ }
+ }
+ }
+ pScfBwd[bnds] = position;
+ position -= dpcm;
+ pRvlc->firstIs = position;
+ break;
+
+ case NOISE_HCB :
+ if ( bnds == pRvlc->first_noise_band ) {
+ pScfBwd[bnds] = pRvlc->dpcm_noise_nrg + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256;
+ pRvlc->firstNrg = pScfBwd[bnds];
+ }
+ else {
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if ( dpcm < 0 ) {
+ pScfBwd[bnds] = noisenrg;
+ pRvlc->conceal_min = FDKmax(0,bnds-offset);
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pScfBwd[bnds] = noisenrg;
+ pRvlc->conceal_min = FDKmax(0,bnds-offset);
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ }
+ else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = FDKmax(0,bnds-offset);
+ }
+ }
+ }
+ pScfBwd[bnds] = noisenrg;
+ noisenrg -= dpcm;
+ pRvlc->firstNrg = noisenrg;
+ }
+ break ;
+
+ default :
+ dpcm = decodeRVLCodeword(bs, pRvlc);
+ if ( dpcm < 0 ) {
+ pScfBwd[bnds] = factor;
+ pRvlc->conceal_min = FDKmax(0,bnds-offset);
+ return;
+ }
+ dpcm -= TABLE_OFFSET;
+ if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
+ if (pRvlc->length_of_rvlc_escapes) {
+ pScfBwd[bnds] = factor;
+ pRvlc->conceal_min = FDKmax(0,bnds-offset);
+ return;
+ }
+ else {
+ if (dpcm == MIN_RVL) {
+ dpcm -= *pScfEsc--;
+ }
+ else {
+ dpcm += *pScfEsc--;
+ }
+ (*pEscBwdCnt)++;
+ if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) {
+ pRvlc->conceal_min_esc = FDKmax(0,bnds-offset);
+ }
+ }
+ }
+ pScfBwd[bnds] = factor;
+ factor -= dpcm;
+ pRvlc->firstScf = factor;
+ break;
+ }
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcFinalErrorDetection
+
+ description: Call RVLC concealment if error was detected in decoding process
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static
+void rvlcFinalErrorDetection (CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo)
+{
+ CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ UCHAR ErrorStatusComplete = 0;
+ UCHAR ErrorStatusLengthFwd = 0;
+ UCHAR ErrorStatusLengthBwd = 0;
+ UCHAR ErrorStatusLengthEscapes = 0;
+ UCHAR ErrorStatusFirstScf = 0;
+ UCHAR ErrorStatusLastScf = 0;
+ UCHAR ErrorStatusFirstNrg = 0;
+ UCHAR ErrorStatusLastNrg = 0;
+ UCHAR ErrorStatusFirstIs = 0;
+ UCHAR ErrorStatusLastIs = 0;
+ UCHAR ErrorStatusForbiddenCwFwd = 0;
+ UCHAR ErrorStatusForbiddenCwBwd = 0;
+ UCHAR ErrorStatusNumEscapesFwd = 0;
+ UCHAR ErrorStatusNumEscapesBwd = 0;
+ UCHAR ConcealStatus = 1;
+ UCHAR currentBlockType; /* short: 0, not short: 1*/
+
+#if VERBOSE_RVLC_OUTPUT
+ CHAR Strategy[60]="No";
+ SHORT conceal_max;
+ SHORT conceal_min;
+#endif
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 1;
+
+ /* invalid escape words, bit counter unequal zero, forbidden codeword detected */
+ if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD)
+ ErrorStatusForbiddenCwFwd = 1;
+
+ if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD)
+ ErrorStatusForbiddenCwBwd = 1;
+
+ /* bit counter forward unequal zero */
+ if (pRvlc->length_of_rvlc_sf_fwd)
+ ErrorStatusLengthFwd = 1;
+
+ /* bit counter backward unequal zero */
+ if (pRvlc->length_of_rvlc_sf_bwd)
+ ErrorStatusLengthBwd = 1;
+
+ /* bit counter escape sequences unequal zero */
+ if (pRvlc->sf_escapes_present)
+ if (pRvlc->length_of_rvlc_escapes)
+ ErrorStatusLengthEscapes = 1;
+
+ if (pRvlc->sf_used) {
+ /* first decoded scf does not match to global gain in backward direction */
+ if (pRvlc->firstScf != (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET) )
+ ErrorStatusFirstScf = 1;
+
+ /* last decoded scf does not match to rev global gain in forward direction */
+ if (pRvlc->lastScf != (pRvlc->rev_global_gain - SF_OFFSET) )
+ ErrorStatusLastScf = 1;
+ }
+
+ if (pRvlc->noise_used) {
+ /* first decoded nrg does not match to dpcm_noise_nrg in backward direction */
+ if (pRvlc->firstNrg != (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain + pRvlc->dpcm_noise_nrg - SF_OFFSET -90 - 256) )
+ ErrorStatusFirstNrg = 1;
+
+ /* last decoded nrg does not match to dpcm_noise_last_position in forward direction */
+ if (pRvlc->lastNrg != (pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256) )
+ ErrorStatusLastNrg = 1;
+ }
+
+ if (pRvlc->intensity_used) {
+ /* first decoded is position does not match in backward direction */
+ if (pRvlc->firstIs != (-SF_OFFSET) )
+ ErrorStatusFirstIs = 1;
+
+ /* last decoded is position does not match in forward direction */
+ if (pRvlc->lastIs != (pRvlc->dpcm_is_last_position - SF_OFFSET) )
+ ErrorStatusLastIs = 1;
+ }
+
+ /* decoded escapes and used escapes in forward direction do not fit */
+ if ((pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && (pRvlc->conceal_max == CONCEAL_MAX_INIT)) {
+ ErrorStatusNumEscapesFwd = 1;
+ }
+
+ /* decoded escapes and used escapes in backward direction do not fit */
+ if ((pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && (pRvlc->conceal_min == CONCEAL_MIN_INIT)) {
+ ErrorStatusNumEscapesBwd = 1;
+ }
+
+#if VERBOSE_RVLC_OUTPUT
+ conceal_max = pRvlc->conceal_max;
+ conceal_min = pRvlc->conceal_min;
+#endif
+
+ if ( ErrorStatusLengthEscapes
+ || (
+ ( (pRvlc->conceal_max == CONCEAL_MAX_INIT)
+ && (pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc)
+ && (ErrorStatusLastScf || ErrorStatusLastNrg || ErrorStatusLastIs) )
+
+ &&
+
+ ( (pRvlc->conceal_min == CONCEAL_MIN_INIT)
+ && (pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc)
+ && (ErrorStatusFirstScf || ErrorStatusFirstNrg || ErrorStatusFirstIs) )
+ )
+ || ( (pRvlc->conceal_max == CONCEAL_MAX_INIT)
+ && ((pRvlc->rev_global_gain - SF_OFFSET - pRvlc->lastScf) < -15)
+ )
+ || ( (pRvlc->conceal_min == CONCEAL_MIN_INIT)
+ && ((pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - pRvlc->firstScf) < -15)
+ )
+ ) {
+ if ((pRvlc->conceal_max == CONCEAL_MAX_INIT) || (pRvlc->conceal_min == CONCEAL_MIN_INIT)) {
+ pRvlc->conceal_max = 0;
+ pRvlc->conceal_min = FDKmax(0, (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1);
+ }
+ else {
+ pRvlc->conceal_max = FDKmin(pRvlc->conceal_max,pRvlc->conceal_max_esc);
+ pRvlc->conceal_min = FDKmax(pRvlc->conceal_min,pRvlc->conceal_min_esc);
+ }
+ }
+
+ ErrorStatusComplete = ErrorStatusLastScf || ErrorStatusFirstScf || ErrorStatusLastNrg || ErrorStatusFirstNrg
+ || ErrorStatusLastIs || ErrorStatusFirstIs || ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd
+ || ErrorStatusLengthFwd || ErrorStatusLengthBwd || ErrorStatusLengthEscapes || ErrorStatusNumEscapesFwd
+ || ErrorStatusNumEscapesBwd;
+
+ currentBlockType = (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) ? 0 : 1;
+
+
+ if (!ErrorStatusComplete) {
+ int band;
+ int group;
+ int bnds;
+ int lastSfbIndex;
+
+ lastSfbIndex = (pRvlc->numWindowGroups > 1) ? 16 : 64;
+
+ for (group=0; group < pRvlc->numWindowGroups; group++) {
+ for (band=0; band<pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ }
+ }
+
+ for (group=0; group < pRvlc->numWindowGroups; group++)
+ {
+ for (band=0; band<pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds] = pAacDecoderChannelInfo->pDynData->aCodeBook[bnds];
+ }
+ for (; band <lastSfbIndex; band++) {
+ bnds = 16*group+band;
+ FDK_ASSERT(bnds >= 0 && bnds < RVLC_MAX_SFB);
+ pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds] = ZERO_HCB;
+ }
+ }
+ }
+ else {
+ int band;
+ int group;
+
+ /* A single bit error was detected in decoding of dpcm values. It also could be an error with more bits in decoding
+ of escapes and dpcm values whereby an illegal codeword followed not directly after the corrupted bits but just
+ after decoding some more (wrong) scalefactors. Use the smaller scalefactor from forward decoding, backward decoding
+ and previous frame. */
+ if ( ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && (pRvlc->conceal_min <= pRvlc->conceal_max)
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType) && pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK
+ && pRvlc->sf_concealment && ConcealStatus )
+ {
+ BidirectionalEstimation_UseScfOfPrevFrameAsReference (pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
+ ConcealStatus=0;
+#if VERBOSE_RVLC_OUTPUT
+ FDKstrcpy(Strategy,"Yes (BidirectionalEstimation_UseScfOfPrevFrameAsReference)");
+#endif
+ }
+
+ /* A single bit error was detected in decoding of dpcm values. It also could be an error with more bits in decoding
+ of escapes and dpcm values whereby an illegal codeword followed not directly after the corrupted bits but just
+ after decoding some more (wrong) scalefactors. Use the smaller scalefactor from forward and backward decoding. */
+ if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || (pRvlc->conceal_max != CONCEAL_MAX_INIT))
+ && !(pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK && pRvlc->sf_concealment && (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType))
+ && ConcealStatus )
+ {
+ BidirectionalEstimation_UseLowerScfOfCurrentFrame (pAacDecoderChannelInfo);
+ ConcealStatus=0;
+#if VERBOSE_RVLC_OUTPUT
+ FDKstrcpy(Strategy,"Yes (BidirectionalEstimation_UseLowerScfOfCurrentFrame)");
+#endif
+ }
+
+ /* No errors were detected in decoding of escapes and dpcm values however the first and last value
+ of a group (is,nrg,sf) is incorrect */
+ if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && ((ErrorStatusLastScf && ErrorStatusFirstScf)
+ || (ErrorStatusLastNrg && ErrorStatusFirstNrg) || (ErrorStatusLastIs && ErrorStatusFirstIs))
+ && !(ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd || ErrorStatusLengthEscapes ) && ConcealStatus)
+ {
+ StatisticalEstimation (pAacDecoderChannelInfo);
+ ConcealStatus=0;
+#if VERBOSE_RVLC_OUTPUT
+ FDKstrcpy(Strategy,"Yes (StatisticalEstimation)");
+#endif
+ }
+
+ /* A error with more bits in decoding of escapes and dpcm values was detected. Use the smaller scalefactor from forward
+ decoding, backward decoding and previous frame. */
+ if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK && pRvlc->sf_concealment
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType) && ConcealStatus )
+ {
+ PredictiveInterpolation(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
+ ConcealStatus=0;
+#if VERBOSE_RVLC_OUTPUT
+ FDKstrcpy(Strategy,"Yes (PredictiveInterpolation)");
+#endif
+ }
+
+ /* Call frame concealment, because no better strategy was found. Setting the scalefactors to zero is done for debugging
+ purposes */
+ if (ConcealStatus) {
+ for (group=0; group < pRvlc->numWindowGroups; group++) {
+ for (band=0; band<pRvlc->maxSfbTransmitted; band++) {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[16*group+band] = 0;
+ }
+ }
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
+#if VERBOSE_RVLC_OUTPUT
+ FDKstrcpy(Strategy,"Yes (FrameConcealment)");
+#endif
+ }
+ }
+
+#if VERBOSE_RVLC_OUTPUT
+ DebugOutputDistortedBitstreams(pRvlc,pAacDecoderChannelInfo,ErrorStatusLengthFwd,ErrorStatusLengthBwd,
+ ErrorStatusLengthEscapes,ErrorStatusFirstScf,ErrorStatusLastScf,
+ ErrorStatusFirstNrg,ErrorStatusLastNrg,ErrorStatusFirstIs,ErrorStatusLastIs,
+ ErrorStatusForbiddenCwFwd,ErrorStatusForbiddenCwBwd,ErrorStatusNumEscapesFwd,
+ ErrorStatusNumEscapesBwd,conceal_max,conceal_min,Strategy);
+#endif
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: CRvlc_Read
+
+ description: Read RVLC ESC1 data (side info) from bitstream.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - pointer bitstream structure
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+void CRvlc_Read (
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs)
+{
+ CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+
+ int group,band;
+
+ /* RVLC long specific initialization Init part 1 of 2 */
+ pRvlc->numWindowGroups = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo);
+ pRvlc->maxSfbTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
+ pRvlc->noise_used = 0; /* noise detection */
+ pRvlc->dpcm_noise_nrg = 0; /* only for debugging */
+ pRvlc->dpcm_noise_last_position = 0; /* only for debugging */
+ pRvlc->length_of_rvlc_escapes = -1; /* default value is used for error detection and concealment */
+
+ /* read only error sensitivity class 1 data (ESC 1 - data) */
+ pRvlc->sf_concealment = FDKreadBits(bs,1); /* #1 */
+ pRvlc->rev_global_gain = FDKreadBits(bs,8); /* #2 */
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) {
+ pRvlc->length_of_rvlc_sf = FDKreadBits(bs,11); /* #3 */
+ }
+ else {
+ pRvlc->length_of_rvlc_sf = FDKreadBits(bs,9); /* #3 */
+ }
+
+ /* check if noise codebook is used */
+ for (group = 0; group < pRvlc->numWindowGroups; group++) {
+ for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
+ if (pAacDecoderChannelInfo->pDynData->aCodeBook[16*group+band] == NOISE_HCB) {
+ pRvlc->noise_used = 1;
+ break;
+ }
+ }
+ }
+
+ if (pRvlc->noise_used)
+ pRvlc->dpcm_noise_nrg = FDKreadBits(bs, 9); /* #4 PNS */
+
+ pRvlc->sf_escapes_present = FDKreadBits(bs, 1); /* #5 */
+
+ if ( pRvlc->sf_escapes_present) {
+ pRvlc->length_of_rvlc_escapes = FDKreadBits(bs, 8); /* #6 */
+ }
+
+ if (pRvlc->noise_used) {
+ pRvlc->dpcm_noise_last_position = FDKreadBits(bs, 9); /* #7 PNS */
+ pRvlc->length_of_rvlc_sf -= 9;
+ }
+
+ pRvlc->length_of_rvlc_sf_fwd = pRvlc->length_of_rvlc_sf;
+ pRvlc->length_of_rvlc_sf_bwd = pRvlc->length_of_rvlc_sf;
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: CRvlc_Decode
+
+ description: Decode rvlc data
+ The function reads both the escape sequences and the scalefactors in forward
+ and backward direction. If an error occured during decoding process which can
+ not be concealed with the rvlc concealment frame concealment will be initiated.
+ Then the element "rvlcCurrentScaleFactorOK" in the decoder channel info is set
+ to 0 otherwise it is set to 1.
+-----------------------------------------------------------------------------------------------
+ input: - pointer rvlc structure
+ - pointer channel info structure
+ - pointer to persistent channel info structure
+ - pointer bitstream structure
+-----------------------------------------------------------------------------------------------
+ return: ErrorStatus = AAC_DEC_OK
+-------------------------------------------------------------------------------------------- */
+
+void CRvlc_Decode (
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ HANDLE_FDK_BITSTREAM bs
+ )
+{
+ CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ INT bitCntOffst;
+ UINT saveBitCnt;
+
+ rvlcInit(pRvlc,pAacDecoderChannelInfo,bs);
+
+ /* save bitstream position */
+ saveBitCnt = FDKgetBitCnt(bs);
+
+#if RVLC_ADVANCED_BITSTREAM_ERROR_GENERATOR_SF
+ GenerateSingleBitError(pRvlc,
+ &(pRvlc->bitstreamIndexRvlFwd),
+ pRvlc->length_of_rvlc_sf,
+ 0);
+#endif
+
+#if RVLC_ADVANCED_BITSTREAM_ERROR_GENERATOR_ESC
+ if (pRvlc->sf_escapes_present)
+ GenerateSingleBitError(pRvlc,
+ &(pRvlc->bitstreamIndexEsc),
+ pRvlc->length_of_rvlc_escapes,
+ 1);
+#endif
+
+ if ( pRvlc->sf_escapes_present)
+ rvlcDecodeEscapes(pRvlc, pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc, bs);
+
+ rvlcDecodeForward(pRvlc,pAacDecoderChannelInfo, bs);
+ rvlcDecodeBackward(pRvlc,pAacDecoderChannelInfo, bs);
+ rvlcFinalErrorDetection(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo);
+
+ pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = pRvlc->intensity_used;
+ pAacDecoderChannelInfo->data.aac.PnsData.PnsActive = pRvlc->noise_used;
+
+ /* restore bitstream position */
+ bitCntOffst = saveBitCnt - FDKgetBitCnt(bs);
+ if( bitCntOffst ) {
+ FDKpushBiDirectional(bs, bitCntOffst);
+ }
+}
+
+void CRvlc_ElementCheck (
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ const UINT flags,
+ const INT elChannels
+ )
+{
+ int ch;
+
+ /* Required for MPS residuals. */
+ if (pAacDecoderStaticChannelInfo == NULL) {
+ return;
+ }
+
+ /* RVLC specific sanity checks */
+ if ( (flags & AC_ER_RVLC) && (elChannels == 2)) { /* to be reviewed */
+ if ( ( (pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) ||
+ (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) )
+ && pAacDecoderChannelInfo[0]->pComData->jointStereoData.MsMaskPresent ) {
+ pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
+ pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
+ }
+
+ if ( (pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0)
+ && (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 1)
+ && (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcIntensityUsed == 1) ){
+ pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0;
+ }
+ }
+
+ for (ch = 0; ch < elChannels; ch ++)
+ {
+ pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousBlockType = (GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) == EightShortSequence) ? 0 : 1;
+ if (flags & AC_ER_RVLC) {
+ pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousScaleFactorOK = pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK;
+ }
+ else {
+ pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousScaleFactorOK = 0;
+ }
+ }
+}
+
+
diff --git a/libAACdec/src/rvlc.h b/libAACdec/src/rvlc.h
new file mode 100644
index 0000000..e80e80e
--- /dev/null
+++ b/libAACdec/src/rvlc.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+ $Id$
+
+****************************************************************************/
+/*!
+ \file
+ \brief Defines structures and prototypes for RVLC
+ \author Robert Weidner
+*/
+
+#ifndef RVLC_H
+#define RVLC_H
+
+
+
+#include "aacdecoder.h"
+#include "channel.h"
+#include "rvlc_info.h"
+
+/* ------------------------------------------------------------------- */
+/* errorLogRvlc: A word of 32 bits used for logging possible errors */
+/* within RVLC in case of distorted bitstreams. */
+/* ------------------------------------------------------------------- */
+#define RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID 0x80000000 /* ESC-Dec During RVLC-Escape-decoding there have been more bits decoded as there are available */
+#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD 0x40000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding (long+shrt) */
+#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD 0x20000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding (long+shrt) */
+#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD 0x08000000 /* RVL-Dec forbidden codeword detected fwd (long+shrt) */
+#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD 0x04000000 /* RVL-Dec forbidden codeword detected bwd (long+shrt) */
+
+
+
+void CRvlc_Read (CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ HANDLE_FDK_BITSTREAM bs);
+
+void CRvlc_Decode (CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
+ HANDLE_FDK_BITSTREAM bs);
+
+/**
+ * \brief performe sanity checks to the channel data corresponding to one channel element.
+ * \param pAacDecoderChannelInfo
+ * \param pAacDecoderStaticChannelInfo
+ * \param elChannels amount of channels of the channel element.
+ */
+void CRvlc_ElementCheck (
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
+ const UINT flags,
+ const INT elChannels
+ );
+
+
+
+
+#endif /* RVLC_H */
diff --git a/libAACdec/src/rvlc_info.h b/libAACdec/src/rvlc_info.h
new file mode 100644
index 0000000..2edc1b3
--- /dev/null
+++ b/libAACdec/src/rvlc_info.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+ $Id$
+
+****************************************************************************/
+/*!
+ \file
+ \brief Defines structures for RVLC
+ \author Robert Weidner
+*/
+#ifndef RVLC_INFO_H
+#define RVLC_INFO_H
+
+
+
+#define FWD 0 /* bitstream decoding direction forward (RVL coded part) */
+#define BWD 1 /* bitstream decoding direction backward (RVL coded part) */
+
+#define MAX_RVL 7 /* positive RVLC escape */
+#define MIN_RVL -7 /* negative RVLC escape */
+#define MAX_ALLOWED_DPCM_INDEX 14 /* the maximum allowed index of a decoded dpcm value (offset 'TABLE_OFFSET' incl --> must be subtracted) */
+#define TABLE_OFFSET 7 /* dpcm offset of valid output values of rvl table decoding, the rvl table ouly returns positive values, therefore the offset */
+#define MAX_LEN_RVLC_CODE_WORD 9 /* max length of a RVL codeword in bits */
+#define MAX_LEN_RVLC_ESCAPE_WORD 20 /* max length of huffman coded RVLC escape word in bits */
+
+#define DPCM_NOISE_NRG_BITS 9
+#define SF_OFFSET 100 /* offset for correcting scf value */
+
+#define CONCEAL_MAX_INIT 1311 /* arbitrary value */
+#define CONCEAL_MIN_INIT -1311 /* arbitrary value */
+
+#define RVLC_MAX_SFB ((8) * (16))
+
+/* sideinfo of RVLC */
+typedef struct
+{
+ /* ------- ESC 1 Data: --------- */ /* order of RVLC-bitstream components in bitstream (RVLC-initialization), every component appears only once in bitstream */
+ INT sf_concealment; /* 1 */
+ INT rev_global_gain; /* 2 */
+ SHORT length_of_rvlc_sf; /* 3 */ /* original value, gets modified (subtract 9) in case of noise (PNS); is kept for later use */
+ INT dpcm_noise_nrg; /* 4 optional */
+ INT sf_escapes_present; /* 5 */
+ SHORT length_of_rvlc_escapes; /* 6 optional */
+ INT dpcm_noise_last_position; /* 7 optional */
+
+ INT dpcm_is_last_position;
+
+ SHORT length_of_rvlc_sf_fwd; /* length_of_rvlc_sf used for forward decoding */
+ SHORT length_of_rvlc_sf_bwd; /* length_of_rvlc_sf used for backward decoding */
+
+ /* for RVL-Codeword decoder to distinguish between fwd and bwd decoding */
+ SHORT *pRvlBitCnt_RVL;
+ USHORT *pBitstrIndxRvl_RVL;
+
+ UCHAR numWindowGroups;
+ UCHAR maxSfbTransmitted;
+ UCHAR first_noise_group;
+ UCHAR first_noise_band;
+ UCHAR direction;
+
+ /* bitstream indices */
+ USHORT bitstreamIndexRvlFwd; /* base address of RVL-coded-scalefactor data (ESC 2) for forward decoding */
+ USHORT bitstreamIndexRvlBwd; /* base address of RVL-coded-scalefactor data (ESC 2) for backward decoding */
+ USHORT bitstreamIndexEsc; /* base address where RVLC-escapes start (ESC 2) */
+
+ /* decoding trees */
+ const UINT *pHuffTreeRvlCodewds;
+ const UINT *pHuffTreeRvlcEscape;
+
+ /* escape counters */
+ UCHAR numDecodedEscapeWordsFwd; /* when decoding RVL-codes forward */
+ UCHAR numDecodedEscapeWordsBwd; /* when decoding RVL-codes backward */
+ UCHAR numDecodedEscapeWordsEsc; /* when decoding the escape-Words */
+
+ SCHAR noise_used;
+ SCHAR intensity_used;
+ SCHAR sf_used;
+
+ SHORT firstScf;
+ SHORT lastScf;
+ SHORT firstNrg;
+ SHORT lastNrg;
+ SHORT firstIs;
+ SHORT lastIs;
+
+ /* ------ RVLC error detection ------ */
+ UINT errorLogRvlc; /* store RVLC errors */
+ SHORT conceal_min; /* is set at backward decoding */
+ SHORT conceal_max; /* is set at forward decoding */
+ SHORT conceal_min_esc; /* is set at backward decoding */
+ SHORT conceal_max_esc; /* is set at forward decoding */
+} CErRvlcInfo;
+
+typedef CErRvlcInfo RVLC_INFO; /* temp */
+
+
+
+#endif /* RVLC_INFO_H */
diff --git a/libAACdec/src/rvlcbit.cpp b/libAACdec/src/rvlcbit.cpp
new file mode 100644
index 0000000..c3ffc59
--- /dev/null
+++ b/libAACdec/src/rvlcbit.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+ $Id$
+
+****************************************************************************/
+/*!
+ \file
+ \brief RVLC bitstream reading
+ \author Robert Weidner
+*/
+
+#include "rvlcbit.h"
+
+
+/*---------------------------------------------------------------------------------------------
+ function: rvlcReadBitFromBitstream
+
+ description: This function returns a bit from the bitstream according to read direction.
+ It is called very often, therefore it makes sense to inline it (runtime).
+-----------------------------------------------------------------------------------------------
+ input: - bitstream
+ - pPosition
+ - readDirection
+-----------------------------------------------------------------------------------------------
+ return: - bit from bitstream
+-------------------------------------------------------------------------------------------- */
+
+UCHAR rvlcReadBitFromBitstream (HANDLE_FDK_BITSTREAM bs,
+ USHORT *pPosition,
+ UCHAR readDirection)
+{
+ UINT bit;
+ INT readBitOffset = *pPosition-FDKgetBitCnt(bs);
+
+ if( readBitOffset ) {
+ FDKpushBiDirectional(bs, readBitOffset);
+ }
+
+ if (readDirection == FWD) {
+ bit = FDKreadBits(bs, 1);
+
+ *pPosition += 1;
+ } else {
+ /* to be replaced with a brother function of FDKreadBits() */
+ bit = FDKreadBits(bs, 1);
+ FDKpushBack(bs, 2);
+
+ *pPosition -= 1;
+ }
+
+ return (bit);
+}
+
diff --git a/libAACdec/src/rvlcbit.h b/libAACdec/src/rvlcbit.h
new file mode 100644
index 0000000..5cb9e88
--- /dev/null
+++ b/libAACdec/src/rvlcbit.h
@@ -0,0 +1,41 @@
+/***************************** MPEG-4 AAC Decoder ***************************
+
+ (C) Copyright Fraunhofer IIS 2000-2008
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Robert Weidner (DSP Solutions)
+ Description: RVLC Decoder: Bitstream reading
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+*******************************************************************************/
+
+#ifndef RVLCBIT_H
+#define RVLCBIT_H
+
+
+
+#include "rvlc.h"
+
+UCHAR rvlcReadBitFromBitstream (HANDLE_FDK_BITSTREAM bs,
+ USHORT *pPosition,
+ UCHAR readDirection);
+
+
+#endif /* RVLCBIT_H */
diff --git a/libAACdec/src/rvlcconceal.cpp b/libAACdec/src/rvlcconceal.cpp
new file mode 100644
index 0000000..161c336
--- /dev/null
+++ b/libAACdec/src/rvlcconceal.cpp
@@ -0,0 +1,639 @@
+/****************************************************************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+ $Id$
+
+****************************************************************************/
+/*!
+ \file
+ \brief rvlc concealment
+ \author Josef Hoepfl
+*/
+
+#include "rvlcconceal.h"
+
+
+#include "block.h"
+#include "rvlc.h"
+
+/*---------------------------------------------------------------------------------------------
+ function: calcRefValFwd
+
+ description: The function determines the scalefactor which is closed to the scalefactorband
+ conceal_min. The same is done for intensity data and noise energies.
+-----------------------------------------------------------------------------------------------
+ output: - reference value scf
+ - reference value internsity data
+ - reference value noise energy
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static
+void calcRefValFwd (CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ int *refIsFwd,
+ int *refNrgFwd,
+ int *refScfFwd)
+{
+ int band,bnds,group,startBand;
+ int idIs,idNrg,idScf;
+ int conceal_min,conceal_group_min;
+ int MaximumScaleFactorBands;
+
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
+ MaximumScaleFactorBands = 16;
+ else
+ MaximumScaleFactorBands = 64;
+
+ conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands;
+ conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands;
+
+ /* calculate first reference value for approach in forward direction */
+ idIs = idNrg = idScf = 1;
+
+ /* set reference values */
+ *refIsFwd = - SF_OFFSET;
+ *refNrgFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256;
+ *refScfFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET;
+
+ startBand = conceal_min-1;
+ for (group=conceal_group_min; group >= 0; group--) {
+ for (band=startBand; band >= 0; band--) {
+ bnds = 16*group+band;
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ break;
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ if (idIs) {
+ *refIsFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ idIs=0; /* reference value has been set */
+ }
+ break;
+ case NOISE_HCB:
+ if (idNrg) {
+ *refNrgFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ idNrg=0; /* reference value has been set */
+ }
+ break ;
+ default:
+ if (idScf) {
+ *refScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ idScf=0; /* reference value has been set */
+ }
+ break;
+ }
+ }
+ startBand = pRvlc->maxSfbTransmitted-1;
+ }
+
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: calcRefValBwd
+
+ description: The function determines the scalefactor which is closed to the scalefactorband
+ conceal_max. The same is done for intensity data and noise energies.
+-----------------------------------------------------------------------------------------------
+ output: - reference value scf
+ - reference value internsity data
+ - reference value noise energy
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+static
+void calcRefValBwd (CErRvlcInfo *pRvlc,
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ int *refIsBwd,
+ int *refNrgBwd,
+ int *refScfBwd)
+{
+ int band,bnds,group,startBand;
+ int idIs,idNrg,idScf;
+ int conceal_max,conceal_group_max;
+ int MaximumScaleFactorBands;
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
+ MaximumScaleFactorBands = 16;
+ else
+ MaximumScaleFactorBands = 64;
+
+ conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands;
+ conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands;
+
+ /* calculate first reference value for approach in backward direction */
+ idIs = idNrg = idScf = 1;
+
+ /* set reference values */
+ *refIsBwd = pRvlc->dpcm_is_last_position - SF_OFFSET;
+ *refNrgBwd = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256 + pRvlc->dpcm_noise_nrg;
+ *refScfBwd = pRvlc->rev_global_gain - SF_OFFSET;
+
+ startBand=conceal_max+1;
+
+ /* if needed, re-set reference values */
+ for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) {
+ for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ break;
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ if (idIs) {
+ *refIsBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ idIs=0; /* reference value has been set */
+ }
+ break;
+ case NOISE_HCB:
+ if (idNrg) {
+ *refNrgBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ idNrg=0; /* reference value has been set */
+ }
+ break ;
+ default:
+ if (idScf) {
+ *refScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ idScf=0; /* reference value has been set */
+ }
+ break;
+ }
+ }
+ startBand=0;
+ }
+
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ function: BidirectionalEstimation_UseLowerScfOfCurrentFrame
+
+ description: This approach by means of bidirectional estimation is generally performed when
+ a single bit error has been detected, the bit error can be isolated between
+ 'conceal_min' and 'conceal_max' and the 'sf_concealment' flag is not set. The
+ sets of scalefactors decoded in forward and backward direction are compared
+ with each other. The smaller scalefactor will be considered as the correct one
+ respectively. The reconstruction of the scalefactors with this approach archieve
+ good results in audio quality. The strategy must be applied to scalefactors,
+ intensity data and noise energy seperately.
+-----------------------------------------------------------------------------------------------
+ output: Concealed scalefactor, noise energy and intensity data between conceal_min and
+ conceal_max
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+void BidirectionalEstimation_UseLowerScfOfCurrentFrame (CAacDecoderChannelInfo *pAacDecoderChannelInfo)
+{
+ CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ int band,bnds,startBand,endBand,group;
+ int conceal_min,conceal_max;
+ int conceal_group_min,conceal_group_max;
+ int MaximumScaleFactorBands;
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) {
+ MaximumScaleFactorBands = 16;
+ }
+ else {
+ MaximumScaleFactorBands = 64;
+ }
+
+ /* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a
+ appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly
+ not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */
+ if (pRvlc->conceal_min == CONCEAL_MIN_INIT)
+ pRvlc->conceal_min = 0;
+
+ if (pRvlc->conceal_max == CONCEAL_MAX_INIT)
+ pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1;
+
+ conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands;
+ conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands;
+ conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands;
+ conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands;
+
+ if (pRvlc->conceal_min == pRvlc->conceal_max) {
+
+ int refIsFwd,refNrgFwd,refScfFwd;
+ int refIsBwd,refNrgBwd,refScfBwd;
+
+ bnds = pRvlc->conceal_min;
+ calcRefValFwd(pRvlc,pAacDecoderChannelInfo,&refIsFwd,&refNrgFwd,&refScfFwd);
+ calcRefValBwd(pRvlc,pAacDecoderChannelInfo,&refIsBwd,&refNrgBwd,&refScfBwd);
+
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ break;
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ if (refIsFwd < refIsBwd)
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsFwd;
+ else
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsBwd;
+ break;
+ case NOISE_HCB:
+ if (refNrgFwd < refNrgBwd)
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgFwd;
+ else
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgBwd;
+ break;
+ default:
+ if (refScfFwd < refScfBwd)
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfFwd;
+ else
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfBwd;
+ break;
+ }
+ }
+ else {
+ pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max];
+ pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min];
+
+ /* consider the smaller of the forward and backward decoded value as the correct one */
+ startBand = conceal_min;
+ if (conceal_group_min == conceal_group_max)
+ endBand = conceal_max;
+ else
+ endBand = pRvlc->maxSfbTransmitted-1;
+
+ for (group=conceal_group_min; group <= conceal_group_max; group++) {
+ for (band=startBand; band <= endBand; band++) {
+ bnds = 16*group+band;
+ if (pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds] < pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds])
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ else
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ }
+ startBand = 0;
+ if ((group+1) == conceal_group_max)
+ endBand = conceal_max;
+ }
+ }
+
+ /* now copy all data to the output buffer which needs not to be concealed */
+ if (conceal_group_min == 0)
+ endBand = conceal_min;
+ else
+ endBand = pRvlc->maxSfbTransmitted;
+ for (group=0; group <= conceal_group_min; group++) {
+ for (band=0; band < endBand; band++) {
+ bnds = 16*group+band;
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ }
+ if ((group+1) == conceal_group_min)
+ endBand = conceal_min;
+ }
+
+ startBand = conceal_max+1;
+ for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) {
+ for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ }
+ startBand = 0;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: BidirectionalEstimation_UseScfOfPrevFrameAsReference
+
+ description: This approach by means of bidirectional estimation is generally performed when
+ a single bit error has been detected, the bit error can be isolated between
+ 'conceal_min' and 'conceal_max', the 'sf_concealment' flag is set and the
+ previous frame has the same block type as the current frame. The scalefactor
+ decoded in forward and backward direction and the scalefactor of the previous
+ frame are compared with each other. The smaller scalefactor will be considered
+ as the correct one. At this the codebook of the previous and current frame must
+ be of the same set (scf, nrg, is) in each scalefactorband. Otherwise the
+ scalefactor of the previous frame is not considered in the minimum calculation.
+ The reconstruction of the scalefactors with this approach archieve good results
+ in audio quality. The strategy must be applied to scalefactors, intensity data
+ and noise energy seperately.
+-----------------------------------------------------------------------------------------------
+ output: Concealed scalefactor, noise energy and intensity data between conceal_min and
+ conceal_max
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+void BidirectionalEstimation_UseScfOfPrevFrameAsReference (
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
+ )
+{
+ CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ int band,bnds,startBand,endBand,group;
+ int conceal_min,conceal_max;
+ int conceal_group_min,conceal_group_max;
+ int MaximumScaleFactorBands;
+ int commonMin;
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) {
+ MaximumScaleFactorBands = 16;
+ }
+ else {
+ MaximumScaleFactorBands = 64;
+ }
+
+ /* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a
+ appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly
+ not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */
+ if (pRvlc->conceal_min == CONCEAL_MIN_INIT)
+ pRvlc->conceal_min = 0;
+
+ if (pRvlc->conceal_max == CONCEAL_MAX_INIT)
+ pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1;
+
+ conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands;
+ conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands;
+ conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands;
+ conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands;
+
+ pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max];
+ pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min];
+
+ /* consider the smaller of the forward and backward decoded value as the correct one */
+ startBand = conceal_min;
+ if (conceal_group_min == conceal_group_max)
+ endBand = conceal_max;
+ else
+ endBand = pRvlc->maxSfbTransmitted-1;
+
+ for (group=conceal_group_min; group <= conceal_group_max; group++) {
+ for (band=startBand; band <= endBand; band++) {
+ bnds = 16*group+band;
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0;
+ break;
+
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) {
+ commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
+ }
+ else {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ }
+ break;
+
+ case NOISE_HCB:
+ if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB) ) {
+ commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
+ } else {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ }
+ break;
+
+ default:
+ if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB)
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB)
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB)
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) )
+ {
+ commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
+ } else {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ }
+ break;
+ }
+ }
+ startBand = 0;
+ if ((group+1) == conceal_group_max)
+ endBand = conceal_max;
+ }
+
+ /* now copy all data to the output buffer which needs not to be concealed */
+ if (conceal_group_min == 0)
+ endBand = conceal_min;
+ else
+ endBand = pRvlc->maxSfbTransmitted;
+ for (group=0; group <= conceal_group_min; group++) {
+ for (band=0; band < endBand; band++) {
+ bnds = 16*group+band;
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ }
+ if ((group+1) == conceal_group_min)
+ endBand = conceal_min;
+ }
+
+ startBand = conceal_max+1;
+ for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) {
+ for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ }
+ startBand = 0;
+ }
+}
+
+/*---------------------------------------------------------------------------------------------
+ function: StatisticalEstimation
+
+ description: This approach by means of statistical estimation is generally performed when
+ both the start value and the end value are different and no further errors have
+ been detected. Considering the forward and backward decoded scalefactors, the
+ set with the lower scalefactors in sum will be considered as the correct one.
+ The scalefactors are differentially encoded. Normally it would reach to compare
+ one pair of the forward and backward decoded scalefactors to specify the lower
+ set. But having detected no further errors does not necessarily mean the absence
+ of errors. Therefore all scalefactors decoded in forward and backward direction
+ are summed up seperately. The set with the lower sum will be used. The strategy
+ must be applied to scalefactors, intensity data and noise energy seperately.
+-----------------------------------------------------------------------------------------------
+ output: Concealed scalefactor, noise energy and intensity data
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+void StatisticalEstimation (CAacDecoderChannelInfo *pAacDecoderChannelInfo)
+{
+ CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ int band,bnds,group;
+ int sumIsFwd,sumIsBwd; /* sum of intensity data forward/backward */
+ int sumNrgFwd,sumNrgBwd; /* sum of noise energy data forward/backward */
+ int sumScfFwd,sumScfBwd; /* sum of scalefactor data forward/backward */
+ int useIsFwd,useNrgFwd,useScfFwd; /* the flags signals the elements which are used for the final result */
+ int MaximumScaleFactorBands;
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
+ MaximumScaleFactorBands = 16;
+ else
+ MaximumScaleFactorBands = 64;
+
+ sumIsFwd = sumIsBwd = sumNrgFwd = sumNrgBwd = sumScfFwd = sumScfBwd = 0;
+ useIsFwd = useNrgFwd = useScfFwd = 0;
+
+ /* calculate sum of each group (scf,nrg,is) of forward and backward direction */
+ for (group=0; group<pRvlc->numWindowGroups; group++) {
+ for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ break;
+
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ sumIsFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ sumIsBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ break;
+
+ case NOISE_HCB:
+ sumNrgFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ sumNrgBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ break ;
+
+ default:
+ sumScfFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ sumScfBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ break;
+ }
+ }
+ }
+
+ /* find for each group (scf,nrg,is) the correct direction */
+ if ( sumIsFwd < sumIsBwd )
+ useIsFwd = 1;
+
+ if ( sumNrgFwd < sumNrgBwd )
+ useNrgFwd = 1;
+
+ if ( sumScfFwd < sumScfBwd )
+ useScfFwd = 1;
+
+ /* conceal each group (scf,nrg,is) */
+ for (group=0; group<pRvlc->numWindowGroups; group++) {
+ for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ break;
+
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ if (useIsFwd)
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ else
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ break;
+
+ case NOISE_HCB:
+ if (useNrgFwd)
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ else
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ break ;
+
+ default:
+ if (useScfFwd)
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
+ else
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
+ break;
+ }
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------------
+ description: Approach by means of predictive interpolation
+ This approach by means of predictive estimation is generally performed when
+ the error cannot be isolated between 'conceal_min' and 'conceal_max', the
+ 'sf_concealment' flag is set and the previous frame has the same block type
+ as the current frame. Check for each scalefactorband if the same type of data
+ (scalefactor, internsity data, noise energies) is transmitted. If so use the
+ scalefactor (intensity data, noise energy) in the current frame. Otherwise set
+ the scalefactor (intensity data, noise energy) for this scalefactorband to zero.
+-----------------------------------------------------------------------------------------------
+ output: Concealed scalefactor, noise energy and intensity data
+-----------------------------------------------------------------------------------------------
+ return: -
+-------------------------------------------------------------------------------------------- */
+
+void PredictiveInterpolation (
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
+ )
+{
+ CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
+ int band,bnds,group;
+ int MaximumScaleFactorBands;
+ int commonMin;
+
+ if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
+ MaximumScaleFactorBands = 16;
+ else
+ MaximumScaleFactorBands = 64;
+
+ for (group=0; group<pRvlc->numWindowGroups; group++) {
+ for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
+ bnds = 16*group+band;
+ switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
+ case ZERO_HCB:
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0;
+ break;
+
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) {
+ commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
+ }
+ else {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110;
+ }
+ break;
+
+ case NOISE_HCB:
+ if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB) ) {
+ commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
+ }
+ else {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110;
+ }
+ break;
+
+ default:
+ if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB)
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB)
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB)
+ && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) ) {
+ commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
+ }
+ else {
+ pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0;
+ }
+ break;
+ }
+ }
+ }
+}
+
diff --git a/libAACdec/src/rvlcconceal.h b/libAACdec/src/rvlcconceal.h
new file mode 100644
index 0000000..0be0afa
--- /dev/null
+++ b/libAACdec/src/rvlcconceal.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+ $Id$
+
+****************************************************************************/
+/*!
+ \file
+ \brief rvlc concealment
+ \author Josef Hoepfl
+*/
+
+#ifndef RVLCCONCEAL_H
+#define RVLCCONCEAL_H
+
+
+
+#include "rvlc.h"
+
+void BidirectionalEstimation_UseLowerScfOfCurrentFrame(CAacDecoderChannelInfo *pAacDecoderChannelInfo);
+
+void BidirectionalEstimation_UseScfOfPrevFrameAsReference(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
+ );
+
+void StatisticalEstimation (CAacDecoderChannelInfo *pAacDecoderChannelInfo);
+
+void PredictiveInterpolation (
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo,
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
+ );
+
+
+#endif /* RVLCCONCEAL_H */
diff --git a/libAACdec/src/stereo.cpp b/libAACdec/src/stereo.cpp
new file mode 100644
index 0000000..b2e5e79
--- /dev/null
+++ b/libAACdec/src/stereo.cpp
@@ -0,0 +1,235 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: joint stereo processing
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#include "stereo.h"
+
+
+#include "aac_rom.h"
+#include "FDK_bitstream.h"
+#include "channelinfo.h"
+
+enum
+{
+ L = 0,
+ R = 1
+};
+
+
+int CJointStereo_Read(
+ HANDLE_FDK_BITSTREAM bs,
+ CJointStereoData *pJointStereoData,
+ const int windowGroups,
+ const int scaleFactorBandsTransmitted,
+ const UINT flags
+ )
+{
+ int group,band;
+
+ pJointStereoData->MsMaskPresent = (UCHAR) FDKreadBits(bs,2);
+
+ FDKmemclear(pJointStereoData->MsUsed, scaleFactorBandsTransmitted*sizeof(UCHAR));
+
+ switch (pJointStereoData->MsMaskPresent)
+ {
+ case 0 : /* no M/S */
+ /* all flags are already cleared */
+ break ;
+
+ case 1 : /* read ms_used */
+
+ for (group=0; group<windowGroups; group++)
+ {
+ for (band=0; band<scaleFactorBandsTransmitted; band++)
+ {
+ pJointStereoData->MsUsed[band] |= (FDKreadBits(bs,1) << group);
+ }
+ }
+ break ;
+
+ case 2 : /* full spectrum M/S */
+
+ for (band=0; band<scaleFactorBandsTransmitted; band++)
+ {
+ pJointStereoData->MsUsed[band] = 255 ; /* set all flags to 1 */
+ }
+ break ;
+ }
+
+ return 0;
+}
+
+void CJointStereo_ApplyMS(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
+ const SHORT *pScaleFactorBandOffsets,
+ const UCHAR *pWindowGroupLength,
+ const int windowGroups,
+ const int scaleFactorBandsTransmittedL,
+ const int scaleFactorBandsTransmittedR
+ )
+{
+ CJointStereoData *pJointStereoData = &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
+ int window, group, scaleFactorBandsTransmitted;
+
+ FDK_ASSERT(scaleFactorBandsTransmittedL == scaleFactorBandsTransmittedR);
+ scaleFactorBandsTransmitted = scaleFactorBandsTransmittedL;
+ for (window = 0, group = 0; group < windowGroups; group++)
+ {
+ UCHAR groupMask = 1 << group;
+
+ for (int groupwin=0; groupwin<pWindowGroupLength[group]; groupwin++, window++)
+ {
+ int band;
+ FIXP_DBL *leftSpectrum, *rightSpectrum;
+ SHORT *leftScale = &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window*16];
+ SHORT *rightScale = &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window*16];
+
+ leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, window, pAacDecoderChannelInfo[L]->granuleLength);
+ rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, window, pAacDecoderChannelInfo[R]->granuleLength);
+
+ for (band=0; band<scaleFactorBandsTransmitted; band++)
+ {
+ if (pJointStereoData->MsUsed[band] & groupMask)
+ {
+ int lScale=leftScale[band];
+ int rScale=rightScale[band];
+ int commonScale=lScale > rScale ? lScale:rScale;
+
+ /* ISO/IEC 14496-3 Chapter 4.6.8.1.1 :
+ M/S joint channel coding can only be used if common_window is ‘1’. */
+ FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
+ FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
+
+ commonScale++;
+ leftScale[band]=commonScale;
+ rightScale[band]=commonScale;
+
+ lScale = fMin(DFRACT_BITS-1, commonScale - lScale);
+ rScale = fMin(DFRACT_BITS-1, commonScale - rScale);
+
+ FDK_ASSERT(lScale >= 0 && rScale >= 0);
+
+ for (int index=pScaleFactorBandOffsets[band]; index<pScaleFactorBandOffsets[band+1]; index++)
+ {
+ FIXP_DBL leftCoefficient = leftSpectrum [index] ;
+ FIXP_DBL rightCoefficient = rightSpectrum [index] ;
+
+ leftCoefficient >>= lScale ;
+ rightCoefficient >>= rScale ;
+
+ leftSpectrum [index] = leftCoefficient + rightCoefficient ;
+ rightSpectrum [index] = leftCoefficient - rightCoefficient ;
+ }
+ }
+ }
+ }
+ }
+
+ /* Reset MsUsed flags if no explicit signalling was transmitted. Necessary for intensity coding.
+ PNS correlation signalling was mapped before calling CJointStereo_ApplyMS(). */
+ if (pJointStereoData->MsMaskPresent == 2) {
+ FDKmemclear(pJointStereoData->MsUsed, JointStereoMaximumBands * sizeof(UCHAR));
+ }
+}
+
+void CJointStereo_ApplyIS(
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
+ const SHORT *pScaleFactorBandOffsets,
+ const UCHAR *pWindowGroupLength,
+ const int windowGroups,
+ const int scaleFactorBandsTransmitted,
+ const UINT CommonWindow
+ )
+{
+ CJointStereoData *pJointStereoData = &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
+
+ for (int window=0,group=0; group<windowGroups; group++)
+ {
+ UCHAR *CodeBook;
+ SHORT *ScaleFactor;
+ UCHAR groupMask = 1 << group;
+
+ CodeBook = &pAacDecoderChannelInfo[R]->pDynData->aCodeBook[group*16];
+ ScaleFactor = &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group*16];
+
+ for (int groupwin=0; groupwin<pWindowGroupLength[group]; groupwin++, window++)
+ {
+ FIXP_DBL *leftSpectrum, *rightSpectrum;
+ SHORT *leftScale = &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window*16];
+ SHORT *rightScale = &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window*16];
+ int band;
+
+ leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, window, pAacDecoderChannelInfo[L]->granuleLength);
+ rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, window, pAacDecoderChannelInfo[R]->granuleLength);
+
+ for (band=0; band<scaleFactorBandsTransmitted; band++)
+ {
+ if ((CodeBook [band] == INTENSITY_HCB) ||
+ (CodeBook [band] == INTENSITY_HCB2))
+ {
+ int bandScale = -(ScaleFactor [band] + 100) ;
+
+ int msb = bandScale >> 2 ;
+ int lsb = bandScale & 0x03 ;
+
+ /* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */
+ FIXP_DBL scale = MantissaTable[lsb][0];
+
+ /* ISO/IEC 14496-3 Chapter 4.6.8.2.3 :
+ The use of intensity stereo coding is signaled by the use of the pseudo codebooks
+ INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only in the right channel of a
+ channel_pair_element() having a common ics_info() (common_window == 1). */
+ FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
+ FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
+
+ rightScale[band] = leftScale[band]+msb+1;
+
+ if (CommonWindow && (pJointStereoData->MsUsed[band] & groupMask))
+ {
+
+ if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */
+ {
+ scale = -scale ;
+ }
+ }
+ else
+ {
+ if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */
+ {
+ scale = -scale ;
+ }
+ }
+
+ for (int index=pScaleFactorBandOffsets[band]; index<pScaleFactorBandOffsets[band+1]; index++)
+ {
+ rightSpectrum[index] = fMult(leftSpectrum[index],scale);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/libAACdec/src/stereo.h b/libAACdec/src/stereo.h
new file mode 100644
index 0000000..afdb110
--- /dev/null
+++ b/libAACdec/src/stereo.h
@@ -0,0 +1,72 @@
+/***************************** MPEG-4 AAC Decoder **************************
+
+ (C) Copyright Fraunhofer IIS (2004)
+ All Rights Reserved
+
+ Please be advised that this software and/or program delivery is
+ Confidential Information of Fraunhofer and subject to and covered by the
+
+ Fraunhofer IIS Software Evaluation Agreement
+ between Google Inc. and Fraunhofer
+ effective and in full force since March 1, 2012.
+
+ You may use this software and/or program only under the terms and
+ conditions described in the above mentioned Fraunhofer IIS Software
+ Evaluation Agreement. Any other and/or further use requires a separate agreement.
+
+
+ $Id$
+ Author(s): Josef Hoepfl
+ Description: joint stereo processing
+
+ This software and/or program is protected by copyright law and international
+ treaties. Any reproduction or distribution of this software and/or program,
+ or any portion of it, may result in severe civil and criminal penalties, and
+ will be prosecuted to the maximum extent possible under law.
+
+******************************************************************************/
+
+#ifndef STEREO_H
+#define STEREO_H
+
+
+
+#include "machine_type.h"
+#include "FDK_bitstream.h"
+
+enum
+{
+ JointStereoMaximumGroups = 8,
+ JointStereoMaximumBands = 64
+};
+
+typedef struct
+{
+ UCHAR MsMaskPresent;
+ UCHAR MsUsed[JointStereoMaximumBands]; /*!< every arry element contains flags for up to 8 groups */
+} CJointStereoData;
+
+
+/*!
+ \brief Read joint stereo data from bitstream
+
+ The function reads joint stereo data from bitstream.
+
+ \param bs bit stream handle data source.
+ \param pJointStereoData pointer to stereo data structure to receive decoded data.
+ \param windowGroups number of window groups.
+ \param scaleFactorBandsTransmitted number of transmitted scalefactor bands.
+ \param flags decoder flags
+
+ \return 0 on success, -1 on error.
+*/
+int CJointStereo_Read(
+ HANDLE_FDK_BITSTREAM bs,
+ CJointStereoData *pJointStereoData,
+ int windowGroups,
+ int scaleFactorBandsTransmitted,
+ UINT flags
+ );
+
+
+#endif /* #ifndef STEREO_H */