From 6cfabd35363c3ef5e3b209b867169a500b3ccc3c Mon Sep 17 00:00:00 2001 From: Fraunhofer IIS FDK Date: Mon, 26 Feb 2018 20:17:00 +0100 Subject: Upgrade to FDKv2 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 --- libAACenc/src/metadata_compressor.cpp | 2257 ++++++++++++++++++++------------- 1 file changed, 1399 insertions(+), 858 deletions(-) (limited to 'libAACenc/src/metadata_compressor.cpp') diff --git a/libAACenc/src/metadata_compressor.cpp b/libAACenc/src/metadata_compressor.cpp index 68a64ae..bdac80a 100644 --- a/libAACenc/src/metadata_compressor.cpp +++ b/libAACenc/src/metadata_compressor.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,50 +90,39 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/********************** Fraunhofer IIS FDK AAC Encoder lib ****************** +/**************************** AAC encoder library ****************************** - Author(s): M. Neusinger - Description: Compressor for AAC Metadata Generator + Author(s): M. Neusinger -******************************************************************************/ + Description: Compressor for AAC Metadata Generator +*******************************************************************************/ #include "metadata_compressor.h" #include "channel_map.h" - -#define LOG2 0.69314718056f /* natural logarithm of 2 */ -#define ILOG2 1.442695041f /* 1/LOG2 */ -#define FIXP_ILOG2_DIV2 (FL2FXCONST_DBL(ILOG2/2)) +#define LOG2 0.69314718056f /* natural logarithm of 2 */ +#define ILOG2 1.442695041f /* 1/LOG2 */ +#define FIXP_ILOG2_DIV2 (FL2FXCONST_DBL(ILOG2 / 2)) /*----------------- defines ----------------------*/ -#define MAX_DRC_CHANNELS (8) /*!< Max number of audio input channels. */ -#define DOWNMIX_SHIFT (3) /*!< Max 8 channel. */ -#define WEIGHTING_FILTER_SHIFT (2) /*!< Scaling used in weighting filter. */ +#define MAX_DRC_CHANNELS (8) /*!< Max number of audio input channels. */ +#define DOWNMIX_SHIFT (3) /*!< Max 8 channel. */ +#define WEIGHTING_FILTER_SHIFT (2) /*!< Scaling used in weighting filter. */ -#define METADATA_INT_BITS 10 -#define METADATA_LINT_BITS 20 -#define METADATA_INT_SCALE (INT64(1)<<(METADATA_INT_BITS)) -#define METADATA_FRACT_BITS (DFRACT_BITS-1-METADATA_INT_BITS) -#define METADATA_FRACT_SCALE (INT64(1)<<(METADATA_FRACT_BITS)) +#define METADATA_INT_BITS 10 +#define METADATA_LINT_BITS 20 +#define METADATA_INT_SCALE (INT64(1) << (METADATA_INT_BITS)) +#define METADATA_FRACT_BITS (DFRACT_BITS - 1 - METADATA_INT_BITS) +#define METADATA_FRACT_SCALE (INT64(1) << (METADATA_FRACT_BITS)) /** * Enum for channel assignment. */ -enum { - L = 0, - R = 1, - C = 2, - LFE = 3, - LS = 4, - RS = 5, - S = 6, - LS2 = 7, - RS2 = 8 -}; +enum { L = 0, R = 1, C = 2, LFE = 3, LS = 4, RS = 5, S = 6, LS2 = 7, RS2 = 8 }; /*--------------- structure definitions --------------------*/ @@ -130,61 +130,62 @@ enum { * Structure holds weighting filter filter states. */ struct WEIGHTING_STATES { - FIXP_DBL x1; - FIXP_DBL x2; - FIXP_DBL y1; - FIXP_DBL y2; + FIXP_DBL x1; + FIXP_DBL x2; + FIXP_DBL y1; + FIXP_DBL y2; }; /** * Dynamic Range Control compressor structure. */ struct DRC_COMP { - - FIXP_DBL maxBoostThr[2]; /*!< Max boost threshold. */ - FIXP_DBL boostThr[2]; /*!< Boost threshold. */ - FIXP_DBL earlyCutThr[2]; /*!< Early cut threshold. */ - FIXP_DBL cutThr[2]; /*!< Cut threshold. */ - FIXP_DBL maxCutThr[2]; /*!< Max cut threshold. */ - - FIXP_DBL boostFac[2]; /*!< Precalculated factor for boost compression. */ - FIXP_DBL earlyCutFac[2]; /*!< Precalculated factor for early cut compression. */ - FIXP_DBL cutFac[2]; /*!< Precalculated factor for cut compression. */ - - FIXP_DBL maxBoost[2]; /*!< Maximum boost. */ - FIXP_DBL maxCut[2]; /*!< Maximum cut. */ - FIXP_DBL maxEarlyCut[2]; /*!< Maximum early cut. */ - - FIXP_DBL fastAttack[2]; /*!< Fast attack coefficient. */ - FIXP_DBL fastDecay[2]; /*!< Fast release coefficient. */ - FIXP_DBL slowAttack[2]; /*!< Slow attack coefficient. */ - FIXP_DBL slowDecay[2]; /*!< Slow release coefficient. */ - UINT holdOff[2]; /*!< Hold time in blocks. */ - - FIXP_DBL attackThr[2]; /*!< Slow/fast attack threshold. */ - FIXP_DBL decayThr[2]; /*!< Slow/fast release threshold. */ - - DRC_PROFILE profile[2]; /*!< DRC profile. */ - INT blockLength; /*!< Block length in samples. */ - UINT sampleRate; /*!< Sample rate. */ - CHANNEL_MODE chanConfig; /*!< Channel configuration. */ - - UCHAR useWeighting; /*!< Use weighting filter. */ - - UINT channels; /*!< Number of channels. */ - UINT fullChannels; /*!< Number of full range channels. */ - INT channelIdx[9]; /*!< Offsets of interleaved channel samples (L, R, C, LFE, Ls, Rs, S, Ls2, Rs2). */ - - FIXP_DBL smoothLevel[2]; /*!< level smoothing states */ - FIXP_DBL smoothGain[2]; /*!< gain smoothing states */ - UINT holdCnt[2]; /*!< hold counter */ - - FIXP_DBL limGain[2]; /*!< limiter gain */ - FIXP_DBL limDecay; /*!< limiter decay (linear) */ - FIXP_DBL prevPeak[2]; /*!< max peak of previous block (stereo/mono)*/ - - WEIGHTING_STATES filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */ - + FIXP_DBL maxBoostThr[2]; /*!< Max boost threshold. */ + FIXP_DBL boostThr[2]; /*!< Boost threshold. */ + FIXP_DBL earlyCutThr[2]; /*!< Early cut threshold. */ + FIXP_DBL cutThr[2]; /*!< Cut threshold. */ + FIXP_DBL maxCutThr[2]; /*!< Max cut threshold. */ + + FIXP_DBL boostFac[2]; /*!< Precalculated factor for boost compression. */ + FIXP_DBL + earlyCutFac[2]; /*!< Precalculated factor for early cut compression. */ + FIXP_DBL cutFac[2]; /*!< Precalculated factor for cut compression. */ + + FIXP_DBL maxBoost[2]; /*!< Maximum boost. */ + FIXP_DBL maxCut[2]; /*!< Maximum cut. */ + FIXP_DBL maxEarlyCut[2]; /*!< Maximum early cut. */ + + FIXP_DBL fastAttack[2]; /*!< Fast attack coefficient. */ + FIXP_DBL fastDecay[2]; /*!< Fast release coefficient. */ + FIXP_DBL slowAttack[2]; /*!< Slow attack coefficient. */ + FIXP_DBL slowDecay[2]; /*!< Slow release coefficient. */ + UINT holdOff[2]; /*!< Hold time in blocks. */ + + FIXP_DBL attackThr[2]; /*!< Slow/fast attack threshold. */ + FIXP_DBL decayThr[2]; /*!< Slow/fast release threshold. */ + + DRC_PROFILE profile[2]; /*!< DRC profile. */ + INT blockLength; /*!< Block length in samples. */ + UINT sampleRate; /*!< Sample rate. */ + CHANNEL_MODE chanConfig; /*!< Channel configuration. */ + + UCHAR useWeighting; /*!< Use weighting filter. */ + + UINT channels; /*!< Number of channels. */ + UINT fullChannels; /*!< Number of full range channels. */ + INT channelIdx[9]; /*!< Offsets of interleaved channel samples (L, R, C, LFE, + Ls, Rs, S, Ls2, Rs2). */ + + FIXP_DBL smoothLevel[2]; /*!< level smoothing states */ + FIXP_DBL smoothGain[2]; /*!< gain smoothing states */ + UINT holdCnt[2]; /*!< hold counter */ + + FIXP_DBL limGain[2]; /*!< limiter gain */ + FIXP_DBL limDecay; /*!< limiter decay (linear) */ + FIXP_DBL prevPeak[2]; /*!< max peak of previous block (stereo/mono)*/ + + WEIGHTING_STATES + filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */ }; /*---------------- constants -----------------------*/ @@ -193,143 +194,110 @@ struct DRC_COMP { * Profile tables. */ static const FIXP_DBL tabMaxBoostThr[] = { - (FIXP_DBL)(int)((unsigned)-43<blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* single channels */ + for (c = 0; c < (int)drcComp->channels; c++) { + maxSample = fMax(maxSample, (INT_PCM)fAbs(pSamples[c])); } + } + peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample) >> DOWNMIX_SHIFT); + + /* 7.1/6.1 to 5.1 downmixes */ + if (drcComp->fullChannels > 5) { + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* channel 1 (L, Ls,...) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* channel 2 (R, Rs,...) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* channel 3 (C) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + DOWNMIX_SHIFT); /* C */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); - /* allocate memory */ - hDcComp = (HDRC_COMP)FDKcalloc(1, sizeof(DRC_COMP)); + } /* for (blocklength) */ - if (hDcComp == NULL) { - err = -1; - goto bail; + /* take downmix gain into accout */ + peak[0] = fMult(dmxGain5, peak[0]) + << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + + /* 7.1 / 5.1 to stereo downmixes */ + if (drcComp->fullChannels > 2) { + /* Lt/Rt downmix */ + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* Lt */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Rt */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); } - FDKmemclear(hDcComp, sizeof(DRC_COMP)); + /* Lo/Ro downmix */ + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* Lo */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc - second path*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[LS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += + fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMultDiv2(lfe_lev, + (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + break; + } - /* Return drc compressor instance */ - *phDrcComp = hDcComp; - return err; -bail: - FDK_DRC_Generator_Close(&hDcComp); - return err; -} + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Ro */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc - second path*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[RS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += + fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMultDiv2(lfe_lev, + (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + } -INT FDK_DRC_Generator_Close( - HDRC_COMP *phDrcComp - ) -{ - if (phDrcComp == NULL) { - return -1; + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); } - if (*phDrcComp != NULL) { - FDKfree(*phDrcComp); - *phDrcComp = NULL; + } + + peak[1] = fixMax(peak[0], peak[1]); + + /* Mono Downmix - for comp_val only */ + if (drcComp->fullChannels > 1) { + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc - second path*/ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc - second path*/ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[LS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + /*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/ /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C (2*clev) */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + } + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[1] = fixMax(peak[1], fixp_abs(tmp)); } - return 0; + } } +INT FDK_DRC_Generator_Open(HDRC_COMP* phDrcComp) { + INT err = 0; + HDRC_COMP hDcComp = NULL; -INT FDK_DRC_Generator_Initialize( - HDRC_COMP drcComp, - const DRC_PROFILE profileLine, - const DRC_PROFILE profileRF, - const INT blockLength, - const UINT sampleRate, - const CHANNEL_MODE channelMode, - const CHANNEL_ORDER channelOrder, - const UCHAR useWeighting - ) -{ - int i; - CHANNEL_MAPPING channelMapping; - - drcComp->limDecay = FL2FXCONST_DBL( ((0.006f / 256) * blockLength) / METADATA_INT_SCALE ); - - /* Save parameters. */ - drcComp->blockLength = blockLength; - drcComp->sampleRate = sampleRate; - drcComp->chanConfig = channelMode; - drcComp->useWeighting = useWeighting; - - if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF)!=0) { /* expects initialized blockLength and sampleRate */ - return (-1); - } + if (phDrcComp == NULL) { + err = -1; + goto bail; + } - /* Set number of channels and channel offsets. */ - if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder, &channelMapping)!=AAC_ENC_OK) { - return (-2); - } + /* allocate memory */ + hDcComp = (HDRC_COMP)FDKcalloc(1, sizeof(DRC_COMP)); + + if (hDcComp == NULL) { + err = -1; + goto bail; + } - for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1; + FDKmemclear(hDcComp, sizeof(DRC_COMP)); - switch (channelMode) { + /* Return drc compressor instance */ + *phDrcComp = hDcComp; + return err; +bail: + FDK_DRC_Generator_Close(&hDcComp); + return err; +} + +INT FDK_DRC_Generator_Close(HDRC_COMP* phDrcComp) { + if (phDrcComp == NULL) { + return -1; + } + if (*phDrcComp != NULL) { + FDKfree(*phDrcComp); + *phDrcComp = NULL; + } + return 0; +} + +INT FDK_DRC_Generator_Initialize(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF, + const INT blockLength, const UINT sampleRate, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder, + const UCHAR useWeighting) { + int i; + CHANNEL_MAPPING channelMapping; + + drcComp->limDecay = + FL2FXCONST_DBL(((0.006f / 256) * blockLength) / METADATA_INT_SCALE); + + /* Save parameters. */ + drcComp->blockLength = blockLength; + drcComp->sampleRate = sampleRate; + drcComp->chanConfig = channelMode; + drcComp->useWeighting = useWeighting; + + if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF) != + 0) { /* expects initialized blockLength and sampleRate */ + return (-1); + } + + /* Set number of channels and channel offsets. */ + if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder, + &channelMapping) != AAC_ENC_OK) { + return (-2); + } + + for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1; + + switch (channelMode) { case MODE_1: /* mono */ - drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; - break; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; case MODE_2: /* stereo */ - drcComp->channelIdx[L] = channelMapping.elInfo[0].ChannelIndex[0]; - drcComp->channelIdx[R] = channelMapping.elInfo[0].ChannelIndex[1]; - break; + drcComp->channelIdx[L] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[0].ChannelIndex[1]; + break; case MODE_1_2: /* 3ch */ - drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; - drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; - drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; - break; + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; case MODE_1_2_1: /* 4ch */ - drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; - drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; - drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; - drcComp->channelIdx[S] = channelMapping.elInfo[2].ChannelIndex[0]; - break; + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[S] = channelMapping.elInfo[2].ChannelIndex[0]; + break; case MODE_1_2_2: /* 5ch */ - drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; - drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; - drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; - drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; - drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; - break; - case MODE_1_2_2_1: /* 5.1 ch */ - drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; - drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; - drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; - drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0]; - drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; - drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; - break; + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; + case MODE_1_2_2_1: /* 5.1 ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; case MODE_1_2_2_2_1: /* 7.1 ch */ case MODE_7_1_FRONT_CENTER: - drcComp->channelIdx[L] = channelMapping.elInfo[2].ChannelIndex[0]; /* l */ - drcComp->channelIdx[R] = channelMapping.elInfo[2].ChannelIndex[1]; /* r */ - drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ - drcComp->channelIdx[LFE] = channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ - drcComp->channelIdx[LS] = channelMapping.elInfo[3].ChannelIndex[0]; /* ls */ - drcComp->channelIdx[RS] = channelMapping.elInfo[3].ChannelIndex[1]; /* rs */ - drcComp->channelIdx[LS2] = channelMapping.elInfo[1].ChannelIndex[0]; /* lc */ - drcComp->channelIdx[RS2] = channelMapping.elInfo[1].ChannelIndex[1]; /* rc */ - break; + drcComp->channelIdx[L] = channelMapping.elInfo[2].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[2].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[3].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[3].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[1].ChannelIndex[0]; /* lc */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[1].ChannelIndex[1]; /* rc */ + break; + case MODE_7_1_BACK: case MODE_7_1_REAR_SURROUND: - drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ - drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ - drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ - drcComp->channelIdx[LFE] = channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ - drcComp->channelIdx[LS] = channelMapping.elInfo[3].ChannelIndex[0]; /* lrear */ - drcComp->channelIdx[RS] = channelMapping.elInfo[3].ChannelIndex[1]; /* rrear */ - drcComp->channelIdx[LS2] = channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ - drcComp->channelIdx[RS2] = channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ - break; - case MODE_1_1: - case MODE_1_1_1_1: - case MODE_1_1_1_1_1_1: - case MODE_1_1_1_1_1_1_1_1: - case MODE_1_1_1_1_1_1_1_1_1_1_1_1: - case MODE_2_2: - case MODE_2_2_2: - case MODE_2_2_2_2: - case MODE_2_2_2_2_2_2: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[3].ChannelIndex[0]; /* lrear */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[3].ChannelIndex[1]; /* rrear */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + break; + case MODE_6_1: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[S] = channelMapping.elInfo[3].ChannelIndex[0]; /* s */ + break; + case MODE_7_1_TOP_FRONT: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[3].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lvh2 */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[4].ChannelIndex[1]; /* rvh2 */ + break; default: - return (-1); - } + return (-1); + } - drcComp->fullChannels = channelMapping.nChannelsEff; - drcComp->channels = channelMapping.nChannels; + drcComp->fullChannels = channelMapping.nChannelsEff; + drcComp->channels = channelMapping.nChannels; - /* Init states. */ - drcComp->smoothLevel[0] = drcComp->smoothLevel[1] = (FIXP_DBL)(int)((unsigned)-135<smoothLevel[0] = drcComp->smoothLevel[1] = + (FIXP_DBL)(-(135 << METADATA_FRACT_BITS)); - FDKmemclear(drcComp->smoothGain, sizeof(drcComp->smoothGain)); - FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt)); - FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain)); - FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak)); - FDKmemclear(drcComp->filter, sizeof(drcComp->filter)); + FDKmemclear(drcComp->smoothGain, sizeof(drcComp->smoothGain)); + FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt)); + FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain)); + FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak)); + FDKmemclear(drcComp->filter, sizeof(drcComp->filter)); - return (0); + return (0); } +INT FDK_DRC_Generator_setDrcProfile(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF) { + int profileIdx, i; + + drcComp->profile[0] = profileLine; + drcComp->profile[1] = profileRF; + + for (i = 0; i < 2; i++) { + /* get profile index */ + switch (drcComp->profile[i]) { + case DRC_NONE: + case DRC_NOT_PRESENT: + case DRC_FILMSTANDARD: + profileIdx = 0; + break; + case DRC_FILMLIGHT: + profileIdx = 1; + break; + case DRC_MUSICSTANDARD: + profileIdx = 2; + break; + case DRC_MUSICLIGHT: + profileIdx = 3; + break; + case DRC_SPEECH: + profileIdx = 4; + break; + case DRC_DELAY_TEST: + profileIdx = 5; + break; + default: + return (-1); + } -INT FDK_DRC_Generator_setDrcProfile( - HDRC_COMP drcComp, - const DRC_PROFILE profileLine, - const DRC_PROFILE profileRF - ) -{ - int profileIdx, i; + /* get parameters for selected profile */ + if (profileIdx >= 0) { + drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx]; + drcComp->boostThr[i] = tabBoostThr[profileIdx]; + drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx]; + drcComp->cutThr[i] = tabCutThr[profileIdx]; + drcComp->maxCutThr[i] = tabMaxCutThr[profileIdx]; + + drcComp->boostFac[i] = tabBoostRatio[profileIdx]; + drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx]; + drcComp->cutFac[i] = tabCutRatio[profileIdx]; + + drcComp->maxBoost[i] = tabMaxBoost[profileIdx]; + drcComp->maxCut[i] = tabMaxCut[profileIdx]; + drcComp->maxEarlyCut[i] = + -fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]), + drcComp->earlyCutFac[i]); /* no scaling after mult needed, + earlyCutFac is in FIXP_DBL */ + + drcComp->fastAttack[i] = tc2Coeff( + tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->fastDecay[i] = tc2Coeff( + tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowAttack[i] = tc2Coeff( + tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowDecay[i] = tc2Coeff( + tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->holdOff[i] = tabHoldOff[profileIdx] * 256 / drcComp->blockLength; + + drcComp->attackThr[i] = tabAttackThr[profileIdx]; + drcComp->decayThr[i] = tabDecayThr[profileIdx]; + } - drcComp->profile[0] = profileLine; - drcComp->profile[1] = profileRF; + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } + return (0); +} - for (i = 0; i < 2; i++) { - /* get profile index */ - switch (drcComp->profile[i]) { - case DRC_NONE: - case DRC_FILMSTANDARD: profileIdx = 0; break; - case DRC_FILMLIGHT: profileIdx = 1; break; - case DRC_MUSICSTANDARD: profileIdx = 2; break; - case DRC_MUSICLIGHT: profileIdx = 3; break; - case DRC_SPEECH: profileIdx = 4; break; - case DRC_DELAY_TEST: profileIdx = 5; break; - default: return (-1); - } +INT FDK_DRC_Generator_Calc(HDRC_COMP drcComp, const INT_PCM* const inSamples, + const UINT inSamplesBufSize, const INT dialnorm, + const INT drc_TargetRefLevel, + const INT comp_TargetRefLevel, const FIXP_DBL clev, + const FIXP_DBL slev, const FIXP_DBL ext_leva, + const FIXP_DBL ext_levb, const FIXP_DBL lfe_lev, + const INT dmxGain5, const INT dmxGain2, + INT* const pDynrng, INT* const pCompr) { + int i, c; + FIXP_DBL peak[2]; + + /************************************************************************** + * compressor + **************************************************************************/ + if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) { + /* Calc loudness level */ + FIXP_DBL level_b = FL2FXCONST_DBL(0.f); + int level_e = DFRACT_BITS - 1; + + /* Increase energy time resolution with shorter processing blocks. 16 is an + * empiric value. */ + const int granuleLength = fixMin(16, drcComp->blockLength); + + if (drcComp->useWeighting) { + FIXP_DBL x1, x2, y, y1, y2; + /* sum of filter coefficients about 2.5 -> squared value is 6.25 + WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce + granuleShift by 1. + */ + const int granuleShift = getShiftFactor(granuleLength) - 1; - /* get parameters for selected profile */ - if (profileIdx >= 0) { - drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx]; - drcComp->boostThr[i] = tabBoostThr[profileIdx]; - drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx]; - drcComp->cutThr[i] = tabCutThr[profileIdx]; - drcComp->maxCutThr[i] = tabMaxCutThr[profileIdx]; - - drcComp->boostFac[i] = tabBoostRatio[profileIdx]; - drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx]; - drcComp->cutFac[i] = tabCutRatio[profileIdx]; - - drcComp->maxBoost[i] = tabMaxBoost[profileIdx]; - drcComp->maxCut[i] = tabMaxCut[profileIdx]; - drcComp->maxEarlyCut[i] = - fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); /* no scaling after mult needed, earlyCutFac is in FIXP_DBL */ - - drcComp->fastAttack[i] = tc2Coeff(tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); - drcComp->fastDecay[i] = tc2Coeff(tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); - drcComp->slowAttack[i] = tc2Coeff(tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); - drcComp->slowDecay[i] = tc2Coeff(tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); - drcComp->holdOff[i] = tabHoldOff[profileIdx] * 256 / drcComp->blockLength; - - drcComp->attackThr[i] = tabAttackThr[profileIdx]; - drcComp->decayThr[i] = tabDecayThr[profileIdx]; + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = inSamples + c * inSamplesBufSize; + + if (c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ } - drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); - } - return (0); -} + /* get filter states */ + x1 = drcComp->filter[c].x1; + x2 = drcComp->filter[c].x2; + y1 = drcComp->filter[c].y1; + y2 = drcComp->filter[c].y2; + i = 0; -INT FDK_DRC_Generator_Calc( - HDRC_COMP drcComp, - const INT_PCM * const inSamples, - const INT dialnorm, - const INT drc_TargetRefLevel, - const INT comp_TargetRefLevel, - FIXP_DBL clev, - FIXP_DBL slev, - INT * const pDynrng, - INT * const pCompr - ) -{ - int i, c; - FIXP_DBL peak[2]; + do { + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + for (i = offset; + i < fixMin(offset + granuleLength, drcComp->blockLength); i++) { + /* apply weighting filter */ + FIXP_DBL x = + FX_PCM2FX_DBL((FIXP_PCM)pSamples[i]) >> WEIGHTING_FILTER_SHIFT; - /************************************************************************** - * compressor - **************************************************************************/ - if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) { - /* Calc loudness level */ - FIXP_DBL level_b = FL2FXCONST_DBL(0.f); - int level_e = DFRACT_BITS-1; + /* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */ + y = fMult(b0, x - x2) - fMult(a1, y1) - fMult(a2, y2); - /* Increase energy time resolution with shorter processing blocks. 32 is an empiric value. */ - const int granuleLength = fixMin(32, drcComp->blockLength); - - if (drcComp->useWeighting) { - FIXP_DBL x1, x2, y, y1, y2; - /* sum of filter coefficients about 2.5 -> squared value is 6.25 - WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce granuleShift by 1. - */ - const int granuleShift = getShiftFactor(granuleLength)-1; - - for (c = 0; c < (int)drcComp->channels; c++) { - const INT_PCM* pSamples = &inSamples[c]; - - if (c == drcComp->channelIdx[LFE]) { - continue; /* skip LFE */ - } - - /* get filter states */ - x1 = drcComp->filter[c].x1; - x2 = drcComp->filter[c].x2; - y1 = drcComp->filter[c].y1; - y2 = drcComp->filter[c].y2; - - i = 0; - - do { - - int offset = i; - FIXP_DBL accu = FL2FXCONST_DBL(0.f); - - for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) { - /* apply weighting filter */ - FIXP_DBL x = FX_PCM2FX_DBL((FIXP_PCM)pSamples[i*drcComp->channels]) >> WEIGHTING_FILTER_SHIFT; - - /* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */ - y = fMult(b0,x-x2) - fMult(a1,y1) - fMult(a2,y2); - - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - - accu += fPow2Div2(y)>>(granuleShift-1); /* partial energy */ - } /* i */ - - fixpAdd(accu, granuleShift+2*WEIGHTING_FILTER_SHIFT, &level_b, &level_e); /* sup up partial energies */ - - } while ( i < drcComp->blockLength ); - - - /* save filter states */ - drcComp->filter[c].x1 = x1; - drcComp->filter[c].x2 = x2; - drcComp->filter[c].y1 = y1; - drcComp->filter[c].y2 = y2; - } /* c */ - } /* weighting */ - else { - const int granuleShift = getShiftFactor(granuleLength); - - for (c = 0; c < (int)drcComp->channels; c++) { - const INT_PCM* pSamples = &inSamples[c]; - - if ((int)c == drcComp->channelIdx[LFE]) { - continue; /* skip LFE */ - } - - i = 0; - - do { - int offset = i; - FIXP_DBL accu = FL2FXCONST_DBL(0.f); - - for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) { - /* partial energy */ - accu += fPow2Div2((FIXP_PCM)pSamples[i*drcComp->channels])>>(granuleShift-1); - } /* i */ - - fixpAdd(accu, granuleShift, &level_b, &level_e); /* sup up partial energies */ - - } while ( i < drcComp->blockLength ); - } - } /* weighting */ - - /* - * Convert to dBFS, apply dialnorm - */ - /* level scaling */ - - /* descaled level in ld64 representation */ - FIXP_DBL ldLevel = CalcLdData(level_b) + (FIXP_DBL)((level_e-12)<<(DFRACT_BITS-1-LD_DATA_SHIFT)) - CalcLdData((FIXP_DBL)(drcComp->blockLength<<(DFRACT_BITS-1-12))); - - /* if (level < 1e-10) level = 1e-10f; */ - ldLevel = FDKmax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f)); - - /* level = 10 * log(level)/log(10) + 3; - * = 10*log(2)/log(10) * ld(level) + 3; - * = 10 * 0.30102999566398119521373889472449 * ld(level) + 3 - * = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3) - * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64 - * - * additional scaling with METADATA_FRACT_BITS: - * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64 * 2^(METADATA_FRACT_BITS) - * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) - * = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * ( 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 ) - * */ - FIXP_DBL level = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) + (FIXP_DBL)(FL2FXCONST_DBL(0.3f)>>LD_DATA_SHIFT) ); - - /* level -= dialnorm + 31 */ /* this is fixed to Dolby-ReferenceLevel as compressor profiles are defined relative to this */ - level -= ((FIXP_DBL)(dialnorm<<(METADATA_FRACT_BITS-16)) + (FIXP_DBL)(31<profile[i] == DRC_NONE) { - /* no compression */ - drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); - } - else { - FIXP_DBL gain, alpha, lvl2smthlvl; - - /* calc static gain */ - if (level <= drcComp->maxBoostThr[i]) { - /* max boost */ - gain = drcComp->maxBoost[i]; - } - else if (level < drcComp->boostThr[i]) { - /* boost range */ - gain = fMult((level - drcComp->boostThr[i]),drcComp->boostFac[i]); - } - else if (level <= drcComp->earlyCutThr[i]) { - /* null band */ - gain = FL2FXCONST_DBL(0.f); - } - else if (level <= drcComp->cutThr[i]) { - /* early cut range */ - gain = fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); - } - else if (level < drcComp->maxCutThr[i]) { - /* cut range */ - gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) - drcComp->maxEarlyCut[i]; - } - else { - /* max cut */ - gain = -drcComp->maxCut[i]; - } - - /* choose time constant */ - lvl2smthlvl = level - drcComp->smoothLevel[i]; - if (gain < drcComp->smoothGain[i]) { - /* attack */ - if (lvl2smthlvl > drcComp->attackThr[i]) { - /* fast attack */ - alpha = drcComp->fastAttack[i]; - } - else { - /* slow attack */ - alpha = drcComp->slowAttack[i]; - } - } - else { - /* release */ - if (lvl2smthlvl < -drcComp->decayThr[i]) { - /* fast release */ - alpha = drcComp->fastDecay[i]; - } - else { - /* slow release */ - alpha = drcComp->slowDecay[i]; - } - } - - /* smooth gain & level */ - if ((gain < drcComp->smoothGain[i]) || (drcComp->holdCnt[i] == 0)) { /* hold gain unless we have an attack or hold period is over */ - FIXP_DBL accu; - - /* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] + alpha * level; */ - accu = fMult(((FIXP_DBL)MAXVAL_DBL-alpha), drcComp->smoothLevel[i]); - accu += fMult(alpha,level); - drcComp->smoothLevel[i] = accu; - - /* drcComp->smoothGain[i] = (1-alpha) * drcComp->smoothGain[i] + alpha * gain; */ - accu = fMult(((FIXP_DBL)MAXVAL_DBL-alpha), drcComp->smoothGain[i]); - accu += fMult(alpha,gain); - drcComp->smoothGain[i] = accu; - } - - /* hold counter */ - if (drcComp->holdCnt[i]) { - drcComp->holdCnt[i]--; - } - if (gain < drcComp->smoothGain[i]) { - drcComp->holdCnt[i] = drcComp->holdOff[i]; - } - } /* profile != DRC_NONE */ - } /* for i=1..2 */ - } else { - /* no compression */ - drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f); - drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f); - } + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; - /************************************************************************** - * limiter - **************************************************************************/ + accu += fPow2Div2(y) >> (granuleShift - 1); /* partial energy */ + } /* i */ - /* find peak level */ - peak[0] = peak[1] = FL2FXCONST_DBL(0.f); - for (i = 0; i < drcComp->blockLength; i++) { - FIXP_DBL tmp; - const INT_PCM* pSamples = &inSamples[i*drcComp->channels]; - INT_PCM maxSample = 0; + fixpAdd(accu, granuleShift + 2 * WEIGHTING_FILTER_SHIFT, &level_b, + &level_e); /* sup up partial energies */ + + } while (i < drcComp->blockLength); + + /* save filter states */ + drcComp->filter[c].x1 = x1; + drcComp->filter[c].x2 = x2; + drcComp->filter[c].y1 = y1; + drcComp->filter[c].y2 = y2; + } /* c */ + } /* weighting */ + else { + const int granuleShift = getShiftFactor(granuleLength); - /* single channels */ - for (c = 0; c < (int)drcComp->channels; c++) { - maxSample = FDKmax(maxSample, fAbs(pSamples[c])); + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = inSamples + c * inSamplesBufSize; + + if ((int)c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ } - peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample)>>DOWNMIX_SHIFT); - - /* Lt/Rt downmix */ - if (drcComp->fullChannels > 2) { - /* Lt */ - tmp = FL2FXCONST_DBL(0.f); - - if (drcComp->channelIdx[LS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ - if (drcComp->channelIdx[LS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ - if (drcComp->channelIdx[RS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ - if (drcComp->channelIdx[RS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ - if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ - if (drcComp->channelIdx[S] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1); /* S */ - if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ - tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */ - - peak[0] = fixMax(peak[0], fixp_abs(tmp)); - - /* Rt */ - tmp = FL2FXCONST_DBL(0.f); - if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ - if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ - if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ - if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ - if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ - if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1); /* S */ - if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ - tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */ - - peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + i = 0; + + do { + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + + for (i = offset; + i < fixMin(offset + granuleLength, drcComp->blockLength); i++) { + /* partial energy */ + accu += fPow2Div2((FIXP_PCM)pSamples[i]) >> (granuleShift - 1); + } /* i */ + + fixpAdd(accu, granuleShift, &level_b, + &level_e); /* sup up partial energies */ + + } while (i < drcComp->blockLength); + } + } /* weighting */ + + /* + * Convert to dBFS, apply dialnorm + */ + /* level scaling */ + + /* descaled level in ld64 representation */ + FIXP_DBL ldLevel = + CalcLdData(level_b) + + (FIXP_DBL)((level_e - 12) << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) - + CalcLdData((FIXP_DBL)(drcComp->blockLength << (DFRACT_BITS - 1 - 12))); + + /* if (level < 1e-10) level = 1e-10f; */ + ldLevel = + fMax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f)); + + /* level = 10 * log(level)/log(10) + 3; + * = 10*log(2)/log(10) * ld(level) + 3; + * = 10 * 0.30102999566398119521373889472449 * ld(level) + 3 + * = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3) + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) + * * 64 + * + * additional scaling with METADATA_FRACT_BITS: + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) + * * 64 * 2^(METADATA_FRACT_BITS) = 10 * (0.30102999566398119521373889472449 + * * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) = + * 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * ( + * 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 ) + * */ + FIXP_DBL level = fMult( + (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)), + fMult(FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) + + (FIXP_DBL)(FL2FXCONST_DBL(0.3f) >> LD_DATA_SHIFT)); + + /* level -= dialnorm + 31 */ /* this is fixed to Dolby-ReferenceLevel as + compressor profiles are defined relative to + this */ + level -= ((FIXP_DBL)(dialnorm << (METADATA_FRACT_BITS - 16)) + + (FIXP_DBL)(31 << METADATA_FRACT_BITS)); + + for (i = 0; i < 2; i++) { + if (drcComp->profile[i] == DRC_NONE) { + /* no compression */ + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } else { + FIXP_DBL gain, alpha, lvl2smthlvl; + + /* calc static gain */ + if (level <= drcComp->maxBoostThr[i]) { + /* max boost */ + gain = drcComp->maxBoost[i]; + } else if (level < drcComp->boostThr[i]) { + /* boost range */ + gain = fMult((level - drcComp->boostThr[i]), drcComp->boostFac[i]); + } else if (level <= drcComp->earlyCutThr[i]) { + /* null band */ + gain = FL2FXCONST_DBL(0.f); + } else if (level <= drcComp->cutThr[i]) { + /* early cut range */ + gain = + fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); + } else if (level < drcComp->maxCutThr[i]) { + /* cut range */ + gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) - + drcComp->maxEarlyCut[i]; + } else { + /* max cut */ + gain = -drcComp->maxCut[i]; } - /* Lo/Ro downmix */ - if (drcComp->fullChannels > 2) { - /* Lo */ - tmp = FL2FXCONST_DBL(0.f); - if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ - if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ - if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ - if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */ - if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ - tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */ - - peak[0] = fixMax(peak[0], fixp_abs(tmp)); - - /* Ro */ - tmp = FL2FXCONST_DBL(0.f); - if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ - if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ - if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ - if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */ - if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ - tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */ - - peak[0] = fixMax(peak[0], fixp_abs(tmp)); + /* choose time constant */ + lvl2smthlvl = level - drcComp->smoothLevel[i]; + if (gain < drcComp->smoothGain[i]) { + /* attack */ + if (lvl2smthlvl > drcComp->attackThr[i]) { + /* fast attack */ + alpha = drcComp->fastAttack[i]; + } else { + /* slow attack */ + alpha = drcComp->slowAttack[i]; + } + } else { + /* release */ + if (lvl2smthlvl < -drcComp->decayThr[i]) { + /* fast release */ + alpha = drcComp->fastDecay[i]; + } else { + /* slow release */ + alpha = drcComp->slowDecay[i]; + } } - peak[1] = fixMax(peak[0], peak[1]); - - /* Mono Downmix - for comp_val only */ - if (drcComp->fullChannels > 1) { - tmp = FL2FXCONST_DBL(0.f); - if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ - if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ - if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ - if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ - if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ - /*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/ /* 7.1ch */ - if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */ - if (drcComp->channelIdx[C] >= 0) tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C (2*clev) */ - tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */ - tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */ - - peak[1] = fixMax(peak[1], fixp_abs(tmp)); + /* smooth gain & level */ + if ((gain < drcComp->smoothGain[i]) || + (drcComp->holdCnt[i] == + 0)) { /* hold gain unless we have an attack or hold + period is over */ + FIXP_DBL accu; + + /* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] + + * alpha * level; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothLevel[i]); + accu += fMult(alpha, level); + drcComp->smoothLevel[i] = accu; + + /* drcComp->smoothGain[i] = (1-alpha) * drcComp->smoothGain[i] + + * alpha * gain; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothGain[i]); + accu += fMult(alpha, gain); + drcComp->smoothGain[i] = accu; } - } - for (i=0; i<2; i++) { - FIXP_DBL tmp = drcComp->prevPeak[i]; - drcComp->prevPeak[i] = peak[i]; - peak[i] = fixMax(peak[i], tmp); + /* hold counter */ + if (drcComp->holdCnt[i]) { + drcComp->holdCnt[i]--; + } + if (gain < drcComp->smoothGain[i]) { + drcComp->holdCnt[i] = drcComp->holdOff[i]; + } + } /* profile != DRC_NONE */ + } /* for i=1..2 */ + } else { + /* no compression */ + drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f); + drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f); + } - /* - * Convert to dBFS, apply dialnorm - */ - /* descaled peak in ld64 representation */ - FIXP_DBL ld_peak = CalcLdData(peak[i]) + (FIXP_DBL)((LONG)DOWNMIX_SHIFT<<(DFRACT_BITS-1-LD_DATA_SHIFT)); - - /* if (peak < 1e-6) level = 1e-6f; */ - ld_peak = FDKmax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f)); - - /* peak[i] = 20 * log(peak[i])/log(10) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) - * peak[i] = 20 * log(2)/log(10) * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) - * peak[i] = 10 * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) - * - * additional scaling with METADATA_FRACT_BITS: - * peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64 + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS) - * peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * 2*0.30102999566398119521373889472449 * ld64(peak[i]) - * + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i] - */ - peak[i] = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FX_DBL(2*0.30102999566398119521373889472449f), ld_peak)); - peak[i] += (FL2FX_DBL(0.5f)>>METADATA_INT_BITS); /* add a little bit headroom */ - peak[i] += drcComp->smoothGain[i]; - } + /************************************************************************** + * limiter + **************************************************************************/ + + findPeakLevels(drcComp, inSamples, clev, slev, ext_leva, ext_levb, lfe_lev, + (FIXP_DBL)((LONG)(dmxGain5) << (METADATA_FRACT_BITS - 16)), + (FIXP_DBL)((LONG)(dmxGain2) << (METADATA_FRACT_BITS - 16)), + peak); + + for (i = 0; i < 2; i++) { + FIXP_DBL tmp = drcComp->prevPeak[i]; + drcComp->prevPeak[i] = peak[i]; + peak[i] = fixMax(peak[i], tmp); + + /* + * Convert to dBFS, apply dialnorm + */ + /* descaled peak in ld64 representation */ + FIXP_DBL ld_peak = + CalcLdData(peak[i]) + + (FIXP_DBL)((LONG)DOWNMIX_SHIFT << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + /* if (peak < 1e-6) level = 1e-6f; */ + ld_peak = + fMax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f)); + + /* peak[i] = 20 * log(peak[i])/log(10) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 20 * + * log(2)/log(10) * ld(peak[i]) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 10 * + * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) + * + * additional scaling with METADATA_FRACT_BITS: + * peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64 + * + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS) + * peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * + * 2*0.30102999566398119521373889472449 * ld64(peak[i]) + * + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i] + */ + peak[i] = fMult( + (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)), + fMult(FL2FX_DBL(2 * 0.30102999566398119521373889472449f), ld_peak)); + peak[i] += + (FL2FX_DBL(0.5f) >> METADATA_INT_BITS); /* add a little bit headroom */ + peak[i] += drcComp->smoothGain[i]; + } - /* peak -= dialnorm + 31; */ /* this is Dolby style only */ - peak[0] -= (FIXP_DBL)((dialnorm-drc_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */ + /* peak -= dialnorm + 31; */ /* this is Dolby style only */ + peak[0] -= (FIXP_DBL)((dialnorm - drc_TargetRefLevel) + << (METADATA_FRACT_BITS - + 16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */ - /* peak += 11; */ /* this is Dolby style only */ /* RF mode output is 11dB higher */ - /*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/ - peak[1] -= (FIXP_DBL)((dialnorm-comp_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */ + /* peak += 11; */ + /* this is Dolby style only */ /* RF mode output is 11dB higher */ + /*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/ + peak[1] -= + (FIXP_DBL)((dialnorm - comp_TargetRefLevel) + << (METADATA_FRACT_BITS - + 16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */ - /* limiter gain */ - drcComp->limGain[0] += drcComp->limDecay; /* linear limiter release */ - drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]); + /* limiter gain */ + drcComp->limGain[0] += drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]); - drcComp->limGain[1] += 2*drcComp->limDecay; /* linear limiter release */ - drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]); + drcComp->limGain[1] += 2 * drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]); - /*************************************************************************/ + /*************************************************************************/ - /* apply limiting, return DRC gains*/ - { - FIXP_DBL tmp; + /* apply limiting, return DRC gains*/ + { + FIXP_DBL tmp; - tmp = drcComp->smoothGain[0]; - if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) { - tmp += drcComp->limGain[0]; - } - *pDynrng = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16)); + tmp = drcComp->smoothGain[0]; + if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[0]; + } + *pDynrng = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16)); - tmp = drcComp->smoothGain[1]; - if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) { - tmp += drcComp->limGain[1]; - } - *pCompr = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16)); + tmp = drcComp->smoothGain[1]; + if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[1]; } + *pCompr = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16)); + } - return 0; + return 0; } - -DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp) -{ - return drcComp->profile[0]; +DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp) { + return drcComp->profile[0]; } -DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp) -{ - return drcComp->profile[1]; +DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp) { + return drcComp->profile[1]; } - - -- cgit v1.2.3