mirror of
https://github.com/mstorsjo/fdk-aac.git
synced 2025-02-12 09:30:43 +01:00
Bug: 71430241 Test: CTS DecoderTest and DecoderTestAacDrc original-Change-Id: Iaa20f749b8a04d553b20247cfe1a8930ebbabe30 Apply clang-format also on header files. original-Change-Id: I14de1ef16bbc79ec0283e745f98356a10efeb2e4 Fixes for MPEG-D DRC original-Change-Id: If1de2d74bbbac84b3f67de3b88b83f6a23b8a15c Catch unsupported tw_mdct at an early stage original-Change-Id: Ied9dd00d754162a0e3ca1ae3e6b854315d818afe Fixing PVC transition frames original-Change-Id: Ib75725abe39252806c32d71176308f2c03547a4e Move qmf bands sanity check original-Change-Id: Iab540c3013c174d9490d2ae100a4576f51d8dbc4 Initialize scaling variable original-Change-Id: I3c4087101b70e998c71c1689b122b0d7762e0f9e Add 16 qmf band configuration to getSlotNrgHQ() original-Change-Id: I49a5d30f703a1b126ff163df9656db2540df21f1 Always apply byte alignment at the end of the AudioMuxElement original-Change-Id: I42d560287506d65d4c3de8bfe3eb9a4ebeb4efc7 Setup SBR element only if no parse error exists original-Change-Id: I1915b73704bc80ab882b9173d6bec59cbd073676 Additional array index check in HCR original-Change-Id: I18cc6e501ea683b5009f1bbee26de8ddd04d8267 Fix fade-in index selection in concealment module original-Change-Id: Ibf802ed6ed8c05e9257e1f3b6d0ac1162e9b81c1 Enable explicit backward compatible parser for AAC_LD original-Change-Id: I27e9c678dcb5d40ed760a6d1e06609563d02482d Skip spatial specific config in explicit backward compatible ASC original-Change-Id: Iff7cc365561319e886090cedf30533f562ea4d6e Update flags description in decoder API original-Change-Id: I9a5b4f8da76bb652f5580cbd3ba9760425c43830 Add QMF domain reset function original-Change-Id: I4f89a8a2c0277d18103380134e4ed86996e9d8d6 DRC upgrade v2.1.0 original-Change-Id: I5731c0540139dab220094cd978ef42099fc45b74 Fix integer overflow in sqrtFixp_lookup() original-Change-Id: I429a6f0d19aa2cc957e0f181066f0ca73968c914 Fix integer overflow in invSqrtNorm2() original-Change-Id: I84de5cbf9fb3adeb611db203fe492fabf4eb6155 Fix integer overflow in GenerateRandomVector() original-Change-Id: I3118a641008bd9484d479e5b0b1ee2b5d7d44d74 Fix integer overflow in adjustTimeSlot_EldGrid() original-Change-Id: I29d503c247c5c8282349b79df940416a512fb9d5 Fix integer overflow in FDKsbrEnc_codeEnvelope() original-Change-Id: I6b34b61ebb9d525b0c651ed08de2befc1f801449 Follow-up on: Fix integer overflow in adjustTimeSlot_EldGrid() original-Change-Id: I6f8f578cc7089e5eb7c7b93e580b72ca35ad689a Fix integer overflow in get_pk_v2() original-Change-Id: I63375bed40d45867f6eeaa72b20b1f33e815938c Fix integer overflow in Syn_filt_zero() original-Change-Id: Ie0c02fdfbe03988f9d3b20d10cd9fe4c002d1279 Fix integer overflow in CFac_CalcFacSignal() original-Change-Id: Id2d767c40066c591b51768e978eb8af3b803f0c5 Fix integer overflow in FDKaacEnc_FDKaacEnc_calcPeNoAH() original-Change-Id: Idcbd0f4a51ae2550ed106aa6f3d678d1f9724841 Fix integer overflow in sbrDecoder_calculateGainVec() original-Change-Id: I7081bcbe29c5cede9821b38d93de07c7add2d507 Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I4a95ddc18de150102352d4a1845f06094764c881 Fix integer overflow in Pred_Lt4() original-Change-Id: I4dbd012b2de7d07c3e70a47b92e3bfae8dbc750a Fix integer overflow in FDKsbrEnc_InitSbrFastTransientDetector() original-Change-Id: I788cbec1a4a00f44c2f3a72ad7a4afa219807d04 Fix unsigned integer overflow in FDKaacEnc_WriteBitstream() original-Change-Id: I68fc75166e7d2cd5cd45b18dbe3d8c2a92f1822a Fix unsigned integer overflow in FDK_MetadataEnc_Init() original-Change-Id: Ie8d025f9bcdb2442c704bd196e61065c03c10af4 Fix overflow in pseudo random number generators original-Change-Id: I3e2551ee01356297ca14e3788436ede80bd5513c Fix unsigned integer overflow in sbrDecoder_Parse() original-Change-Id: I3f231b2f437e9c37db4d5b964164686710eee971 Fix unsigned integer overflow in longsub() original-Change-Id: I73c2bc50415cac26f1f5a29e125bbe75f9180a6e Fix unsigned integer overflow in CAacDecoder_DecodeFrame() original-Change-Id: Ifce2db4b1454b46fa5f887e9d383f1cc43b291e4 Fix overflow at CLpdChannelStream_Read() original-Change-Id: Idb9d822ce3a4272e4794b643644f5434e2d4bf3f Fix unsigned integer overflow in Hcr_State_BODY_SIGN_ESC__ESC_WORD() original-Change-Id: I1ccf77c0015684b85534c5eb97162740a870b71c Fix unsigned integer overflow in UsacConfig_Parse() original-Change-Id: Ie6d27f84b6ae7eef092ecbff4447941c77864d9f Fix unsigned integer overflow in aacDecoder_drcParse() original-Change-Id: I713f28e883eea3d70b6fa56a7b8f8c22bcf66ca0 Fix unsigned integer overflow in aacDecoder_drcReadCompression() original-Change-Id: Ia34dfeb88c4705c558bce34314f584965cafcf7a Fix unsigned integer overflow in CDataStreamElement_Read() original-Change-Id: Iae896cc1d11f0a893d21be6aa90bd3e60a2c25f0 Fix unsigned integer overflow in transportDec_AdjustEndOfAccessUnit() original-Change-Id: I64cf29a153ee784bb4a16fdc088baabebc0007dc Fix unsigned integer overflow in transportDec_GetAuBitsRemaining() original-Change-Id: I975b3420faa9c16a041874ba0db82e92035962e4 Fix unsigned integer overflow in extractExtendedData() original-Change-Id: I2a59eb09e2053cfb58dfb75fcecfad6b85a80a8f Fix signed integer overflow in CAacDecoder_ExtPayloadParse() original-Change-Id: I4ad5ca4e3b83b5d964f1c2f8c5e7b17c477c7929 Fix unsigned integer overflow in CAacDecoder_DecodeFrame() original-Change-Id: I29a39df77d45c52a0c9c5c83c1ba81f8d0f25090 Follow-up on: Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I8fb194ffc073a3432a380845be71036a272d388f Fix signed integer overflow in _interpolateDrcGain() original-Change-Id: I879ec9ab14005069a7c47faf80e8bc6e03d22e60 Fix unsigned integer overflow in FDKreadBits() original-Change-Id: I1f47a6a8037ff70375aa8844947d5681bb4287ad Fix unsigned integer overflow in FDKbyteAlign() original-Change-Id: Id5f3a11a0c9e50fc6f76ed6c572dbd4e9f2af766 Fix unsigned integer overflow in FDK_get32() original-Change-Id: I9d33b8e97e3d38cbb80629cb859266ca0acdce96 Fix unsigned integer overflow in FDK_pushBack() original-Change-Id: Ic87f899bc8c6acf7a377a8ca7f3ba74c3a1e1c19 Fix unsigned integer overflow in FDK_pushForward() original-Change-Id: I3b754382f6776a34be1602e66694ede8e0b8effc Fix unsigned integer overflow in ReadPsData() original-Change-Id: I25361664ba8139e32bbbef2ca8c106a606ce9c37 Fix signed integer overflow in E_UTIL_residu() original-Change-Id: I8c3abd1f437ee869caa8fb5903ce7d3d641b6aad REVERT: Follow-up on: Integer overflow in CLpc_SynthesisLattice(). original-Change-Id: I3d340099acb0414795c8dfbe6362bc0a8f045f9b Follow-up on: Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I4aedb8b3a187064e9f4d985175aa55bb99cc7590 Follow-up on: Fix unsigned integer overflow in aacDecoder_drcParse() original-Change-Id: I2aa2e13916213bf52a67e8b0518e7bf7e57fb37d Fix integer overflow in acelp original-Change-Id: Ie6390c136d84055f8b728aefbe4ebef6e029dc77 Fix unsigned integer overflow in aacDecoder_UpdateBitStreamCounters() original-Change-Id: I391ffd97ddb0b2c184cba76139bfb356a3b4d2e2 Adjust concealment default settings original-Change-Id: I6a95db935a327c47df348030bcceafcb29f54b21 Saturate estimatedStartPos original-Change-Id: I27be2085e0ae83ec9501409f65e003f6bcba1ab6 Negative shift exponent in _interpolateDrcGain() original-Change-Id: I18edb26b26d002aafd5e633d4914960f7a359c29 Negative shift exponent in calculateICC() original-Change-Id: I3dcd2ae98d2eb70ee0d59750863cbb2a6f4f8aba Too large shift exponent in FDK_put() original-Change-Id: Ib7d9aaa434d2d8de4a13b720ca0464b31ca9b671 Too large shift exponent in CalcInvLdData() original-Change-Id: I43e6e78d4cd12daeb1dcd5d82d1798bdc2550262 Member access within null pointer of type SBR_CHANNEL original-Change-Id: Idc5e4ea8997810376d2f36bbdf628923b135b097 Member access within null pointer of type CpePersistentData original-Change-Id: Ib6c91cb0d37882768e5baf63324e429589de0d9d Member access within null pointer FDKaacEnc_psyMain() original-Change-Id: I7729b7f4479970531d9dc823abff63ca52e01997 Member access within null pointer FDKaacEnc_GetPnsParam() original-Change-Id: I9aa3b9f3456ae2e0f7483dbd5b3dde95fc62da39 Member access within null pointer FDKsbrEnc_EnvEncodeFrame() original-Change-Id: I67936f90ea714e90b3e81bc0dd1472cc713eb23a Add HCR sanity check original-Change-Id: I6c1d9732ebcf6af12f50b7641400752f74be39f7 Fix memory issue for HBE edge case with 8:3 SBR original-Change-Id: I11ea58a61e69fbe8bf75034b640baee3011e63e9 Additional SBR parametrization sanity check for ELD original-Change-Id: Ie26026fbfe174c2c7b3691f6218b5ce63e322140 Add MPEG-D DRC channel layout check original-Change-Id: Iea70a74f171b227cce636a9eac4ba662777a2f72 Additional out-of-bounds checks in MPEG-D DRC original-Change-Id: Ife4a8c3452c6fde8a0a09e941154a39a769777d4 Change-Id: Ic63cb2f628720f54fe9b572b0cb528e2599c624e
2028 lines
69 KiB
C++
2028 lines
69 KiB
C++
/* -----------------------------------------------------------------------------
|
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
|
|
© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
|
|
Forschung e.V. All rights reserved.
|
|
|
|
1. INTRODUCTION
|
|
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
|
|
that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
|
|
scheme for digital audio. This FDK AAC Codec software is intended to be used on
|
|
a wide variety of Android devices.
|
|
|
|
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
|
|
general perceptual audio codecs. AAC-ELD is considered the best-performing
|
|
full-bandwidth communications codec by independent studies and is widely
|
|
deployed. AAC has been standardized by ISO and IEC as part of the MPEG
|
|
specifications.
|
|
|
|
Patent licenses for necessary patent claims for the FDK AAC Codec (including
|
|
those of Fraunhofer) may be obtained through Via Licensing
|
|
(www.vialicensing.com) or through the respective patent owners individually for
|
|
the purpose of encoding or decoding bit streams in products that are compliant
|
|
with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
|
|
Android devices already license these patent claims through Via Licensing or
|
|
directly from the patent owners, and therefore FDK AAC Codec software may
|
|
already be covered under those patent licenses when it is used for those
|
|
licensed purposes only.
|
|
|
|
Commercially-licensed AAC software libraries, including floating-point versions
|
|
with enhanced sound quality, are also available from Fraunhofer. Users are
|
|
encouraged to check the Fraunhofer website for additional applications
|
|
information and documentation.
|
|
|
|
2. COPYRIGHT LICENSE
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted without payment of copyright license fees provided that you
|
|
satisfy the following conditions:
|
|
|
|
You must retain the complete text of this software license in redistributions of
|
|
the FDK AAC Codec or your modifications thereto in source code form.
|
|
|
|
You must retain the complete text of this software license in the documentation
|
|
and/or other materials provided with redistributions of the FDK AAC Codec or
|
|
your modifications thereto in binary form. You must make available free of
|
|
charge copies of the complete source code of the FDK AAC Codec and your
|
|
modifications thereto to recipients of copies in binary form.
|
|
|
|
The name of Fraunhofer may not be used to endorse or promote products derived
|
|
from this library without prior written permission.
|
|
|
|
You may not charge copyright license fees for anyone to use, copy or distribute
|
|
the FDK AAC Codec software or your modifications thereto.
|
|
|
|
Your modified versions of the FDK AAC Codec must carry prominent notices stating
|
|
that you changed the software and the date of any change. For modified versions
|
|
of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
|
|
must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
|
|
AAC Codec Library for Android."
|
|
|
|
3. NO PATENT LICENSE
|
|
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
|
|
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
|
|
Fraunhofer provides no warranty of patent non-infringement with respect to this
|
|
software.
|
|
|
|
You may use this FDK AAC Codec software or modifications thereto only for
|
|
purposes that are authorized by appropriate patent licenses.
|
|
|
|
4. DISCLAIMER
|
|
|
|
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
|
|
holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
including but not limited to the implied warranties of merchantability and
|
|
fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
|
|
or consequential damages, including but not limited to procurement of substitute
|
|
goods or services; loss of use, data, or profits, or business interruption,
|
|
however caused and on any theory of liability, whether in contract, strict
|
|
liability, or tort (including negligence), arising in any way out of the use of
|
|
this software, even if advised of the possibility of such damage.
|
|
|
|
5. CONTACT INFORMATION
|
|
|
|
Fraunhofer Institute for Integrated Circuits IIS
|
|
Attention: Audio and Multimedia Departments - FDK AAC LL
|
|
Am Wolfsmantel 33
|
|
91058 Erlangen, Germany
|
|
|
|
www.iis.fraunhofer.de/amm
|
|
amm-info@iis.fraunhofer.de
|
|
----------------------------------------------------------------------------- */
|
|
|
|
/************************* MPEG-D DRC decoder library **************************
|
|
|
|
Author(s):
|
|
|
|
Description:
|
|
|
|
*******************************************************************************/
|
|
|
|
#include "fixpoint_math.h"
|
|
#include "drcDec_reader.h"
|
|
#include "drcDec_tools.h"
|
|
#include "drcDec_rom.h"
|
|
#include "drcDecoder.h"
|
|
|
|
/* MPEG-D DRC AMD 1 */
|
|
|
|
#define UNIDRCCONFEXT_PARAM_DRC 0x1
|
|
#define UNIDRCCONFEXT_V1 0x2
|
|
#define UNIDRCLOUDEXT_EQ 0x1
|
|
|
|
#define UNIDRCGAINEXT_TERM 0x0
|
|
#define UNIDRCLOUDEXT_TERM 0x0
|
|
#define UNIDRCCONFEXT_TERM 0x0
|
|
|
|
static int _getZ(const int nNodesMax) {
|
|
/* Z is the minimum codeword length that is needed to encode all possible
|
|
* timeDelta values */
|
|
/* Z = ceil(log2(2*nNodesMax)) */
|
|
int Z = 1;
|
|
while ((1 << Z) < (2 * nNodesMax)) {
|
|
Z++;
|
|
}
|
|
return Z;
|
|
}
|
|
|
|
static int _getTimeDeltaMin(const GAIN_SET* pGset, const int deltaTminDefault) {
|
|
if (pGset->timeDeltaMinPresent) {
|
|
return pGset->timeDeltaMin;
|
|
} else {
|
|
return deltaTminDefault;
|
|
}
|
|
}
|
|
|
|
/* compare and assign */
|
|
static inline int _compAssign(UCHAR* dest, const UCHAR src) {
|
|
int diff = 0;
|
|
if (*dest != src) diff = 1;
|
|
*dest = src;
|
|
return diff;
|
|
}
|
|
|
|
static inline int _compAssign(ULONG* dest, const ULONG src) {
|
|
int diff = 0;
|
|
if (*dest != src) diff = 1;
|
|
*dest = src;
|
|
return diff;
|
|
}
|
|
|
|
typedef const SCHAR (*Huffman)[2];
|
|
|
|
int _decodeHuffmanCW(Huffman h, /*!< pointer to huffman codebook table */
|
|
HANDLE_FDK_BITSTREAM hBs) /*!< Handle to bitbuffer */
|
|
{
|
|
SCHAR index = 0;
|
|
int value, bit;
|
|
|
|
while (index >= 0) {
|
|
bit = FDKreadBits(hBs, 1);
|
|
index = h[index][bit];
|
|
}
|
|
|
|
value = index + 64; /* Add offset */
|
|
|
|
return value;
|
|
}
|
|
|
|
/**********/
|
|
/* uniDrc */
|
|
/**********/
|
|
|
|
DRC_ERROR
|
|
drcDec_readUniDrc(HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig,
|
|
HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet,
|
|
const int frameSize, const int deltaTminDefault,
|
|
HANDLE_UNI_DRC_GAIN hUniDrcGain) {
|
|
DRC_ERROR err = DE_OK;
|
|
int loudnessInfoSetPresent, uniDrcConfigPresent;
|
|
|
|
loudnessInfoSetPresent = FDKreadBits(hBs, 1);
|
|
if (loudnessInfoSetPresent) {
|
|
uniDrcConfigPresent = FDKreadBits(hBs, 1);
|
|
if (uniDrcConfigPresent) {
|
|
err = drcDec_readUniDrcConfig(hBs, hUniDrcConfig);
|
|
if (err) return err;
|
|
}
|
|
err = drcDec_readLoudnessInfoSet(hBs, hLoudnessInfoSet);
|
|
if (err) return err;
|
|
}
|
|
|
|
if (hUniDrcGain != NULL) {
|
|
err = drcDec_readUniDrcGain(hBs, hUniDrcConfig, frameSize, deltaTminDefault,
|
|
hUniDrcGain);
|
|
if (err) return err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/**************/
|
|
/* uniDrcGain */
|
|
/**************/
|
|
|
|
static FIXP_SGL _decodeGainInitial(
|
|
HANDLE_FDK_BITSTREAM hBs, const GAIN_CODING_PROFILE gainCodingProfile) {
|
|
int sign, magn;
|
|
FIXP_SGL gainInitial = (FIXP_SGL)0;
|
|
switch (gainCodingProfile) {
|
|
case GCP_REGULAR:
|
|
sign = FDKreadBits(hBs, 1);
|
|
magn = FDKreadBits(hBs, 8);
|
|
|
|
gainInitial =
|
|
(FIXP_SGL)(magn << (FRACT_BITS - 1 - 3 - 7)); /* magn * 0.125; */
|
|
if (sign) gainInitial = -gainInitial;
|
|
break;
|
|
case GCP_FADING:
|
|
sign = FDKreadBits(hBs, 1);
|
|
if (sign == 0)
|
|
gainInitial = (FIXP_SGL)0;
|
|
else {
|
|
magn = FDKreadBits(hBs, 10);
|
|
gainInitial = -(FIXP_SGL)(
|
|
(magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */
|
|
}
|
|
break;
|
|
case GCP_CLIPPING_DUCKING:
|
|
sign = FDKreadBits(hBs, 1);
|
|
if (sign == 0)
|
|
gainInitial = (FIXP_SGL)0;
|
|
else {
|
|
magn = FDKreadBits(hBs, 8);
|
|
gainInitial = -(FIXP_SGL)(
|
|
(magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */
|
|
}
|
|
break;
|
|
case GCP_CONSTANT:
|
|
break;
|
|
}
|
|
return gainInitial;
|
|
}
|
|
|
|
static int _decodeNNodes(HANDLE_FDK_BITSTREAM hBs) {
|
|
int nNodes = 0, endMarker = 0;
|
|
|
|
/* decode number of nodes */
|
|
while (endMarker != 1) {
|
|
nNodes++;
|
|
if (nNodes >= 128) break;
|
|
endMarker = FDKreadBits(hBs, 1);
|
|
}
|
|
return nNodes;
|
|
}
|
|
|
|
static void _decodeGains(HANDLE_FDK_BITSTREAM hBs,
|
|
const GAIN_CODING_PROFILE gainCodingProfile,
|
|
const int nNodes, GAIN_NODE* pNodes) {
|
|
int k, deltaGain;
|
|
Huffman deltaGainCodebook;
|
|
|
|
pNodes[0].gainDb = _decodeGainInitial(hBs, gainCodingProfile);
|
|
|
|
if (gainCodingProfile == GCP_CLIPPING_DUCKING) {
|
|
deltaGainCodebook = (Huffman)&deltaGain_codingProfile_2_huffman;
|
|
} else {
|
|
deltaGainCodebook = (Huffman)&deltaGain_codingProfile_0_1_huffman;
|
|
}
|
|
|
|
for (k = 1; k < nNodes; k++) {
|
|
deltaGain = _decodeHuffmanCW(deltaGainCodebook, hBs);
|
|
if (k >= 16) continue;
|
|
/* gain_dB_e = 7 */
|
|
pNodes[k].gainDb =
|
|
pNodes[k - 1].gainDb +
|
|
(FIXP_SGL)(deltaGain << (FRACT_BITS - 1 - 7 -
|
|
3)); /* pNodes[k-1].gainDb + 0.125*deltaGain */
|
|
}
|
|
}
|
|
|
|
static void _decodeSlopes(HANDLE_FDK_BITSTREAM hBs,
|
|
const GAIN_INTERPOLATION_TYPE gainInterpolationType,
|
|
const int nNodes, GAIN_NODE* pNodes) {
|
|
int k = 0;
|
|
|
|
if (gainInterpolationType == GIT_SPLINE) {
|
|
/* decode slope steepness */
|
|
for (k = 0; k < nNodes; k++) {
|
|
_decodeHuffmanCW((Huffman)&slopeSteepness_huffman, hBs);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int _decodeTimeDelta(HANDLE_FDK_BITSTREAM hBs, const int Z) {
|
|
int prefix, mu;
|
|
|
|
prefix = FDKreadBits(hBs, 2);
|
|
switch (prefix) {
|
|
case 0x0:
|
|
return 1;
|
|
case 0x1:
|
|
mu = FDKreadBits(hBs, 2);
|
|
return mu + 2;
|
|
case 0x2:
|
|
mu = FDKreadBits(hBs, 3);
|
|
return mu + 6;
|
|
case 0x3:
|
|
mu = FDKreadBits(hBs, Z);
|
|
return mu + 14;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void _decodeTimes(HANDLE_FDK_BITSTREAM hBs, const int deltaTmin,
|
|
const int frameSize, const int fullFrame,
|
|
const int timeOffset, const int Z, const int nNodes,
|
|
GAIN_NODE* pNodes) {
|
|
int timeDelta, k;
|
|
int timeOffs = timeOffset;
|
|
int frameEndFlag, nodeTimeTmp, nodeResFlag;
|
|
|
|
if (fullFrame == 0) {
|
|
frameEndFlag = FDKreadBits(hBs, 1);
|
|
} else {
|
|
frameEndFlag = 1;
|
|
}
|
|
|
|
if (frameEndFlag ==
|
|
1) { /* frameEndFlag == 1 signals that the last node is at the end of the
|
|
DRC frame */
|
|
nodeResFlag = 0;
|
|
for (k = 0; k < nNodes - 1; k++) {
|
|
/* decode a delta time value */
|
|
timeDelta = _decodeTimeDelta(hBs, Z);
|
|
if (k >= (16 - 1)) continue;
|
|
/* frameEndFlag == 1 needs special handling for last node with node
|
|
* reservoir */
|
|
nodeTimeTmp = timeOffs + timeDelta * deltaTmin;
|
|
if (nodeTimeTmp > frameSize + timeOffset) {
|
|
if (nodeResFlag == 0) {
|
|
pNodes[k].time = frameSize + timeOffset;
|
|
nodeResFlag = 1;
|
|
}
|
|
pNodes[k + 1].time = nodeTimeTmp;
|
|
} else {
|
|
pNodes[k].time = nodeTimeTmp;
|
|
}
|
|
timeOffs = nodeTimeTmp;
|
|
}
|
|
if (nodeResFlag == 0) {
|
|
k = fMin(k, 16 - 1);
|
|
pNodes[k].time = frameSize + timeOffset;
|
|
}
|
|
} else {
|
|
for (k = 0; k < nNodes; k++) {
|
|
/* decode a delta time value */
|
|
timeDelta = _decodeTimeDelta(hBs, Z);
|
|
if (k >= 16) continue;
|
|
pNodes[k].time = timeOffs + timeDelta * deltaTmin;
|
|
timeOffs = pNodes[k].time;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _readNodes(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet,
|
|
const int frameSize, const int timeDeltaMin,
|
|
UCHAR* pNNodes, GAIN_NODE* pNodes) {
|
|
int timeOffset, drcGainCodingMode, nNodes;
|
|
int Z = _getZ(frameSize / timeDeltaMin);
|
|
if (gainSet->timeAlignment == 0) {
|
|
timeOffset = -1;
|
|
} else {
|
|
timeOffset = -timeDeltaMin +
|
|
(timeDeltaMin - 1) /
|
|
2; /* timeOffset = - deltaTmin + floor((deltaTmin-1)/2); */
|
|
}
|
|
|
|
drcGainCodingMode = FDKreadBits(hBs, 1);
|
|
if (drcGainCodingMode == 0) {
|
|
/* "simple" mode: only one node at the end of the frame with slope = 0 */
|
|
nNodes = 1;
|
|
pNodes[0].gainDb = _decodeGainInitial(
|
|
hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile);
|
|
pNodes[0].time = frameSize + timeOffset;
|
|
} else {
|
|
nNodes = _decodeNNodes(hBs);
|
|
|
|
_decodeSlopes(hBs, (GAIN_INTERPOLATION_TYPE)gainSet->gainInterpolationType,
|
|
nNodes, pNodes);
|
|
|
|
_decodeTimes(hBs, timeDeltaMin, frameSize, gainSet->fullFrame, timeOffset,
|
|
Z, nNodes, pNodes);
|
|
|
|
_decodeGains(hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile, nNodes,
|
|
pNodes);
|
|
}
|
|
*pNNodes = (UCHAR)nNodes;
|
|
}
|
|
|
|
static void _readDrcGainSequence(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet,
|
|
const int frameSize, const int timeDeltaMin,
|
|
UCHAR* pNNodes, GAIN_NODE pNodes[16]) {
|
|
SHORT timeBufPrevFrame[16], timeBufCurFrame[16];
|
|
int nNodesNodeRes, nNodesCur, k, m;
|
|
|
|
if (gainSet->gainCodingProfile == GCP_CONSTANT) {
|
|
*pNNodes = 1;
|
|
pNodes[0].time = frameSize - 1;
|
|
pNodes[0].gainDb = (FIXP_SGL)0;
|
|
} else {
|
|
_readNodes(hBs, gainSet, frameSize, timeDeltaMin, pNNodes, pNodes);
|
|
|
|
/* count number of nodes in node reservoir */
|
|
nNodesNodeRes = 0;
|
|
nNodesCur = 0;
|
|
/* count and buffer nodes from node reservoir */
|
|
for (k = 0; k < *pNNodes; k++) {
|
|
if (k >= 16) continue;
|
|
if (pNodes[k].time >= frameSize) {
|
|
/* write node reservoir times into buffer */
|
|
timeBufPrevFrame[nNodesNodeRes] = pNodes[k].time;
|
|
nNodesNodeRes++;
|
|
} else { /* times from current frame */
|
|
timeBufCurFrame[nNodesCur] = pNodes[k].time;
|
|
nNodesCur++;
|
|
}
|
|
}
|
|
/* compose right time order (bit reservoir first) */
|
|
for (k = 0; k < nNodesNodeRes; k++) {
|
|
/* subtract two time frameSize: one to remove node reservoir offset and
|
|
* one to get the negative index relative to the current frame
|
|
*/
|
|
pNodes[k].time = timeBufPrevFrame[k] - 2 * frameSize;
|
|
}
|
|
/* ...and times from current frame */
|
|
for (m = 0; m < nNodesCur; m++, k++) {
|
|
pNodes[k].time = timeBufCurFrame[m];
|
|
}
|
|
}
|
|
}
|
|
|
|
static DRC_ERROR _readUniDrcGainExtension(HANDLE_FDK_BITSTREAM hBs,
|
|
UNI_DRC_GAIN_EXTENSION* pExt) {
|
|
DRC_ERROR err = DE_OK;
|
|
int k, bitSizeLen, extSizeBits, bitSize;
|
|
|
|
k = 0;
|
|
pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4);
|
|
while (pExt->uniDrcGainExtType[k] != UNIDRCGAINEXT_TERM) {
|
|
if (k >= (8 - 1)) return DE_MEMORY_ERROR;
|
|
bitSizeLen = FDKreadBits(hBs, 3);
|
|
extSizeBits = bitSizeLen + 4;
|
|
|
|
bitSize = FDKreadBits(hBs, extSizeBits);
|
|
pExt->extBitSize[k] = bitSize + 1;
|
|
|
|
switch (pExt->uniDrcGainExtType[k]) {
|
|
/* add future extensions here */
|
|
default:
|
|
FDKpushFor(hBs, pExt->extBitSize[k]);
|
|
break;
|
|
}
|
|
k++;
|
|
pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
DRC_ERROR
|
|
drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs,
|
|
HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int frameSize,
|
|
const int deltaTminDefault,
|
|
HANDLE_UNI_DRC_GAIN hUniDrcGain) {
|
|
DRC_ERROR err = DE_OK;
|
|
int seq, gainSequenceCount;
|
|
DRC_COEFFICIENTS_UNI_DRC* pCoef =
|
|
selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED);
|
|
if (pCoef == NULL) return DE_OK;
|
|
if (hUniDrcGain == NULL) return DE_OK; /* hUniDrcGain not initialized yet */
|
|
|
|
gainSequenceCount = fMin(pCoef->gainSequenceCount, (UCHAR)12);
|
|
|
|
for (seq = 0; seq < gainSequenceCount; seq++) {
|
|
UCHAR index = pCoef->gainSetIndexForGainSequence[seq];
|
|
GAIN_SET* gainSet;
|
|
int timeDeltaMin;
|
|
UCHAR tmpNNodes = 0;
|
|
GAIN_NODE tmpNodes[16];
|
|
|
|
if ((index >= pCoef->gainSetCount) || (index >= 12)) return DE_NOT_OK;
|
|
gainSet = &(pCoef->gainSet[index]);
|
|
|
|
timeDeltaMin = _getTimeDeltaMin(gainSet, deltaTminDefault);
|
|
|
|
_readDrcGainSequence(hBs, gainSet, frameSize, timeDeltaMin, &tmpNNodes,
|
|
tmpNodes);
|
|
|
|
hUniDrcGain->nNodes[seq] = tmpNNodes;
|
|
FDKmemcpy(hUniDrcGain->gainNode[seq], tmpNodes,
|
|
fMin(tmpNNodes, (UCHAR)16) * sizeof(GAIN_NODE));
|
|
}
|
|
|
|
hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1);
|
|
if (hUniDrcGain->uniDrcGainExtPresent == 1) {
|
|
err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension));
|
|
if (err) return err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/****************/
|
|
/* uniDrcConfig */
|
|
/****************/
|
|
|
|
static void _decodeDuckingModification(HANDLE_FDK_BITSTREAM hBs,
|
|
DUCKING_MODIFICATION* pDMod, int isBox) {
|
|
int bsDuckingScaling, sigma, mu;
|
|
|
|
if (isBox) FDKpushFor(hBs, 7); /* reserved */
|
|
pDMod->duckingScalingPresent = FDKreadBits(hBs, 1);
|
|
|
|
if (pDMod->duckingScalingPresent) {
|
|
if (isBox) FDKpushFor(hBs, 4); /* reserved */
|
|
bsDuckingScaling = FDKreadBits(hBs, 4);
|
|
sigma = bsDuckingScaling >> 3;
|
|
mu = bsDuckingScaling & 0x7;
|
|
|
|
if (sigma) {
|
|
pDMod->duckingScaling = (FIXP_SGL)(
|
|
(7 - mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 - 0.125 * (1 + mu); */
|
|
} else {
|
|
pDMod->duckingScaling = (FIXP_SGL)(
|
|
(9 + mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 + 0.125 * (1 + mu); */
|
|
}
|
|
} else {
|
|
pDMod->duckingScaling = (FIXP_SGL)(1 << (FRACT_BITS - 1 - 2)); /* 1.0 */
|
|
}
|
|
}
|
|
|
|
static void _decodeGainModification(HANDLE_FDK_BITSTREAM hBs, const int version,
|
|
int bandCount, GAIN_MODIFICATION* pGMod,
|
|
int isBox) {
|
|
int sign, bsGainOffset, bsAttenuationScaling, bsAmplificationScaling;
|
|
|
|
if (version > 0) {
|
|
int b, shapeFilterPresent;
|
|
|
|
if (isBox) {
|
|
FDKpushFor(hBs, 4); /* reserved */
|
|
bandCount = FDKreadBits(hBs, 4);
|
|
}
|
|
|
|
for (b = 0; b < bandCount; b++) {
|
|
if (isBox) {
|
|
FDKpushFor(hBs, 4); /* reserved */
|
|
pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1);
|
|
pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1);
|
|
pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1);
|
|
pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1);
|
|
}
|
|
|
|
if (!isBox)
|
|
pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1);
|
|
if (pGMod[b].targetCharacteristicLeftPresent) {
|
|
if (isBox) FDKpushFor(hBs, 4); /* reserved */
|
|
pGMod[b].targetCharacteristicLeftIndex = FDKreadBits(hBs, 4);
|
|
}
|
|
if (!isBox)
|
|
pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1);
|
|
if (pGMod[b].targetCharacteristicRightPresent) {
|
|
if (isBox) FDKpushFor(hBs, 4); /* reserved */
|
|
pGMod[b].targetCharacteristicRightIndex = FDKreadBits(hBs, 4);
|
|
}
|
|
if (!isBox) pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1);
|
|
if (pGMod[b].gainScalingPresent) {
|
|
bsAttenuationScaling = FDKreadBits(hBs, 4);
|
|
pGMod[b].attenuationScaling = (FIXP_SGL)(
|
|
bsAttenuationScaling
|
|
<< (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */
|
|
bsAmplificationScaling = FDKreadBits(hBs, 4);
|
|
pGMod[b].amplificationScaling = (FIXP_SGL)(
|
|
bsAmplificationScaling
|
|
<< (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */
|
|
}
|
|
if (!isBox) pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1);
|
|
if (pGMod[b].gainOffsetPresent) {
|
|
if (isBox) FDKpushFor(hBs, 2); /* reserved */
|
|
sign = FDKreadBits(hBs, 1);
|
|
bsGainOffset = FDKreadBits(hBs, 5);
|
|
pGMod[b].gainOffset = (FIXP_SGL)(
|
|
(1 + bsGainOffset)
|
|
<< (FRACT_BITS - 1 - 2 - 4)); /* (1+bsGainOffset) * 0.25; */
|
|
if (sign) {
|
|
pGMod[b].gainOffset = -pGMod[b].gainOffset;
|
|
}
|
|
}
|
|
}
|
|
if (bandCount == 1) {
|
|
shapeFilterPresent = FDKreadBits(hBs, 1);
|
|
if (shapeFilterPresent) {
|
|
if (isBox) FDKpushFor(hBs, 3); /* reserved */
|
|
FDKpushFor(hBs, 4); /* pGMod->shapeFilterIndex */
|
|
} else {
|
|
if (isBox) FDKpushFor(hBs, 7); /* reserved */
|
|
}
|
|
}
|
|
} else {
|
|
int b, gainScalingPresent, gainOffsetPresent;
|
|
FIXP_SGL attenuationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)),
|
|
amplificationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)),
|
|
gainOffset = (FIXP_SGL)0;
|
|
if (isBox) FDKpushFor(hBs, 7); /* reserved */
|
|
gainScalingPresent = FDKreadBits(hBs, 1);
|
|
if (gainScalingPresent) {
|
|
bsAttenuationScaling = FDKreadBits(hBs, 4);
|
|
attenuationScaling = (FIXP_SGL)(
|
|
bsAttenuationScaling
|
|
<< (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */
|
|
bsAmplificationScaling = FDKreadBits(hBs, 4);
|
|
amplificationScaling = (FIXP_SGL)(
|
|
bsAmplificationScaling
|
|
<< (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */
|
|
}
|
|
if (isBox) FDKpushFor(hBs, 7); /* reserved */
|
|
gainOffsetPresent = FDKreadBits(hBs, 1);
|
|
if (gainOffsetPresent) {
|
|
if (isBox) FDKpushFor(hBs, 2); /* reserved */
|
|
sign = FDKreadBits(hBs, 1);
|
|
bsGainOffset = FDKreadBits(hBs, 5);
|
|
gainOffset =
|
|
(FIXP_SGL)((1 + bsGainOffset) << (FRACT_BITS - 1 - 2 -
|
|
4)); /* (1+bsGainOffset) * 0.25; */
|
|
if (sign) {
|
|
gainOffset = -gainOffset;
|
|
}
|
|
}
|
|
for (b = 0; b < 4; b++) {
|
|
pGMod[b].targetCharacteristicLeftPresent = 0;
|
|
pGMod[b].targetCharacteristicRightPresent = 0;
|
|
pGMod[b].gainScalingPresent = gainScalingPresent;
|
|
pGMod[b].attenuationScaling = attenuationScaling;
|
|
pGMod[b].amplificationScaling = amplificationScaling;
|
|
pGMod[b].gainOffsetPresent = gainOffsetPresent;
|
|
pGMod[b].gainOffset = gainOffset;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _readDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs, const int version,
|
|
DRC_CHARACTERISTIC* pDChar, int isBox) {
|
|
if (version == 0) {
|
|
if (isBox) FDKpushFor(hBs, 1); /* reserved */
|
|
pDChar->cicpIndex = FDKreadBits(hBs, 7);
|
|
if (pDChar->cicpIndex > 0) {
|
|
pDChar->present = 1;
|
|
pDChar->isCICP = 1;
|
|
} else {
|
|
pDChar->present = 0;
|
|
}
|
|
} else {
|
|
pDChar->present = FDKreadBits(hBs, 1);
|
|
if (isBox) pDChar->isCICP = FDKreadBits(hBs, 1);
|
|
if (pDChar->present) {
|
|
if (!isBox) pDChar->isCICP = FDKreadBits(hBs, 1);
|
|
if (pDChar->isCICP) {
|
|
if (isBox) FDKpushFor(hBs, 1); /* reserved */
|
|
pDChar->cicpIndex = FDKreadBits(hBs, 7);
|
|
} else {
|
|
pDChar->custom.left = FDKreadBits(hBs, 4);
|
|
pDChar->custom.right = FDKreadBits(hBs, 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _readBandBorder(HANDLE_FDK_BITSTREAM hBs, BAND_BORDER* pBBord,
|
|
int drcBandType, int isBox) {
|
|
if (drcBandType) {
|
|
if (isBox) FDKpushFor(hBs, 4); /* reserved */
|
|
pBBord->crossoverFreqIndex = FDKreadBits(hBs, 4);
|
|
} else {
|
|
if (isBox) FDKpushFor(hBs, 6); /* reserved */
|
|
pBBord->startSubBandIndex = FDKreadBits(hBs, 10);
|
|
}
|
|
}
|
|
|
|
static DRC_ERROR _readGainSet(HANDLE_FDK_BITSTREAM hBs, const int version,
|
|
int* gainSequenceIndex, GAIN_SET* pGSet,
|
|
int isBox) {
|
|
if (isBox) FDKpushFor(hBs, 2); /* reserved */
|
|
pGSet->gainCodingProfile = FDKreadBits(hBs, 2);
|
|
pGSet->gainInterpolationType = FDKreadBits(hBs, 1);
|
|
pGSet->fullFrame = FDKreadBits(hBs, 1);
|
|
pGSet->timeAlignment = FDKreadBits(hBs, 1);
|
|
pGSet->timeDeltaMinPresent = FDKreadBits(hBs, 1);
|
|
|
|
if (pGSet->timeDeltaMinPresent) {
|
|
int bsTimeDeltaMin;
|
|
if (isBox) FDKpushFor(hBs, 5); /* reserved */
|
|
bsTimeDeltaMin = FDKreadBits(hBs, 11);
|
|
pGSet->timeDeltaMin = bsTimeDeltaMin + 1;
|
|
}
|
|
|
|
if (pGSet->gainCodingProfile != GCP_CONSTANT) {
|
|
int i;
|
|
if (isBox) FDKpushFor(hBs, 3); /* reserved */
|
|
pGSet->bandCount = FDKreadBits(hBs, 4);
|
|
if (pGSet->bandCount > 4) return DE_MEMORY_ERROR;
|
|
|
|
if ((pGSet->bandCount > 1) || isBox) {
|
|
pGSet->drcBandType = FDKreadBits(hBs, 1);
|
|
}
|
|
|
|
for (i = 0; i < pGSet->bandCount; i++) {
|
|
if (version == 0) {
|
|
*gainSequenceIndex = (*gainSequenceIndex) + 1;
|
|
} else {
|
|
int indexPresent;
|
|
indexPresent = (isBox) ? 1 : FDKreadBits(hBs, 1);
|
|
if (indexPresent) {
|
|
int bsIndex;
|
|
bsIndex = FDKreadBits(hBs, 6);
|
|
*gainSequenceIndex = bsIndex;
|
|
} else {
|
|
*gainSequenceIndex = (*gainSequenceIndex) + 1;
|
|
}
|
|
}
|
|
pGSet->gainSequenceIndex[i] = *gainSequenceIndex;
|
|
_readDrcCharacteristic(hBs, version, &(pGSet->drcCharacteristic[i]),
|
|
isBox);
|
|
}
|
|
for (i = 1; i < pGSet->bandCount; i++) {
|
|
_readBandBorder(hBs, &(pGSet->bandBorder[i]), pGSet->drcBandType, isBox);
|
|
}
|
|
} else {
|
|
pGSet->bandCount = 1;
|
|
*gainSequenceIndex = (*gainSequenceIndex) + 1;
|
|
pGSet->gainSequenceIndex[0] = *gainSequenceIndex;
|
|
}
|
|
|
|
return DE_OK;
|
|
}
|
|
|
|
static DRC_ERROR _readCustomDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs,
|
|
const CHARACTERISTIC_SIDE side,
|
|
UCHAR* pCharacteristicFormat,
|
|
CUSTOM_DRC_CHAR* pCChar,
|
|
int isBox) {
|
|
if (isBox) FDKpushFor(hBs, 7); /* reserved */
|
|
*pCharacteristicFormat = FDKreadBits(hBs, 1);
|
|
if (*pCharacteristicFormat == CF_SIGMOID) {
|
|
int bsGain, bsIoRatio, bsExp;
|
|
if (isBox) FDKpushFor(hBs, 1); /* reserved */
|
|
bsGain = FDKreadBits(hBs, 6);
|
|
if (side == CS_LEFT) {
|
|
pCChar->sigmoid.gain = (FIXP_SGL)(bsGain << (FRACT_BITS - 1 - 6));
|
|
} else {
|
|
pCChar->sigmoid.gain = (FIXP_SGL)(-bsGain << (FRACT_BITS - 1 - 6));
|
|
}
|
|
bsIoRatio = FDKreadBits(hBs, 4);
|
|
/* pCChar->sigmoid.ioRatio = 0.05 + 0.15 * bsIoRatio; */
|
|
pCChar->sigmoid.ioRatio =
|
|
FL2FXCONST_SGL(0.05f / (float)(1 << 2)) +
|
|
(FIXP_SGL)((((3 * bsIoRatio) << (FRACT_BITS - 1)) / 5) >> 4);
|
|
bsExp = FDKreadBits(hBs, 4);
|
|
if (bsExp < 15) {
|
|
pCChar->sigmoid.exp = (FIXP_SGL)((1 + 2 * bsExp) << (FRACT_BITS - 1 - 5));
|
|
} else {
|
|
pCChar->sigmoid.exp = (FIXP_SGL)MAXVAL_SGL; /* represents infinity */
|
|
}
|
|
pCChar->sigmoid.flipSign = FDKreadBits(hBs, 1);
|
|
} else { /* CF_NODES */
|
|
int i, bsCharacteristicNodeCount, bsNodeLevelDelta, bsNodeGain;
|
|
if (isBox) FDKpushFor(hBs, 6); /* reserved */
|
|
bsCharacteristicNodeCount = FDKreadBits(hBs, 2);
|
|
pCChar->nodes.characteristicNodeCount = bsCharacteristicNodeCount + 1;
|
|
if (pCChar->nodes.characteristicNodeCount > 4) return DE_MEMORY_ERROR;
|
|
pCChar->nodes.nodeLevel[0] = DRC_INPUT_LOUDNESS_TARGET_SGL;
|
|
pCChar->nodes.nodeGain[0] = (FIXP_SGL)0;
|
|
for (i = 0; i < pCChar->nodes.characteristicNodeCount; i++) {
|
|
if (isBox) FDKpushFor(hBs, 3); /* reserved */
|
|
bsNodeLevelDelta = FDKreadBits(hBs, 5);
|
|
if (side == CS_LEFT) {
|
|
pCChar->nodes.nodeLevel[i + 1] =
|
|
pCChar->nodes.nodeLevel[i] -
|
|
(FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7));
|
|
} else {
|
|
pCChar->nodes.nodeLevel[i + 1] =
|
|
pCChar->nodes.nodeLevel[i] +
|
|
(FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7));
|
|
}
|
|
bsNodeGain = FDKreadBits(hBs, 8);
|
|
pCChar->nodes.nodeGain[i + 1] = (FIXP_SGL)(
|
|
(bsNodeGain - 128)
|
|
<< (FRACT_BITS - 1 - 1 - 7)); /* 0.5f * bsNodeGain - 64.0f; */
|
|
}
|
|
}
|
|
return DE_OK;
|
|
}
|
|
|
|
static void _skipLoudEqInstructions(HANDLE_FDK_BITSTREAM hBs) {
|
|
int i;
|
|
int downmixIdPresent, additionalDownmixIdPresent,
|
|
additionalDownmixIdCount = 0;
|
|
int drcSetIdPresent, additionalDrcSetIdPresent, additionalDrcSetIdCount = 0;
|
|
int eqSetIdPresent, additionalEqSetIdPresent, additionalEqSetIdCount = 0;
|
|
int loudEqGainSequenceCount, drcCharacteristicFormatIsCICP;
|
|
|
|
FDKpushFor(hBs, 4); /* loudEqSetId */
|
|
FDKpushFor(hBs, 4); /* drcLocation */
|
|
downmixIdPresent = FDKreadBits(hBs, 1);
|
|
if (downmixIdPresent) {
|
|
FDKpushFor(hBs, 7); /* downmixId */
|
|
additionalDownmixIdPresent = FDKreadBits(hBs, 1);
|
|
if (additionalDownmixIdPresent) {
|
|
additionalDownmixIdCount = FDKreadBits(hBs, 7);
|
|
for (i = 0; i < additionalDownmixIdCount; i++) {
|
|
FDKpushFor(hBs, 7); /* additionalDownmixId */
|
|
}
|
|
}
|
|
}
|
|
|
|
drcSetIdPresent = FDKreadBits(hBs, 1);
|
|
if (drcSetIdPresent) {
|
|
FDKpushFor(hBs, 6); /* drcSetId */
|
|
additionalDrcSetIdPresent = FDKreadBits(hBs, 1);
|
|
if (additionalDrcSetIdPresent) {
|
|
additionalDrcSetIdCount = FDKreadBits(hBs, 6);
|
|
for (i = 0; i < additionalDrcSetIdCount; i++) {
|
|
FDKpushFor(hBs, 6); /* additionalDrcSetId; */
|
|
}
|
|
}
|
|
}
|
|
|
|
eqSetIdPresent = FDKreadBits(hBs, 1);
|
|
if (eqSetIdPresent) {
|
|
FDKpushFor(hBs, 6); /* eqSetId */
|
|
additionalEqSetIdPresent = FDKreadBits(hBs, 1);
|
|
if (additionalEqSetIdPresent) {
|
|
additionalEqSetIdCount = FDKreadBits(hBs, 6);
|
|
for (i = 0; i < additionalEqSetIdCount; i++) {
|
|
FDKpushFor(hBs, 6); /* additionalEqSetId; */
|
|
}
|
|
}
|
|
}
|
|
|
|
FDKpushFor(hBs, 1); /* loudnessAfterDrc */
|
|
FDKpushFor(hBs, 1); /* loudnessAfterEq */
|
|
loudEqGainSequenceCount = FDKreadBits(hBs, 6);
|
|
for (i = 0; i < loudEqGainSequenceCount; i++) {
|
|
FDKpushFor(hBs, 6); /* gainSequenceIndex */
|
|
drcCharacteristicFormatIsCICP = FDKreadBits(hBs, 1);
|
|
if (drcCharacteristicFormatIsCICP) {
|
|
FDKpushFor(hBs, 7); /* drcCharacteristic */
|
|
} else {
|
|
FDKpushFor(hBs, 4); /* drcCharacteristicLeftIndex */
|
|
FDKpushFor(hBs, 4); /* drcCharacteristicRightIndex */
|
|
}
|
|
FDKpushFor(hBs, 6); /* frequencyRangeIndex */
|
|
FDKpushFor(hBs, 3); /* bsLoudEqScaling */
|
|
FDKpushFor(hBs, 5); /* bsLoudEqOffset */
|
|
}
|
|
}
|
|
|
|
static void _skipEqSubbandGainSpline(HANDLE_FDK_BITSTREAM hBs) {
|
|
int nEqNodes, k, bits;
|
|
nEqNodes = FDKreadBits(hBs, 5);
|
|
nEqNodes += 2;
|
|
for (k = 0; k < nEqNodes; k++) {
|
|
bits = FDKreadBits(hBs, 1);
|
|
if (!bits) {
|
|
FDKpushFor(hBs, 4);
|
|
}
|
|
}
|
|
FDKpushFor(hBs, 4 * (nEqNodes - 1));
|
|
bits = FDKreadBits(hBs, 2);
|
|
switch (bits) {
|
|
case 0:
|
|
FDKpushFor(hBs, 5);
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
FDKpushFor(hBs, 4);
|
|
break;
|
|
case 3:
|
|
FDKpushFor(hBs, 3);
|
|
break;
|
|
}
|
|
FDKpushFor(hBs, 5 * (nEqNodes - 1));
|
|
}
|
|
|
|
static void _skipEqCoefficients(HANDLE_FDK_BITSTREAM hBs) {
|
|
int j, k;
|
|
int eqDelayMaxPresent;
|
|
int uniqueFilterBlockCount, filterElementCount, filterElementGainPresent;
|
|
int uniqueTdFilterElementCount, eqFilterFormat, bsRealZeroRadiusOneCount,
|
|
realZeroCount, genericZeroCount, realPoleCount, complexPoleCount,
|
|
firFilterOrder;
|
|
int uniqueEqSubbandGainsCount, eqSubbandGainRepresentation,
|
|
eqSubbandGainCount;
|
|
EQ_SUBBAND_GAIN_FORMAT eqSubbandGainFormat;
|
|
|
|
eqDelayMaxPresent = FDKreadBits(hBs, 1);
|
|
if (eqDelayMaxPresent) {
|
|
FDKpushFor(hBs, 8); /* bsEqDelayMax */
|
|
}
|
|
|
|
uniqueFilterBlockCount = FDKreadBits(hBs, 6);
|
|
for (j = 0; j < uniqueFilterBlockCount; j++) {
|
|
filterElementCount = FDKreadBits(hBs, 6);
|
|
for (k = 0; k < filterElementCount; k++) {
|
|
FDKpushFor(hBs, 6); /* filterElementIndex */
|
|
filterElementGainPresent = FDKreadBits(hBs, 1);
|
|
if (filterElementGainPresent) {
|
|
FDKpushFor(hBs, 10); /* bsFilterElementGain */
|
|
}
|
|
}
|
|
}
|
|
uniqueTdFilterElementCount = FDKreadBits(hBs, 6);
|
|
for (j = 0; j < uniqueTdFilterElementCount; j++) {
|
|
eqFilterFormat = FDKreadBits(hBs, 1);
|
|
if (eqFilterFormat == 0) { /* pole/zero */
|
|
bsRealZeroRadiusOneCount = FDKreadBits(hBs, 3);
|
|
realZeroCount = FDKreadBits(hBs, 6);
|
|
genericZeroCount = FDKreadBits(hBs, 6);
|
|
realPoleCount = FDKreadBits(hBs, 4);
|
|
complexPoleCount = FDKreadBits(hBs, 4);
|
|
FDKpushFor(hBs, 2 * bsRealZeroRadiusOneCount * 1);
|
|
FDKpushFor(hBs, realZeroCount * 8);
|
|
FDKpushFor(hBs, genericZeroCount * 14);
|
|
FDKpushFor(hBs, realPoleCount * 8);
|
|
FDKpushFor(hBs, complexPoleCount * 14);
|
|
} else { /* FIR coefficients */
|
|
firFilterOrder = FDKreadBits(hBs, 7);
|
|
FDKpushFor(hBs, 1);
|
|
FDKpushFor(hBs, (firFilterOrder / 2 + 1) * 11);
|
|
}
|
|
}
|
|
uniqueEqSubbandGainsCount = FDKreadBits(hBs, 6);
|
|
if (uniqueEqSubbandGainsCount > 0) {
|
|
eqSubbandGainRepresentation = FDKreadBits(hBs, 1);
|
|
eqSubbandGainFormat = (EQ_SUBBAND_GAIN_FORMAT)FDKreadBits(hBs, 4);
|
|
switch (eqSubbandGainFormat) {
|
|
case GF_QMF32:
|
|
eqSubbandGainCount = 32;
|
|
break;
|
|
case GF_QMFHYBRID39:
|
|
eqSubbandGainCount = 39;
|
|
break;
|
|
case GF_QMF64:
|
|
eqSubbandGainCount = 64;
|
|
break;
|
|
case GF_QMFHYBRID71:
|
|
eqSubbandGainCount = 71;
|
|
break;
|
|
case GF_QMF128:
|
|
eqSubbandGainCount = 128;
|
|
break;
|
|
case GF_QMFHYBRID135:
|
|
eqSubbandGainCount = 135;
|
|
break;
|
|
case GF_UNIFORM:
|
|
default:
|
|
eqSubbandGainCount = FDKreadBits(hBs, 8);
|
|
eqSubbandGainCount++;
|
|
break;
|
|
}
|
|
for (k = 0; k < uniqueEqSubbandGainsCount; k++) {
|
|
if (eqSubbandGainRepresentation == 1) {
|
|
_skipEqSubbandGainSpline(hBs);
|
|
} else {
|
|
FDKpushFor(hBs, eqSubbandGainCount * 9);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _skipTdFilterCascade(HANDLE_FDK_BITSTREAM hBs,
|
|
const int eqChannelGroupCount) {
|
|
int i, eqCascadeGainPresent, filterBlockCount, eqPhaseAlignmentPresent;
|
|
for (i = 0; i < eqChannelGroupCount; i++) {
|
|
eqCascadeGainPresent = FDKreadBits(hBs, 1);
|
|
if (eqCascadeGainPresent) {
|
|
FDKpushFor(hBs, 10); /* bsEqCascadeGain */
|
|
}
|
|
filterBlockCount = FDKreadBits(hBs, 4);
|
|
FDKpushFor(hBs, filterBlockCount * 7); /* filterBlockIndex */
|
|
}
|
|
eqPhaseAlignmentPresent = FDKreadBits(hBs, 1);
|
|
{
|
|
if (eqPhaseAlignmentPresent) {
|
|
for (i = 0; i < eqChannelGroupCount; i++) {
|
|
FDKpushFor(hBs, (eqChannelGroupCount - i - 1) * 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static DRC_ERROR _skipEqInstructions(HANDLE_FDK_BITSTREAM hBs,
|
|
HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
|
|
DRC_ERROR err = DE_OK;
|
|
int c, i, k, channelCount;
|
|
int downmixIdPresent, downmixId, eqApplyToDownmix, additionalDownmixIdPresent,
|
|
additionalDownmixIdCount = 0;
|
|
int additionalDrcSetIdPresent, additionalDrcSetIdCount;
|
|
int dependsOnEqSetPresent, eqChannelGroupCount, tdFilterCascadePresent,
|
|
subbandGainsPresent, eqTransitionDurationPresent;
|
|
|
|
FDKpushFor(hBs, 6); /* eqSetId */
|
|
FDKpushFor(hBs, 4); /* eqSetComplexityLevel */
|
|
downmixIdPresent = FDKreadBits(hBs, 1);
|
|
if (downmixIdPresent) {
|
|
downmixId = FDKreadBits(hBs, 7);
|
|
eqApplyToDownmix = FDKreadBits(hBs, 1);
|
|
additionalDownmixIdPresent = FDKreadBits(hBs, 1);
|
|
if (additionalDownmixIdPresent) {
|
|
additionalDownmixIdCount = FDKreadBits(hBs, 7);
|
|
FDKpushFor(hBs, additionalDownmixIdCount * 7); /* additionalDownmixId */
|
|
}
|
|
} else {
|
|
downmixId = 0;
|
|
eqApplyToDownmix = 0;
|
|
}
|
|
FDKpushFor(hBs, 6); /* drcSetId */
|
|
additionalDrcSetIdPresent = FDKreadBits(hBs, 1);
|
|
if (additionalDrcSetIdPresent) {
|
|
additionalDrcSetIdCount = FDKreadBits(hBs, 6);
|
|
for (i = 0; i < additionalDrcSetIdCount; i++) {
|
|
FDKpushFor(hBs, 6); /* additionalDrcSetId */
|
|
}
|
|
}
|
|
FDKpushFor(hBs, 16); /* eqSetPurpose */
|
|
dependsOnEqSetPresent = FDKreadBits(hBs, 1);
|
|
if (dependsOnEqSetPresent) {
|
|
FDKpushFor(hBs, 6); /* dependsOnEqSet */
|
|
} else {
|
|
FDKpushFor(hBs, 1); /* noIndependentEqUse */
|
|
}
|
|
|
|
channelCount = hUniDrcConfig->channelLayout.baseChannelCount;
|
|
if ((downmixIdPresent == 1) && (eqApplyToDownmix == 1) && (downmixId != 0) &&
|
|
(downmixId != DOWNMIX_ID_ANY_DOWNMIX) &&
|
|
(additionalDownmixIdCount == 0)) {
|
|
DOWNMIX_INSTRUCTIONS* pDown =
|
|
selectDownmixInstructions(hUniDrcConfig, downmixId);
|
|
if (pDown == NULL) return DE_NOT_OK;
|
|
|
|
channelCount =
|
|
pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/
|
|
} else if ((downmixId == DOWNMIX_ID_ANY_DOWNMIX) ||
|
|
(additionalDownmixIdCount > 1)) {
|
|
channelCount = 1;
|
|
}
|
|
|
|
eqChannelGroupCount = 0;
|
|
for (c = 0; c < channelCount; c++) {
|
|
UCHAR eqChannelGroupForChannel[8];
|
|
int newGroup = 1;
|
|
if (c >= 8) return DE_MEMORY_ERROR;
|
|
eqChannelGroupForChannel[c] = FDKreadBits(hBs, 7);
|
|
for (k = 0; k < c; k++) {
|
|
if (eqChannelGroupForChannel[c] == eqChannelGroupForChannel[k]) {
|
|
newGroup = 0;
|
|
}
|
|
}
|
|
if (newGroup == 1) {
|
|
eqChannelGroupCount += 1;
|
|
}
|
|
}
|
|
tdFilterCascadePresent = FDKreadBits(hBs, 1);
|
|
if (tdFilterCascadePresent) {
|
|
_skipTdFilterCascade(hBs, eqChannelGroupCount);
|
|
}
|
|
subbandGainsPresent = FDKreadBits(hBs, 1);
|
|
if (subbandGainsPresent) {
|
|
FDKpushFor(hBs, eqChannelGroupCount * 6); /* subbandGainsIndex */
|
|
}
|
|
eqTransitionDurationPresent = FDKreadBits(hBs, 1);
|
|
if (eqTransitionDurationPresent) {
|
|
FDKpushFor(hBs, 5); /* bsEqTransitionDuration */
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static void _skipDrcCoefficientsBasic(HANDLE_FDK_BITSTREAM hBs) {
|
|
FDKpushFor(hBs, 4); /* drcLocation */
|
|
FDKpushFor(hBs, 7); /* drcCharacteristic */
|
|
}
|
|
|
|
static DRC_ERROR _readDrcCoefficientsUniDrc(HANDLE_FDK_BITSTREAM hBs,
|
|
const int version,
|
|
DRC_COEFFICIENTS_UNI_DRC* pCoef) {
|
|
DRC_ERROR err = DE_OK;
|
|
int i, bsDrcFrameSize;
|
|
int gainSequenceIndex = -1;
|
|
|
|
pCoef->drcLocation = FDKreadBits(hBs, 4);
|
|
pCoef->drcFrameSizePresent = FDKreadBits(hBs, 1);
|
|
|
|
if (pCoef->drcFrameSizePresent == 1) {
|
|
bsDrcFrameSize = FDKreadBits(hBs, 15);
|
|
pCoef->drcFrameSize = bsDrcFrameSize + 1;
|
|
}
|
|
if (version == 0) {
|
|
int gainSequenceCount = 0, gainSetCount;
|
|
pCoef->characteristicLeftCount = 0;
|
|
pCoef->characteristicRightCount = 0;
|
|
gainSetCount = FDKreadBits(hBs, 6);
|
|
pCoef->gainSetCount = fMin(gainSetCount, 12);
|
|
for (i = 0; i < gainSetCount; i++) {
|
|
GAIN_SET tmpGset;
|
|
FDKmemclear(&tmpGset, sizeof(GAIN_SET));
|
|
err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0);
|
|
if (err) return err;
|
|
gainSequenceCount += tmpGset.bandCount;
|
|
|
|
if (i >= 12) continue;
|
|
pCoef->gainSet[i] = tmpGset;
|
|
}
|
|
pCoef->gainSequenceCount = gainSequenceCount;
|
|
} else { /* (version == 1) */
|
|
UCHAR drcCharacteristicLeftPresent, drcCharacteristicRightPresent;
|
|
UCHAR shapeFiltersPresent, shapeFilterCount, tmpPresent;
|
|
int gainSetCount;
|
|
drcCharacteristicLeftPresent = FDKreadBits(hBs, 1);
|
|
if (drcCharacteristicLeftPresent) {
|
|
pCoef->characteristicLeftCount = FDKreadBits(hBs, 4);
|
|
if ((pCoef->characteristicLeftCount + 1) > 8) return DE_MEMORY_ERROR;
|
|
for (i = 0; i < pCoef->characteristicLeftCount; i++) {
|
|
err = _readCustomDrcCharacteristic(
|
|
hBs, CS_LEFT, &(pCoef->characteristicLeftFormat[i + 1]),
|
|
&(pCoef->customCharacteristicLeft[i + 1]), 0);
|
|
if (err) return err;
|
|
}
|
|
}
|
|
drcCharacteristicRightPresent = FDKreadBits(hBs, 1);
|
|
if (drcCharacteristicRightPresent) {
|
|
pCoef->characteristicRightCount = FDKreadBits(hBs, 4);
|
|
if ((pCoef->characteristicRightCount + 1) > 8) return DE_MEMORY_ERROR;
|
|
for (i = 0; i < pCoef->characteristicRightCount; i++) {
|
|
err = _readCustomDrcCharacteristic(
|
|
hBs, CS_RIGHT, &(pCoef->characteristicRightFormat[i + 1]),
|
|
&(pCoef->customCharacteristicRight[i + 1]), 0);
|
|
if (err) return err;
|
|
}
|
|
}
|
|
shapeFiltersPresent = FDKreadBits(hBs, 1);
|
|
if (shapeFiltersPresent) {
|
|
shapeFilterCount = FDKreadBits(hBs, 4);
|
|
for (i = 0; i < shapeFilterCount; i++) {
|
|
tmpPresent = FDKreadBits(hBs, 1);
|
|
if (tmpPresent) /* lfCutParams */
|
|
FDKpushFor(hBs, 5);
|
|
|
|
tmpPresent = FDKreadBits(hBs, 1);
|
|
if (tmpPresent) /* lfBoostParams */
|
|
FDKpushFor(hBs, 5);
|
|
|
|
tmpPresent = FDKreadBits(hBs, 1);
|
|
if (tmpPresent) /* hfCutParams */
|
|
FDKpushFor(hBs, 5);
|
|
|
|
tmpPresent = FDKreadBits(hBs, 1);
|
|
if (tmpPresent) /* hfBoostParams */
|
|
FDKpushFor(hBs, 5);
|
|
}
|
|
}
|
|
pCoef->gainSequenceCount = FDKreadBits(hBs, 6);
|
|
gainSetCount = FDKreadBits(hBs, 6);
|
|
pCoef->gainSetCount = fMin(gainSetCount, 12);
|
|
for (i = 0; i < gainSetCount; i++) {
|
|
GAIN_SET tmpGset;
|
|
FDKmemclear(&tmpGset, sizeof(GAIN_SET));
|
|
err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0);
|
|
if (err) return err;
|
|
|
|
if (i >= 12) continue;
|
|
pCoef->gainSet[i] = tmpGset;
|
|
}
|
|
}
|
|
for (i = 0; i < 12; i++) {
|
|
pCoef->gainSetIndexForGainSequence[i] = 255;
|
|
}
|
|
for (i = 0; i < pCoef->gainSetCount; i++) {
|
|
int b;
|
|
for (b = 0; b < pCoef->gainSet[i].bandCount; b++) {
|
|
if (pCoef->gainSet[i].gainSequenceIndex[b] >= 12) continue;
|
|
pCoef->gainSetIndexForGainSequence[pCoef->gainSet[i]
|
|
.gainSequenceIndex[b]] = i;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static void _skipDrcInstructionsBasic(HANDLE_FDK_BITSTREAM hBs) {
|
|
int drcSetEffect;
|
|
int additionalDownmixIdPresent, additionalDownmixIdCount,
|
|
limiterPeakTargetPresent;
|
|
int drcSetTargetLoudnessPresent, drcSetTargetLoudnessValueLowerPresent;
|
|
|
|
FDKpushFor(hBs, 6); /* drcSetId */
|
|
FDKpushFor(hBs, 4); /* drcLocation */
|
|
FDKpushFor(hBs, 7); /* downmixId */
|
|
additionalDownmixIdPresent = FDKreadBits(hBs, 1);
|
|
if (additionalDownmixIdPresent) {
|
|
additionalDownmixIdCount = FDKreadBits(hBs, 3);
|
|
FDKpushFor(hBs, 7 * additionalDownmixIdCount); /* additionalDownmixId */
|
|
}
|
|
|
|
drcSetEffect = FDKreadBits(hBs, 16);
|
|
if (!(drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF))) {
|
|
limiterPeakTargetPresent = FDKreadBits(hBs, 1);
|
|
if (limiterPeakTargetPresent) {
|
|
FDKpushFor(hBs, 8); /* bsLimiterPeakTarget */
|
|
}
|
|
}
|
|
|
|
drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1);
|
|
if (drcSetTargetLoudnessPresent) {
|
|
FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueUpper */
|
|
drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1);
|
|
if (drcSetTargetLoudnessValueLowerPresent) {
|
|
FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueLower */
|
|
}
|
|
}
|
|
}
|
|
|
|
static DRC_ERROR _readDrcInstructionsUniDrc(HANDLE_FDK_BITSTREAM hBs,
|
|
const int version,
|
|
HANDLE_UNI_DRC_CONFIG hUniDrcConfig,
|
|
DRC_INSTRUCTIONS_UNI_DRC* pInst) {
|
|
DRC_ERROR err = DE_OK;
|
|
int i, g, c;
|
|
int downmixIdPresent, additionalDownmixIdPresent, additionalDownmixIdCount;
|
|
int bsLimiterPeakTarget, channelCount;
|
|
DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL;
|
|
int repeatParameters, bsRepeatParametersCount;
|
|
int repeatSequenceIndex, bsRepeatSequenceCount;
|
|
SCHAR* gainSetIndex = pInst->gainSetIndex;
|
|
SCHAR channelGroupForChannel[8];
|
|
DUCKING_MODIFICATION duckingModificationForChannelGroup[8];
|
|
|
|
pInst->drcSetId = FDKreadBits(hBs, 6);
|
|
if (version == 0) {
|
|
/* Assume all v0 DRC sets to be manageable in terms of complexity */
|
|
pInst->drcSetComplexityLevel = 2;
|
|
} else {
|
|
pInst->drcSetComplexityLevel = FDKreadBits(hBs, 4);
|
|
}
|
|
pInst->drcLocation = FDKreadBits(hBs, 4);
|
|
if (version == 0) {
|
|
downmixIdPresent = 1;
|
|
} else {
|
|
downmixIdPresent = FDKreadBits(hBs, 1);
|
|
}
|
|
if (downmixIdPresent) {
|
|
pInst->downmixId[0] = FDKreadBits(hBs, 7);
|
|
if (version == 0) {
|
|
if (pInst->downmixId[0] == 0)
|
|
pInst->drcApplyToDownmix = 0;
|
|
else
|
|
pInst->drcApplyToDownmix = 1;
|
|
} else {
|
|
pInst->drcApplyToDownmix = FDKreadBits(hBs, 1);
|
|
}
|
|
|
|
additionalDownmixIdPresent = FDKreadBits(hBs, 1);
|
|
if (additionalDownmixIdPresent) {
|
|
additionalDownmixIdCount = FDKreadBits(hBs, 3);
|
|
if ((1 + additionalDownmixIdCount) > 8) return DE_MEMORY_ERROR;
|
|
for (i = 0; i < additionalDownmixIdCount; i++) {
|
|
pInst->downmixId[i + 1] = FDKreadBits(hBs, 7);
|
|
}
|
|
pInst->downmixIdCount = 1 + additionalDownmixIdCount;
|
|
} else {
|
|
pInst->downmixIdCount = 1;
|
|
}
|
|
} else {
|
|
pInst->downmixId[0] = 0;
|
|
pInst->downmixIdCount = 1;
|
|
}
|
|
|
|
pInst->drcSetEffect = FDKreadBits(hBs, 16);
|
|
|
|
if ((pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) {
|
|
pInst->limiterPeakTargetPresent = FDKreadBits(hBs, 1);
|
|
if (pInst->limiterPeakTargetPresent) {
|
|
bsLimiterPeakTarget = FDKreadBits(hBs, 8);
|
|
pInst->limiterPeakTarget = -(FIXP_SGL)(
|
|
bsLimiterPeakTarget
|
|
<< (FRACT_BITS - 1 - 3 - 5)); /* - bsLimiterPeakTarget * 0.125; */
|
|
}
|
|
}
|
|
|
|
pInst->drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1);
|
|
|
|
/* set default values */
|
|
pInst->drcSetTargetLoudnessValueUpper = 0;
|
|
pInst->drcSetTargetLoudnessValueLower = -63;
|
|
|
|
if (pInst->drcSetTargetLoudnessPresent == 1) {
|
|
int bsDrcSetTargetLoudnessValueUpper, bsDrcSetTargetLoudnessValueLower;
|
|
int drcSetTargetLoudnessValueLowerPresent;
|
|
bsDrcSetTargetLoudnessValueUpper = FDKreadBits(hBs, 6);
|
|
pInst->drcSetTargetLoudnessValueUpper =
|
|
bsDrcSetTargetLoudnessValueUpper - 63;
|
|
drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1);
|
|
if (drcSetTargetLoudnessValueLowerPresent == 1) {
|
|
bsDrcSetTargetLoudnessValueLower = FDKreadBits(hBs, 6);
|
|
pInst->drcSetTargetLoudnessValueLower =
|
|
bsDrcSetTargetLoudnessValueLower - 63;
|
|
}
|
|
}
|
|
|
|
pInst->dependsOnDrcSetPresent = FDKreadBits(hBs, 1);
|
|
|
|
pInst->noIndependentUse = 0;
|
|
if (pInst->dependsOnDrcSetPresent) {
|
|
pInst->dependsOnDrcSet = FDKreadBits(hBs, 6);
|
|
} else {
|
|
pInst->noIndependentUse = FDKreadBits(hBs, 1);
|
|
}
|
|
|
|
if (version == 0) {
|
|
pInst->requiresEq = 0;
|
|
} else {
|
|
pInst->requiresEq = FDKreadBits(hBs, 1);
|
|
}
|
|
|
|
pCoef = selectDrcCoefficients(hUniDrcConfig, pInst->drcLocation);
|
|
|
|
pInst->drcChannelCount = channelCount =
|
|
hUniDrcConfig->channelLayout.baseChannelCount;
|
|
|
|
if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) {
|
|
DUCKING_MODIFICATION* pDModForChannel =
|
|
pInst->duckingModificationForChannel;
|
|
c = 0;
|
|
while (c < channelCount) {
|
|
int bsGainSetIndex;
|
|
bsGainSetIndex = FDKreadBits(hBs, 6);
|
|
if (c >= 8) return DE_MEMORY_ERROR;
|
|
gainSetIndex[c] = bsGainSetIndex - 1;
|
|
_decodeDuckingModification(hBs, &(pDModForChannel[c]), 0);
|
|
|
|
c++;
|
|
repeatParameters = FDKreadBits(hBs, 1);
|
|
if (repeatParameters == 1) {
|
|
bsRepeatParametersCount = FDKreadBits(hBs, 5);
|
|
bsRepeatParametersCount += 1;
|
|
for (i = 0; i < bsRepeatParametersCount; i++) {
|
|
if (c >= 8) return DE_MEMORY_ERROR;
|
|
gainSetIndex[c] = gainSetIndex[c - 1];
|
|
pDModForChannel[c] = pDModForChannel[c - 1];
|
|
c++;
|
|
}
|
|
}
|
|
}
|
|
if (c > channelCount) {
|
|
return DE_NOT_OK;
|
|
}
|
|
|
|
err = deriveDrcChannelGroups(
|
|
pInst->drcSetEffect, pInst->drcChannelCount, gainSetIndex,
|
|
pDModForChannel, &pInst->nDrcChannelGroups,
|
|
pInst->gainSetIndexForChannelGroup, channelGroupForChannel,
|
|
duckingModificationForChannelGroup);
|
|
if (err) return (err);
|
|
} else {
|
|
int deriveChannelCount = 0;
|
|
if (((version == 0) || (pInst->drcApplyToDownmix != 0)) &&
|
|
(pInst->downmixId[0] != DOWNMIX_ID_BASE_LAYOUT) &&
|
|
(pInst->downmixId[0] != DOWNMIX_ID_ANY_DOWNMIX) &&
|
|
(pInst->downmixIdCount == 1)) {
|
|
if (hUniDrcConfig->downmixInstructionsCount != 0) {
|
|
DOWNMIX_INSTRUCTIONS* pDown =
|
|
selectDownmixInstructions(hUniDrcConfig, pInst->downmixId[0]);
|
|
if (pDown == NULL) return DE_NOT_OK;
|
|
pInst->drcChannelCount = channelCount =
|
|
pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/
|
|
} else {
|
|
deriveChannelCount = 1;
|
|
channelCount = 1;
|
|
}
|
|
} else if (((version == 0) || (pInst->drcApplyToDownmix != 0)) &&
|
|
((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) ||
|
|
(pInst->downmixIdCount > 1))) {
|
|
/* Set maximum channel count as upper border. The effective channel count
|
|
* is set at the process function. */
|
|
pInst->drcChannelCount = 8;
|
|
channelCount = 1;
|
|
}
|
|
|
|
c = 0;
|
|
while (c < channelCount) {
|
|
int bsGainSetIndex;
|
|
bsGainSetIndex = FDKreadBits(hBs, 6);
|
|
if (c >= 8) return DE_MEMORY_ERROR;
|
|
gainSetIndex[c] = bsGainSetIndex - 1;
|
|
c++;
|
|
repeatSequenceIndex = FDKreadBits(hBs, 1);
|
|
|
|
if (repeatSequenceIndex == 1) {
|
|
bsRepeatSequenceCount = FDKreadBits(hBs, 5);
|
|
bsRepeatSequenceCount += 1;
|
|
if (deriveChannelCount) {
|
|
channelCount = 1 + bsRepeatSequenceCount;
|
|
}
|
|
for (i = 0; i < bsRepeatSequenceCount; i++) {
|
|
if (c >= 8) return DE_MEMORY_ERROR;
|
|
gainSetIndex[c] = bsGainSetIndex - 1;
|
|
c++;
|
|
}
|
|
}
|
|
}
|
|
if (c > channelCount) {
|
|
return DE_NOT_OK;
|
|
}
|
|
if (deriveChannelCount) {
|
|
pInst->drcChannelCount = channelCount;
|
|
}
|
|
|
|
/* DOWNMIX_ID_ANY_DOWNMIX: channelCount is 1. Distribute gainSetIndex to all
|
|
* channels. */
|
|
if ((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) ||
|
|
(pInst->downmixIdCount > 1)) {
|
|
for (c = 1; c < pInst->drcChannelCount; c++) {
|
|
gainSetIndex[c] = gainSetIndex[0];
|
|
}
|
|
}
|
|
|
|
err = deriveDrcChannelGroups(pInst->drcSetEffect, pInst->drcChannelCount,
|
|
gainSetIndex, NULL, &pInst->nDrcChannelGroups,
|
|
pInst->gainSetIndexForChannelGroup,
|
|
channelGroupForChannel, NULL);
|
|
if (err) return (err);
|
|
|
|
for (g = 0; g < pInst->nDrcChannelGroups; g++) {
|
|
int set, bandCount;
|
|
set = pInst->gainSetIndexForChannelGroup[g];
|
|
|
|
/* get bandCount */
|
|
if (pCoef != NULL && set < pCoef->gainSetCount) {
|
|
bandCount = pCoef->gainSet[set].bandCount;
|
|
} else {
|
|
bandCount = 1;
|
|
}
|
|
|
|
_decodeGainModification(hBs, version, bandCount,
|
|
pInst->gainModificationForChannelGroup[g], 0);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static DRC_ERROR _readChannelLayout(HANDLE_FDK_BITSTREAM hBs,
|
|
CHANNEL_LAYOUT* pChan) {
|
|
DRC_ERROR err = DE_OK;
|
|
|
|
pChan->baseChannelCount = FDKreadBits(hBs, 7);
|
|
|
|
if (pChan->baseChannelCount > 8) return DE_NOT_OK;
|
|
|
|
pChan->layoutSignalingPresent = FDKreadBits(hBs, 1);
|
|
|
|
if (pChan->layoutSignalingPresent) {
|
|
pChan->definedLayout = FDKreadBits(hBs, 8);
|
|
|
|
if (pChan->definedLayout == 0) {
|
|
int i;
|
|
for (i = 0; i < pChan->baseChannelCount; i++) {
|
|
if (i < 8) {
|
|
pChan->speakerPosition[i] = FDKreadBits(hBs, 7);
|
|
} else {
|
|
FDKpushFor(hBs, 7);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static DRC_ERROR _readDownmixInstructions(HANDLE_FDK_BITSTREAM hBs,
|
|
const int version,
|
|
CHANNEL_LAYOUT* pChan,
|
|
DOWNMIX_INSTRUCTIONS* pDown) {
|
|
DRC_ERROR err = DE_OK;
|
|
|
|
pDown->downmixId = FDKreadBits(hBs, 7);
|
|
pDown->targetChannelCount = FDKreadBits(hBs, 7);
|
|
pDown->targetLayout = FDKreadBits(hBs, 8);
|
|
pDown->downmixCoefficientsPresent = FDKreadBits(hBs, 1);
|
|
|
|
if (pDown->downmixCoefficientsPresent) {
|
|
int nDownmixCoeffs = pDown->targetChannelCount * pChan->baseChannelCount;
|
|
int i;
|
|
if (nDownmixCoeffs > 8 * 8) return DE_NOT_OK;
|
|
if (version == 0) {
|
|
pDown->bsDownmixOffset = 0;
|
|
for (i = 0; i < nDownmixCoeffs; i++) {
|
|
/* LFE downmix coefficients are not supported. */
|
|
pDown->downmixCoefficient[i] = downmixCoeff[FDKreadBits(hBs, 4)];
|
|
}
|
|
} else {
|
|
pDown->bsDownmixOffset = FDKreadBits(hBs, 4);
|
|
for (i = 0; i < nDownmixCoeffs; i++) {
|
|
pDown->downmixCoefficient[i] = downmixCoeffV1[FDKreadBits(hBs, 5)];
|
|
}
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static DRC_ERROR _readDrcExtensionV1(HANDLE_FDK_BITSTREAM hBs,
|
|
HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
|
|
DRC_ERROR err = DE_OK;
|
|
int downmixInstructionsV1Present;
|
|
int drcCoeffsAndInstructionsUniDrcV1Present;
|
|
int loudEqInstructionsPresent, loudEqInstructionsCount;
|
|
int eqPresent, eqInstructionsCount;
|
|
int i, offset;
|
|
int diff = hUniDrcConfig->diff;
|
|
|
|
downmixInstructionsV1Present = FDKreadBits(hBs, 1);
|
|
if (downmixInstructionsV1Present == 1) {
|
|
diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1,
|
|
FDKreadBits(hBs, 7));
|
|
offset = hUniDrcConfig->downmixInstructionsCountV0;
|
|
hUniDrcConfig->downmixInstructionsCount = fMin(
|
|
(UCHAR)(offset + hUniDrcConfig->downmixInstructionsCountV1), (UCHAR)6);
|
|
for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV1; i++) {
|
|
DOWNMIX_INSTRUCTIONS tmpDown;
|
|
FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS));
|
|
err = _readDownmixInstructions(hBs, 1, &hUniDrcConfig->channelLayout,
|
|
&tmpDown);
|
|
if (err) return err;
|
|
if ((offset + i) >= 6) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpDown,
|
|
&(hUniDrcConfig->downmixInstructions[offset + i]),
|
|
sizeof(DOWNMIX_INSTRUCTIONS)) != 0);
|
|
hUniDrcConfig->downmixInstructions[offset + i] = tmpDown;
|
|
}
|
|
} else {
|
|
diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1, 0);
|
|
}
|
|
|
|
drcCoeffsAndInstructionsUniDrcV1Present = FDKreadBits(hBs, 1);
|
|
if (drcCoeffsAndInstructionsUniDrcV1Present == 1) {
|
|
diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1,
|
|
FDKreadBits(hBs, 3));
|
|
offset = hUniDrcConfig->drcCoefficientsUniDrcCountV0;
|
|
hUniDrcConfig->drcCoefficientsUniDrcCount =
|
|
fMin((UCHAR)(offset + hUniDrcConfig->drcCoefficientsUniDrcCountV1),
|
|
(UCHAR)2);
|
|
for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV1; i++) {
|
|
DRC_COEFFICIENTS_UNI_DRC tmpCoef;
|
|
FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC));
|
|
err = _readDrcCoefficientsUniDrc(hBs, 1, &tmpCoef);
|
|
if (err) return err;
|
|
if ((offset + i) >= 2) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpCoef,
|
|
&(hUniDrcConfig->drcCoefficientsUniDrc[offset + i]),
|
|
sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0);
|
|
hUniDrcConfig->drcCoefficientsUniDrc[offset + i] = tmpCoef;
|
|
}
|
|
|
|
diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1,
|
|
FDKreadBits(hBs, 6));
|
|
offset = hUniDrcConfig->drcInstructionsUniDrcCount;
|
|
hUniDrcConfig->drcInstructionsUniDrcCount =
|
|
fMin((UCHAR)(offset + hUniDrcConfig->drcInstructionsUniDrcCountV1),
|
|
(UCHAR)12);
|
|
for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) {
|
|
DRC_INSTRUCTIONS_UNI_DRC tmpInst;
|
|
FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC));
|
|
err = _readDrcInstructionsUniDrc(hBs, 1, hUniDrcConfig, &tmpInst);
|
|
if (err) return err;
|
|
if ((offset + i) >= 12) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpInst,
|
|
&(hUniDrcConfig->drcInstructionsUniDrc[offset + i]),
|
|
sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0);
|
|
hUniDrcConfig->drcInstructionsUniDrc[offset + i] = tmpInst;
|
|
}
|
|
} else {
|
|
diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1, 0);
|
|
diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1, 0);
|
|
}
|
|
|
|
loudEqInstructionsPresent = FDKreadBits(hBs, 1);
|
|
if (loudEqInstructionsPresent == 1) {
|
|
loudEqInstructionsCount = FDKreadBits(hBs, 4);
|
|
for (i = 0; i < loudEqInstructionsCount; i++) {
|
|
_skipLoudEqInstructions(hBs);
|
|
}
|
|
}
|
|
|
|
eqPresent = FDKreadBits(hBs, 1);
|
|
if (eqPresent == 1) {
|
|
_skipEqCoefficients(hBs);
|
|
eqInstructionsCount = FDKreadBits(hBs, 4);
|
|
for (i = 0; i < eqInstructionsCount; i++) {
|
|
_skipEqInstructions(hBs, hUniDrcConfig);
|
|
}
|
|
}
|
|
|
|
hUniDrcConfig->diff = diff;
|
|
|
|
return err;
|
|
}
|
|
|
|
static DRC_ERROR _readUniDrcConfigExtension(
|
|
HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
|
|
DRC_ERROR err = DE_OK;
|
|
int k, bitSizeLen, extSizeBits, bitSize;
|
|
UINT nBitsRemaining;
|
|
UNI_DRC_CONFIG_EXTENSION* pExt = &(hUniDrcConfig->uniDrcConfigExt);
|
|
|
|
k = 0;
|
|
pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4);
|
|
while (pExt->uniDrcConfigExtType[k] != UNIDRCCONFEXT_TERM) {
|
|
if (k >= (8 - 1)) return DE_MEMORY_ERROR;
|
|
bitSizeLen = FDKreadBits(hBs, 4);
|
|
extSizeBits = bitSizeLen + 4;
|
|
|
|
bitSize = FDKreadBits(hBs, extSizeBits);
|
|
pExt->extBitSize[k] = bitSize + 1;
|
|
nBitsRemaining = FDKgetValidBits(hBs);
|
|
|
|
switch (pExt->uniDrcConfigExtType[k]) {
|
|
case UNIDRCCONFEXT_V1:
|
|
err = _readDrcExtensionV1(hBs, hUniDrcConfig);
|
|
if (err) return err;
|
|
if (nBitsRemaining != (pExt->extBitSize[k] + FDKgetValidBits(hBs)))
|
|
return DE_NOT_OK;
|
|
break;
|
|
case UNIDRCCONFEXT_PARAM_DRC:
|
|
/* add future extensions here */
|
|
default:
|
|
FDKpushFor(hBs, pExt->extBitSize[k]);
|
|
break;
|
|
}
|
|
k++;
|
|
pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
DRC_ERROR
|
|
drcDec_readUniDrcConfig(HANDLE_FDK_BITSTREAM hBs,
|
|
HANDLE_UNI_DRC_CONFIG hUniDrcConfig) {
|
|
DRC_ERROR err = DE_OK;
|
|
int i, diff = 0;
|
|
int drcDescriptionBasicPresent, drcCoefficientsBasicCount,
|
|
drcInstructionsBasicCount;
|
|
CHANNEL_LAYOUT tmpChan;
|
|
FDKmemclear(&tmpChan, sizeof(CHANNEL_LAYOUT));
|
|
if (hUniDrcConfig == NULL) return DE_NOT_OK;
|
|
|
|
diff |= _compAssign(&hUniDrcConfig->sampleRatePresent, FDKreadBits(hBs, 1));
|
|
|
|
if (hUniDrcConfig->sampleRatePresent == 1) {
|
|
diff |=
|
|
_compAssign(&hUniDrcConfig->sampleRate, FDKreadBits(hBs, 18) + 1000);
|
|
}
|
|
|
|
diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV0,
|
|
FDKreadBits(hBs, 7));
|
|
|
|
drcDescriptionBasicPresent = FDKreadBits(hBs, 1);
|
|
if (drcDescriptionBasicPresent == 1) {
|
|
drcCoefficientsBasicCount = FDKreadBits(hBs, 3);
|
|
drcInstructionsBasicCount = FDKreadBits(hBs, 4);
|
|
} else {
|
|
drcCoefficientsBasicCount = 0;
|
|
drcInstructionsBasicCount = 0;
|
|
}
|
|
|
|
diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV0,
|
|
FDKreadBits(hBs, 3));
|
|
diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV0,
|
|
FDKreadBits(hBs, 6));
|
|
|
|
err = _readChannelLayout(hBs, &tmpChan);
|
|
if (err) return err;
|
|
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpChan, &hUniDrcConfig->channelLayout,
|
|
sizeof(CHANNEL_LAYOUT)) != 0);
|
|
hUniDrcConfig->channelLayout = tmpChan;
|
|
|
|
hUniDrcConfig->downmixInstructionsCount =
|
|
fMin(hUniDrcConfig->downmixInstructionsCountV0, (UCHAR)6);
|
|
for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV0; i++) {
|
|
DOWNMIX_INSTRUCTIONS tmpDown;
|
|
FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS));
|
|
err = _readDownmixInstructions(hBs, 0, &hUniDrcConfig->channelLayout,
|
|
&tmpDown);
|
|
if (err) return err;
|
|
if (i >= 6) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpDown, &(hUniDrcConfig->downmixInstructions[i]),
|
|
sizeof(DOWNMIX_INSTRUCTIONS)) != 0);
|
|
hUniDrcConfig->downmixInstructions[i] = tmpDown;
|
|
}
|
|
|
|
for (i = 0; i < drcCoefficientsBasicCount; i++) {
|
|
_skipDrcCoefficientsBasic(hBs);
|
|
}
|
|
for (i = 0; i < drcInstructionsBasicCount; i++) {
|
|
_skipDrcInstructionsBasic(hBs);
|
|
}
|
|
|
|
hUniDrcConfig->drcCoefficientsUniDrcCount =
|
|
fMin(hUniDrcConfig->drcCoefficientsUniDrcCountV0, (UCHAR)2);
|
|
for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV0; i++) {
|
|
DRC_COEFFICIENTS_UNI_DRC tmpCoef;
|
|
FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC));
|
|
err = _readDrcCoefficientsUniDrc(hBs, 0, &tmpCoef);
|
|
if (err) return err;
|
|
if (i >= 2) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpCoef, &(hUniDrcConfig->drcCoefficientsUniDrc[i]),
|
|
sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0);
|
|
hUniDrcConfig->drcCoefficientsUniDrc[i] = tmpCoef;
|
|
}
|
|
|
|
hUniDrcConfig->drcInstructionsUniDrcCount =
|
|
fMin(hUniDrcConfig->drcInstructionsUniDrcCountV0, (UCHAR)12);
|
|
for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCountV0; i++) {
|
|
DRC_INSTRUCTIONS_UNI_DRC tmpInst;
|
|
FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC));
|
|
err = _readDrcInstructionsUniDrc(hBs, 0, hUniDrcConfig, &tmpInst);
|
|
if (err) return err;
|
|
if (i >= 12) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpInst, &(hUniDrcConfig->drcInstructionsUniDrc[i]),
|
|
sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0);
|
|
hUniDrcConfig->drcInstructionsUniDrc[i] = tmpInst;
|
|
}
|
|
|
|
diff |=
|
|
_compAssign(&hUniDrcConfig->uniDrcConfigExtPresent, FDKreadBits(hBs, 1));
|
|
hUniDrcConfig->diff = diff;
|
|
|
|
if (hUniDrcConfig->uniDrcConfigExtPresent == 1) {
|
|
err = _readUniDrcConfigExtension(hBs, hUniDrcConfig);
|
|
if (err) return err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*******************/
|
|
/* loudnessInfoSet */
|
|
/*******************/
|
|
|
|
static DRC_ERROR _decodeMethodValue(HANDLE_FDK_BITSTREAM hBs,
|
|
const UCHAR methodDefinition,
|
|
FIXP_DBL* methodValue, INT isBox) {
|
|
int tmp;
|
|
FIXP_DBL val;
|
|
switch (methodDefinition) {
|
|
case MD_UNKNOWN_OTHER:
|
|
case MD_PROGRAM_LOUDNESS:
|
|
case MD_ANCHOR_LOUDNESS:
|
|
case MD_MAX_OF_LOUDNESS_RANGE:
|
|
case MD_MOMENTARY_LOUDNESS_MAX:
|
|
case MD_SHORT_TERM_LOUDNESS_MAX:
|
|
tmp = FDKreadBits(hBs, 8);
|
|
val = FL2FXCONST_DBL(-57.75f / (float)(1 << 7)) +
|
|
(FIXP_DBL)(
|
|
tmp << (DFRACT_BITS - 1 - 2 - 7)); /* -57.75 + tmp * 0.25; */
|
|
break;
|
|
case MD_LOUDNESS_RANGE:
|
|
tmp = FDKreadBits(hBs, 8);
|
|
if (tmp == 0)
|
|
val = (FIXP_DBL)0;
|
|
else if (tmp <= 128)
|
|
val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 2 - 7)); /* tmp * 0.25; */
|
|
else if (tmp <= 204) {
|
|
val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 1 - 7)) -
|
|
FL2FXCONST_DBL(32.0f / (float)(1 << 7)); /* 0.5 * tmp - 32.0f; */
|
|
} else {
|
|
/* downscale by 1 more bit to prevent overflow at intermediate result */
|
|
val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 8)) -
|
|
FL2FXCONST_DBL(134.0f / (float)(1 << 8)); /* tmp - 134.0; */
|
|
val <<= 1;
|
|
}
|
|
break;
|
|
case MD_MIXING_LEVEL:
|
|
tmp = FDKreadBits(hBs, isBox ? 8 : 5);
|
|
val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)) +
|
|
FL2FXCONST_DBL(80.0f / (float)(1 << 7)); /* tmp + 80.0; */
|
|
break;
|
|
case MD_ROOM_TYPE:
|
|
tmp = FDKreadBits(hBs, isBox ? 8 : 2);
|
|
val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)); /* tmp; */
|
|
break;
|
|
case MD_SHORT_TERM_LOUDNESS:
|
|
tmp = FDKreadBits(hBs, 8);
|
|
val = FL2FXCONST_DBL(-116.0f / (float)(1 << 7)) +
|
|
(FIXP_DBL)(
|
|
tmp << (DFRACT_BITS - 1 - 1 - 7)); /* -116.0 + tmp * 0.5; */
|
|
break;
|
|
default:
|
|
return DE_NOT_OK; /* invalid methodDefinition value */
|
|
}
|
|
*methodValue = val;
|
|
return DE_OK;
|
|
}
|
|
|
|
static DRC_ERROR _readLoudnessMeasurement(HANDLE_FDK_BITSTREAM hBs,
|
|
LOUDNESS_MEASUREMENT* pMeas) {
|
|
DRC_ERROR err = DE_OK;
|
|
|
|
pMeas->methodDefinition = FDKreadBits(hBs, 4);
|
|
err =
|
|
_decodeMethodValue(hBs, pMeas->methodDefinition, &pMeas->methodValue, 0);
|
|
if (err) return err;
|
|
pMeas->measurementSystem = FDKreadBits(hBs, 4);
|
|
pMeas->reliability = FDKreadBits(hBs, 2);
|
|
|
|
return err;
|
|
}
|
|
|
|
static DRC_ERROR _readLoudnessInfo(HANDLE_FDK_BITSTREAM hBs, const int version,
|
|
LOUDNESS_INFO* loudnessInfo) {
|
|
DRC_ERROR err = DE_OK;
|
|
int bsSamplePeakLevel, bsTruePeakLevel, i;
|
|
int measurementCount;
|
|
|
|
loudnessInfo->drcSetId = FDKreadBits(hBs, 6);
|
|
if (version >= 1) {
|
|
loudnessInfo->eqSetId = FDKreadBits(hBs, 6);
|
|
} else {
|
|
loudnessInfo->eqSetId = 0;
|
|
}
|
|
loudnessInfo->downmixId = FDKreadBits(hBs, 7);
|
|
|
|
loudnessInfo->samplePeakLevelPresent = FDKreadBits(hBs, 1);
|
|
if (loudnessInfo->samplePeakLevelPresent) {
|
|
bsSamplePeakLevel = FDKreadBits(hBs, 12);
|
|
if (bsSamplePeakLevel == 0) {
|
|
loudnessInfo->samplePeakLevelPresent = 0;
|
|
loudnessInfo->samplePeakLevel = (FIXP_DBL)0;
|
|
} else { /* 20.0 - bsSamplePeakLevel * 0.03125; */
|
|
loudnessInfo->samplePeakLevel =
|
|
FL2FXCONST_DBL(20.0f / (float)(1 << 7)) -
|
|
(FIXP_DBL)(bsSamplePeakLevel << (DFRACT_BITS - 1 - 5 - 7));
|
|
}
|
|
}
|
|
|
|
loudnessInfo->truePeakLevelPresent = FDKreadBits(hBs, 1);
|
|
if (loudnessInfo->truePeakLevelPresent) {
|
|
bsTruePeakLevel = FDKreadBits(hBs, 12);
|
|
if (bsTruePeakLevel == 0) {
|
|
loudnessInfo->truePeakLevelPresent = 0;
|
|
loudnessInfo->truePeakLevel = (FIXP_DBL)0;
|
|
} else {
|
|
loudnessInfo->truePeakLevel =
|
|
FL2FXCONST_DBL(20.0f / (float)(1 << 7)) -
|
|
(FIXP_DBL)(bsTruePeakLevel << (DFRACT_BITS - 1 - 5 - 7));
|
|
}
|
|
loudnessInfo->truePeakLevelMeasurementSystem = FDKreadBits(hBs, 4);
|
|
loudnessInfo->truePeakLevelReliability = FDKreadBits(hBs, 2);
|
|
}
|
|
|
|
measurementCount = FDKreadBits(hBs, 4);
|
|
loudnessInfo->measurementCount = fMin(measurementCount, 8);
|
|
for (i = 0; i < measurementCount; i++) {
|
|
LOUDNESS_MEASUREMENT tmpMeas;
|
|
FDKmemclear(&tmpMeas, sizeof(LOUDNESS_MEASUREMENT));
|
|
err = _readLoudnessMeasurement(hBs, &tmpMeas);
|
|
if (err) return err;
|
|
if (i >= 8) continue;
|
|
loudnessInfo->loudnessMeasurement[i] = tmpMeas;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static DRC_ERROR _readLoudnessInfoSetExtEq(
|
|
HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) {
|
|
DRC_ERROR err = DE_OK;
|
|
int i, offset;
|
|
int diff = hLoudnessInfoSet->diff;
|
|
|
|
diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV1,
|
|
FDKreadBits(hBs, 6));
|
|
diff |=
|
|
_compAssign(&hLoudnessInfoSet->loudnessInfoCountV1, FDKreadBits(hBs, 6));
|
|
|
|
offset = hLoudnessInfoSet->loudnessInfoAlbumCountV0;
|
|
hLoudnessInfoSet->loudnessInfoAlbumCount = fMin(
|
|
(UCHAR)(offset + hLoudnessInfoSet->loudnessInfoAlbumCountV1), (UCHAR)12);
|
|
for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV1; i++) {
|
|
LOUDNESS_INFO tmpLoud;
|
|
FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
|
|
err = _readLoudnessInfo(hBs, 1, &tmpLoud);
|
|
if (err) return err;
|
|
if ((offset + i) >= 12) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpLoud,
|
|
&(hLoudnessInfoSet->loudnessInfoAlbum[offset + i]),
|
|
sizeof(LOUDNESS_INFO)) != 0);
|
|
hLoudnessInfoSet->loudnessInfoAlbum[offset + i] = tmpLoud;
|
|
}
|
|
|
|
offset = hLoudnessInfoSet->loudnessInfoCountV0;
|
|
hLoudnessInfoSet->loudnessInfoCount =
|
|
fMin((UCHAR)(offset + hLoudnessInfoSet->loudnessInfoCountV1), (UCHAR)12);
|
|
for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV1; i++) {
|
|
LOUDNESS_INFO tmpLoud;
|
|
FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
|
|
err = _readLoudnessInfo(hBs, 1, &tmpLoud);
|
|
if (err) return err;
|
|
if ((offset + i) >= 12) continue;
|
|
if (!diff)
|
|
diff |=
|
|
(FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[offset + i]),
|
|
sizeof(LOUDNESS_INFO)) != 0);
|
|
hLoudnessInfoSet->loudnessInfo[offset + i] = tmpLoud;
|
|
}
|
|
hLoudnessInfoSet->diff = diff;
|
|
return err;
|
|
}
|
|
|
|
static DRC_ERROR _readLoudnessInfoSetExtension(
|
|
HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) {
|
|
DRC_ERROR err = DE_OK;
|
|
int k, bitSizeLen, extSizeBits, bitSize;
|
|
UINT nBitsRemaining;
|
|
LOUDNESS_INFO_SET_EXTENSION* pExt = &(hLoudnessInfoSet->loudnessInfoSetExt);
|
|
|
|
k = 0;
|
|
pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4);
|
|
while (pExt->loudnessInfoSetExtType[k] != UNIDRCLOUDEXT_TERM) {
|
|
if (k >= (8 - 1)) return DE_MEMORY_ERROR;
|
|
bitSizeLen = FDKreadBits(hBs, 4);
|
|
extSizeBits = bitSizeLen + 4;
|
|
|
|
bitSize = FDKreadBits(hBs, extSizeBits);
|
|
pExt->extBitSize[k] = bitSize + 1;
|
|
nBitsRemaining = FDKgetValidBits(hBs);
|
|
|
|
switch (pExt->loudnessInfoSetExtType[k]) {
|
|
case UNIDRCLOUDEXT_EQ:
|
|
err = _readLoudnessInfoSetExtEq(hBs, hLoudnessInfoSet);
|
|
if (err) return err;
|
|
if (nBitsRemaining != (pExt->extBitSize[k] + FDKgetValidBits(hBs)))
|
|
return DE_NOT_OK;
|
|
break;
|
|
/* add future extensions here */
|
|
default:
|
|
FDKpushFor(hBs, pExt->extBitSize[k]);
|
|
break;
|
|
}
|
|
k++;
|
|
pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Parser for loundessInfoSet() */
|
|
DRC_ERROR
|
|
drcDec_readLoudnessInfoSet(HANDLE_FDK_BITSTREAM hBs,
|
|
HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) {
|
|
DRC_ERROR err = DE_OK;
|
|
int i, diff = 0;
|
|
if (hLoudnessInfoSet == NULL) return DE_NOT_OK;
|
|
|
|
diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV0,
|
|
FDKreadBits(hBs, 6));
|
|
diff |=
|
|
_compAssign(&hLoudnessInfoSet->loudnessInfoCountV0, FDKreadBits(hBs, 6));
|
|
|
|
hLoudnessInfoSet->loudnessInfoAlbumCount =
|
|
fMin(hLoudnessInfoSet->loudnessInfoAlbumCountV0, (UCHAR)12);
|
|
for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV0; i++) {
|
|
LOUDNESS_INFO tmpLoud;
|
|
FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
|
|
err = _readLoudnessInfo(hBs, 0, &tmpLoud);
|
|
if (err) return err;
|
|
if (i >= 12) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfoAlbum[i]),
|
|
sizeof(LOUDNESS_INFO)) != 0);
|
|
hLoudnessInfoSet->loudnessInfoAlbum[i] = tmpLoud;
|
|
}
|
|
|
|
hLoudnessInfoSet->loudnessInfoCount =
|
|
fMin(hLoudnessInfoSet->loudnessInfoCountV0, (UCHAR)12);
|
|
for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV0; i++) {
|
|
LOUDNESS_INFO tmpLoud;
|
|
FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO));
|
|
err = _readLoudnessInfo(hBs, 0, &tmpLoud);
|
|
if (err) return err;
|
|
if (i >= 12) continue;
|
|
if (!diff)
|
|
diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[i]),
|
|
sizeof(LOUDNESS_INFO)) != 0);
|
|
hLoudnessInfoSet->loudnessInfo[i] = tmpLoud;
|
|
}
|
|
|
|
diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoSetExtPresent,
|
|
FDKreadBits(hBs, 1));
|
|
hLoudnessInfoSet->diff = diff;
|
|
|
|
if (hLoudnessInfoSet->loudnessInfoSetExtPresent) {
|
|
err = _readLoudnessInfoSetExtension(hBs, hLoudnessInfoSet);
|
|
if (err) return err;
|
|
}
|
|
|
|
return err;
|
|
}
|