diff options
author | Dave Burke <daveburke@google.com> | 2012-04-17 09:51:45 -0700 |
---|---|---|
committer | Dave Burke <daveburke@google.com> | 2012-04-17 23:04:43 -0700 |
commit | 9bf37cc9712506b2483650c82d3c41152337ef7e (patch) | |
tree | 77db44e2bae06e3d144b255628be2b7a55c581d3 /libAACdec | |
parent | a37315fe10ee143d6d0b28c19d41a476a23e63ea (diff) | |
download | fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.gz fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.tar.bz2 fdk-aac-9bf37cc9712506b2483650c82d3c41152337ef7e.zip |
Fraunhofer AAC codec.
License boilerplate update to follow.
Change-Id: I2810460c11a58b6d148d84673cc031f3685e79b5
Diffstat (limited to 'libAACdec')
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ä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 */ |