diff options
author | Fraunhofer IIS FDK <audio-fdk@iis.fraunhofer.de> | 2018-02-26 20:17:00 +0100 |
---|---|---|
committer | Jean-Michel Trivi <jmtrivi@google.com> | 2018-04-19 11:21:15 -0700 |
commit | 6cfabd35363c3ef5e3b209b867169a500b3ccc3c (patch) | |
tree | 01c0a19f2735e8b5d2407555fe992d4230d089eb /libAACdec/src/conceal.cpp | |
parent | 6288a1e34c4dede4c2806beb1736ece6580558c7 (diff) | |
download | fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.tar.gz fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.tar.bz2 fdk-aac-6cfabd35363c3ef5e3b209b867169a500b3ccc3c.zip |
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
Diffstat (limited to 'libAACdec/src/conceal.cpp')
-rw-r--r-- | libAACdec/src/conceal.cpp | 2626 |
1 files changed, 1427 insertions, 1199 deletions
diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp index 1c313ef..91ba488 100644 --- a/libAACdec/src/conceal.cpp +++ b/libAACdec/src/conceal.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,53 +90,58 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/**************************** AAC decoder library ****************************** Author(s): Josef Hoepfl + Description: independent channel concealment -******************************************************************************/ +*******************************************************************************/ /*! \page concealment AAC core concealment - This AAC core implementation includes a concealment function, which can be enabled - using the several defines during compilation. + This AAC core implementation includes a concealment function, which can be + enabled using the several defines during compilation. - There are various tests inside the core, starting with simple CRC tests and ending in - a variety of plausibility checks. If such a check indicates an invalid bitstream, then - concealment is applied. + There are various tests inside the core, starting with simple CRC tests and + ending in a variety of plausibility checks. If such a check indicates an + invalid bitstream, then concealment is applied. - Concealment is also applied when the calling main program indicates a distorted or missing - data frame using the frameOK flag. This is used for error detection on the transport layer. - (See below) + Concealment is also applied when the calling main program indicates a + distorted or missing data frame using the frameOK flag. This is used for error + detection on the transport layer. (See below) There are three concealment-modes: - 1) Muting: The spectral data is simply set to zero in case of an detected error. - - 2) Noise substitution: In case of an detected error, concealment copies the last frame and adds - attenuates the spectral data. For this mode you have to set the #CONCEAL_NOISE define. - Noise substitution adds no additional delay. - - 3) Interpolation: The interpolation routine swaps the spectral data from the previous and the - current frame just before the final frequency to time conversion. In case a single frame is - corrupted, concealmant interpolates between the last good and the first good frame to create - the spectral data for the missing frame. If multiple frames are corrupted, concealment - implements first a fade out based on slightly modified spectral values from the last good - frame. As soon as good frames are available, concealmant fades in the new spectral data. - For this mode you have to set the #CONCEAL_INTER define. Note that in this case, you also - need to set #SBR_BS_DELAY_ENABLE, which basically adds approriate delay in the SBR decoder. - Note that the Interpolating-Concealment increases the delay of your decoder by one frame - and that it does require additional resources such as memory and computational complexity. + 1) Muting: The spectral data is simply set to zero in case of an detected + error. + + 2) Noise substitution: In case of an detected error, concealment copies the + last frame and adds attenuates the spectral data. For this mode you have to + set the #CONCEAL_NOISE define. Noise substitution adds no additional delay. + + 3) Interpolation: The interpolation routine swaps the spectral data from the + previous and the current frame just before the final frequency to time + conversion. In case a single frame is corrupted, concealmant interpolates + between the last good and the first good frame to create the spectral data for + the missing frame. If multiple frames are corrupted, concealment implements + first a fade out based on slightly modified spectral values from the last good + frame. As soon as good frames are available, concealmant fades in the new + spectral data. For this mode you have to set the #CONCEAL_INTER define. Note + that in this case, you also need to set #SBR_BS_DELAY_ENABLE, which basically + adds approriate delay in the SBR decoder. Note that the + Interpolating-Concealment increases the delay of your decoder by one frame and + that it does require additional resources such as memory and computational + complexity. <h2>How concealment can be used with errors on the transport layer</h2> - Many errors can or have to be detected on the transport layer. For example in IP based systems - packet loss can occur. The transport protocol used should indicate such packet loss by inserting - an empty frame with frameOK=0. + Many errors can or have to be detected on the transport layer. For example in + IP based systems packet loss can occur. The transport protocol used should + indicate such packet loss by inserting an empty frame with frameOK=0. */ #include "conceal.h" @@ -133,171 +149,153 @@ amm-info@iis.fraunhofer.de #include "aac_rom.h" #include "genericStds.h" - /* PNS (of block) */ #include "aacdec_pns.h" #include "block.h" -#include "FDK_tools_rom.h" - -#define CONCEAL_DFLT_COMF_NOISE_LEVEL ( 46 ) /* ~= -70 dB */ +#define CONCEAL_DFLT_COMF_NOISE_LEVEL (0x100000) +#define CONCEAL_NOT_DEFINED ((UCHAR)-1) /* default settings */ -#define CONCEAL_DFLT_FADEOUT_FRAMES ( 5 ) -#define CONCEAL_DFLT_FADEIN_FRAMES ( 5 ) -#define CONCEAL_DFLT_MUTE_RELEASE_FRAMES ( 3 ) +#define CONCEAL_DFLT_FADEOUT_FRAMES (0) +#define CONCEAL_DFLT_FADEIN_FRAMES (0) +#define CONCEAL_DFLT_MUTE_RELEASE_FRAMES (0) -#define CONCEAL_DFLT_FADE_FACTOR ( 0.707106781186548f ) /* 1/sqrt(2) */ +#define CONCEAL_DFLT_FADE_FACTOR (0.707106781186548f) /* 1/sqrt(2) */ /* some often used constants: */ -#define FIXP_ZERO FL2FXCONST_DBL(0.0f) -#define FIXP_ONE FL2FXCONST_DBL(1.0f) -#define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f) +#define FIXP_ZERO FL2FXCONST_DBL(0.0f) +#define FIXP_ONE FL2FXCONST_DBL(1.0f) +#define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f) /* For parameter conversion */ -#define CONCEAL_PARAMETER_BITS ( 8 ) -#define CONCEAL_MAX_QUANT_FACTOR ( (1<<CONCEAL_PARAMETER_BITS)-1 ) -/*#define CONCEAL_MIN_ATTENUATION_FACTOR_025 ( FL2FXCONST_DBL(0.971627951577106174) )*/ /* -0.25 dB */ -#define CONCEAL_MIN_ATTENUATION_FACTOR_025_LD FL2FXCONST_DBL(-0.041524101186092029596853445212299) -/*#define CONCEAL_MIN_ATTENUATION_FACTOR_050 ( FL2FXCONST_DBL(0.944060876285923380) )*/ /* -0.50 dB */ -#define CONCEAL_MIN_ATTENUATION_FACTOR_050_LD FL2FXCONST_DBL(-0.083048202372184059253597008145293) +#define CONCEAL_PARAMETER_BITS (8) +#define CONCEAL_MAX_QUANT_FACTOR ((1 << CONCEAL_PARAMETER_BITS) - 1) +/*#define CONCEAL_MIN_ATTENUATION_FACTOR_025 ( FL2FXCONST_DBL(0.971627951577106174) )*/ /* -0.25 dB */ +#define CONCEAL_MIN_ATTENUATION_FACTOR_025_LD \ + FL2FXCONST_DBL(-0.041524101186092029596853445212299) +/*#define CONCEAL_MIN_ATTENUATION_FACTOR_050 ( FL2FXCONST_DBL(0.944060876285923380) )*/ /* -0.50 dB */ +#define CONCEAL_MIN_ATTENUATION_FACTOR_050_LD \ + FL2FXCONST_DBL(-0.083048202372184059253597008145293) typedef enum { CConcealment_NoExpand, CConcealment_Expand, CConcealment_Compress -} -CConcealmentExpandType; +} CConcealmentExpandType; static const FIXP_SGL facMod4Table[4] = { - FL2FXCONST_SGL(0.500000000f), /* FIXP_SGL(0x4000), 2^-(1-0,00) */ - FL2FXCONST_SGL(0.594603558f), /* FIXP_SGL(0x4c1b), 2^-(1-0,25) */ - FL2FXCONST_SGL(0.707106781f), /* FIXP_SGL(0x5a82), 2^-(1-0,50) */ - FL2FXCONST_SGL(0.840896415f) /* FIXP_SGL(0x6ba2) 2^-(1-0,75) */ + FL2FXCONST_SGL(0.500000000f), /* FIXP_SGL(0x4000), 2^-(1-0,00) */ + FL2FXCONST_SGL(0.594603558f), /* FIXP_SGL(0x4c1b), 2^-(1-0,25) */ + FL2FXCONST_SGL(0.707106781f), /* FIXP_SGL(0x5a82), 2^-(1-0,50) */ + FL2FXCONST_SGL(0.840896415f) /* FIXP_SGL(0x6ba2) 2^-(1-0,75) */ }; +static void CConcealment_CalcBandEnergy( + FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo, + const int blockType, CConcealmentExpandType ex, int *sfbEnergy); +static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum, + SHORT *pSpecScalePrev, + SHORT *pSpecScaleAct, + SHORT *pSpecScaleOut, int *enPrv, + int *enAct, int sfbCnt, + const SHORT *pSfbOffset); - -static void - CConcealment_CalcBandEnergy ( - FIXP_DBL *spectrum, - const SamplingRateInfo *pSamplingRateInfo, - const int blockType, - CConcealmentExpandType ex, - int *sfbEnergy - ); - -static void - CConcealment_InterpolateBuffer ( - FIXP_DBL *spectrum, - SHORT *pSpecScalePrev, - SHORT *pSpecScaleAct, - SHORT *pSpecScaleOut, - int *enPrv, - int *enAct, - int sfbCnt, - const SHORT *pSfbOffset - ); - -static int - CConcealment_ApplyInter ( - CConcealmentInfo *pConcealmentInfo, +static int CConcealment_ApplyInter( + CConcealmentInfo *pConcealmentInfo, CAacDecoderChannelInfo *pAacDecoderChannelInfo, - const SamplingRateInfo *pSamplingRateInfo, - const int samplesPerFrame, - const int improveTonal, - const int frameOk - ); - - + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const int improveTonal, const int frameOk, const int mute_release_active); -static int - CConcealment_ApplyNoise ( +static int CConcealment_ApplyNoise( CConcealmentInfo *pConcealmentInfo, CAacDecoderChannelInfo *pAacDecoderChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - const SamplingRateInfo *pSamplingRateInfo, - const int samplesPerFrame, - const UINT flags - ); + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UINT flags); -static void - CConcealment_UpdateState ( - CConcealmentInfo *pConcealmentInfo, - int frameOk - ); - -static void - CConcealment_ApplyRandomSign ( - int iRandomPhase, - FIXP_DBL *spec, - int samplesPerFrame - ); +static void CConcealment_UpdateState( + CConcealmentInfo *pConcealmentInfo, int frameOk, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec, + int samplesPerFrame); + +/* TimeDomainFading */ +static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, + FIXP_DBL fadeStop, FIXP_PCM *pcmdata); +static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations, + int *fadingSteps, + FIXP_DBL fadeStop, + FIXP_DBL fadeStart, + TDfadingType fadingType); +static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps); + +/* Streamline the state machine */ +static int CConcealment_ApplyFadeOut( + int mode, CConcealmentInfo *pConcealmentInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo); +static int CConcealment_TDNoise_Random(ULONG *seed); +static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, + const int len, FIXP_PCM *const pcmdata); -static int CConcealment_GetWinSeq(int prevWinSeq) -{ - int newWinSeq = OnlyLongSequence; +static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) { + BLOCK_TYPE newWinSeq = BLOCK_LONG; /* Try to have only long blocks */ - if ( prevWinSeq == LongStartSequence - || prevWinSeq == EightShortSequence ) - { - newWinSeq = LongStopSequence; + if (prevWinSeq == BLOCK_START || prevWinSeq == BLOCK_SHORT) { + newWinSeq = BLOCK_STOP; } return (newWinSeq); } - /*! \brief Init common concealment information data - \pConcealCommonData Pointer to the concealment common data structure. - - \return none + \param pConcealCommonData Pointer to the concealment common data structure. */ -void - CConcealment_InitCommonData (CConcealParams *pConcealCommonData) -{ - if (pConcealCommonData != NULL) - { +void CConcealment_InitCommonData(CConcealParams *pConcealCommonData) { + if (pConcealCommonData != NULL) { int i; /* Set default error concealment technique */ pConcealCommonData->method = ConcealMethodInter; - pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES; - pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES; + pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES; + pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES; pConcealCommonData->numMuteReleaseFrames = CONCEAL_DFLT_MUTE_RELEASE_FRAMES; - pConcealCommonData->comfortNoiseLevel = CONCEAL_DFLT_COMF_NOISE_LEVEL; + pConcealCommonData->comfortNoiseLevel = + (FIXP_DBL)CONCEAL_DFLT_COMF_NOISE_LEVEL; /* Init fade factors (symetric) */ - pConcealCommonData->fadeOutFactor[0] = FL2FXCONST_SGL( CONCEAL_DFLT_FADE_FACTOR ); - pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0]; + pConcealCommonData->fadeOutFactor[0] = + FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR); + pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0]; for (i = 1; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { - pConcealCommonData->fadeOutFactor[i] = FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i-1],FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR))); - pConcealCommonData->fadeInFactor[i] = pConcealCommonData->fadeOutFactor[i]; + pConcealCommonData->fadeOutFactor[i] = + FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i - 1], + FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR))); + pConcealCommonData->fadeInFactor[i] = + pConcealCommonData->fadeOutFactor[i]; } } } - - /*! \brief Get current concealment method. - \pConcealCommonData Pointer to common concealment data (for all channels) - - \return Concealment method. + \param pConcealCommonData Pointer to common concealment data (for all + channels) */ -CConcealmentMethod - CConcealment_GetMethod( CConcealParams *pConcealCommonData ) -{ +CConcealmentMethod CConcealment_GetMethod(CConcealParams *pConcealCommonData) { CConcealmentMethod method = ConcealMethodNone; if (pConcealCommonData != NULL) { @@ -307,95 +305,95 @@ CConcealmentMethod return (method); } - /*! \brief Init concealment information for each channel - The function initializes the concealment information. Two methods can be chosen: - 0 = interpolation method (adds delay) - 1 = noise substitution (no delay, low complexity) - - \return none + \param pConcealChannelInfo Pointer to the channel related concealment info + structure to be initialized. \param pConcealCommonData Pointer to common + concealment data (for all channels) \param initRenderMode Initial render + mode to be set for the current channel. \param samplesPerFrame The number + of samples per frame. */ -void - CConcealment_InitChannelData ( - CConcealmentInfo *pConcealChannelInfo, - CConcealParams *pConcealCommonData, - int samplesPerFrame ) -{ +void CConcealment_InitChannelData(CConcealmentInfo *pConcealChannelInfo, + CConcealParams *pConcealCommonData, + AACDEC_RENDER_MODE initRenderMode, + int samplesPerFrame) { int i; + pConcealChannelInfo->TDNoiseSeed = 0; + FDKmemclear(pConcealChannelInfo->TDNoiseStates, + sizeof(pConcealChannelInfo->TDNoiseStates)); + pConcealChannelInfo->TDNoiseCoef[0] = FL2FXCONST_SGL(0.05f); + pConcealChannelInfo->TDNoiseCoef[1] = FL2FXCONST_SGL(0.5f); + pConcealChannelInfo->TDNoiseCoef[2] = FL2FXCONST_SGL(0.45f); pConcealChannelInfo->pConcealParams = pConcealCommonData; - FDKmemclear(pConcealChannelInfo->spectralCoefficient, 1024 * sizeof(FIXP_CNCL)); + pConcealChannelInfo->lastRenderMode = initRenderMode; + + pConcealChannelInfo->windowShape = CONCEAL_NOT_DEFINED; + pConcealChannelInfo->windowSequence = BLOCK_LONG; /* default type */ + pConcealChannelInfo->lastWinGrpLen = 1; + + pConcealChannelInfo->concealState = ConcealState_Ok; + + FDKmemclear(pConcealChannelInfo->spectralCoefficient, + 1024 * sizeof(FIXP_CNCL)); for (i = 0; i < 8; i++) { pConcealChannelInfo->specScale[i] = 0; } - pConcealChannelInfo->iRandomPhase = 0; - - pConcealChannelInfo->windowSequence = 0; - pConcealChannelInfo->windowShape = 0; + pConcealChannelInfo->iRandomPhase = 0; pConcealChannelInfo->prevFrameOk[0] = 1; pConcealChannelInfo->prevFrameOk[1] = 1; - pConcealChannelInfo->cntFadeFrames = 0; + pConcealChannelInfo->cntFadeFrames = 0; pConcealChannelInfo->cntValidFrames = 0; - - pConcealChannelInfo->concealState = ConcealState_Ok; - + pConcealChannelInfo->fade_old = (FIXP_DBL)MAXVAL_DBL; + pConcealChannelInfo->winGrpOffset[0] = 0; + pConcealChannelInfo->winGrpOffset[1] = 0; + pConcealChannelInfo->attGrpOffset[0] = 0; + pConcealChannelInfo->attGrpOffset[1] = 0; } - /*! \brief Set error concealment parameters - \concealParams - \method - \fadeOutSlope - \fadeInSlope - \muteRelease - \comfNoiseLevel - - \return none + \param concealParams + \param method + \param fadeOutSlope + \param fadeInSlope + \param muteRelease + \param comfNoiseLevel */ AAC_DECODER_ERROR - CConcealment_SetParams ( - CConcealParams *concealParams, - int method, - int fadeOutSlope, - int fadeInSlope, - int muteRelease, - int comfNoiseLevel ) -{ +CConcealment_SetParams(CConcealParams *concealParams, int method, + int fadeOutSlope, int fadeInSlope, int muteRelease, + FIXP_DBL comfNoiseLevel) { /* set concealment technique */ if (method != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { - switch ((CConcealmentMethod)method) - { - case ConcealMethodMute: - case ConcealMethodNoise: - case ConcealMethodInter: - /* Be sure to enable delay adjustment of SBR decoder! */ - if (concealParams == NULL) { - return AAC_DEC_INVALID_HANDLE; - } else { - /* set param */ - concealParams->method = (CConcealmentMethod)method; - } - break; + switch ((CConcealmentMethod)method) { + case ConcealMethodMute: + case ConcealMethodNoise: + case ConcealMethodInter: + /* Be sure to enable delay adjustment of SBR decoder! */ + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->method = (CConcealmentMethod)method; + } + break; - default: - return AAC_DEC_SET_PARAM_FAIL; + default: + return AAC_DEC_SET_PARAM_FAIL; } } /* set number of frames for fade-out slope */ if (fadeOutSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { - if ( (fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS) - && (fadeOutSlope >= 0) ) - { + if ((fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeOutSlope >= 0)) { if (concealParams == NULL) { return AAC_DEC_INVALID_HANDLE; } else { @@ -409,9 +407,7 @@ AAC_DECODER_ERROR /* set number of frames for fade-in slope */ if (fadeInSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { - if ( (fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS) - && (fadeInSlope >= 1) ) - { + if ((fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeInSlope >= 0)) { if (concealParams == NULL) { return AAC_DEC_INVALID_HANDLE; } else { @@ -425,9 +421,8 @@ AAC_DECODER_ERROR /* set number of error-free frames after which the muting will be released */ if (muteRelease != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { - if ( (muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS<<1)) - && (muteRelease >= 0) ) - { + if ((muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS << 1)) && + (muteRelease >= 0)) { if (concealParams == NULL) { return AAC_DEC_INVALID_HANDLE; } else { @@ -440,50 +435,46 @@ AAC_DECODER_ERROR } /* set confort noise level which will be inserted while in state 'muting' */ - if (comfNoiseLevel != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { - if ( (comfNoiseLevel < -1) - || (comfNoiseLevel > 127) ) { + if (comfNoiseLevel != (FIXP_DBL)AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((comfNoiseLevel < (FIXP_DBL)0) || + (comfNoiseLevel > (FIXP_DBL)MAXVAL_DBL)) { return AAC_DEC_SET_PARAM_FAIL; } if (concealParams == NULL) { return AAC_DEC_INVALID_HANDLE; } else { - concealParams->comfortNoiseLevel = comfNoiseLevel; + concealParams->comfortNoiseLevel = (FIXP_DBL)comfNoiseLevel; } } return (AAC_DEC_OK); } - /*! \brief Set fade-out/in attenuation factor vectors - \concealParams - \fadeOutAttenuationVector - \fadeInAttenuationVector + \param concealParams + \param fadeOutAttenuationVector + \param fadeInAttenuationVector \return 0 if OK all other values indicate errors */ AAC_DECODER_ERROR - CConcealment_SetAttenuation ( - CConcealParams *concealParams, - SHORT *fadeOutAttenuationVector, - SHORT *fadeInAttenuationVector ) -{ - if ( (fadeOutAttenuationVector == NULL) - && (fadeInAttenuationVector == NULL) ) { +CConcealment_SetAttenuation(CConcealParams *concealParams, + const SHORT *fadeOutAttenuationVector, + const SHORT *fadeInAttenuationVector) { + if ((fadeOutAttenuationVector == NULL) && (fadeInAttenuationVector == NULL)) { return AAC_DEC_SET_PARAM_FAIL; } /* Fade-out factors */ - if (fadeOutAttenuationVector != NULL) - { + if (fadeOutAttenuationVector != NULL) { int i; /* check quantized factors first */ for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { - if ((fadeOutAttenuationVector[i] < 0) || (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + if ((fadeOutAttenuationVector[i] < 0) || + (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { return AAC_DEC_SET_PARAM_FAIL; } } @@ -492,26 +483,24 @@ AAC_DECODER_ERROR } /* now dequantize factors */ - for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) - { + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { concealParams->fadeOutFactor[i] = - FX_DBL2FX_SGL( fLdPow( CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, - 0, - (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0/2.0)>>(CONCEAL_PARAMETER_BITS-1)) * (INT)fadeOutAttenuationVector[i]), - CONCEAL_PARAMETER_BITS - ) - ); + FX_DBL2FX_SGL(fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0, + (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0 / 2.0) >> + (CONCEAL_PARAMETER_BITS - 1)) * + (INT)fadeOutAttenuationVector[i]), + CONCEAL_PARAMETER_BITS)); } } /* Fade-in factors */ - if (fadeInAttenuationVector != NULL) - { + if (fadeInAttenuationVector != NULL) { int i; /* check quantized factors first */ for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { - if ((fadeInAttenuationVector[i] < 0) || (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + if ((fadeInAttenuationVector[i] < 0) || + (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { return AAC_DEC_SET_PARAM_FAIL; } } @@ -520,34 +509,26 @@ AAC_DECODER_ERROR } /* now dequantize factors */ - for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) - { - concealParams->fadeInFactor[i] = - FX_DBL2FX_SGL( fLdPow( CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, - 0, - (FIXP_DBL)((INT)(FIXP_ONE>>CONCEAL_PARAMETER_BITS) * (INT)fadeInAttenuationVector[i]), - CONCEAL_PARAMETER_BITS - ) - ); + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + concealParams->fadeInFactor[i] = FX_DBL2FX_SGL( + fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0, + (FIXP_DBL)((INT)(FIXP_ONE >> CONCEAL_PARAMETER_BITS) * + (INT)fadeInAttenuationVector[i]), + CONCEAL_PARAMETER_BITS)); } } return (AAC_DEC_OK); } - /*! \brief Get state of concealment module. - \pConcealChannelInfo + \param pConcealChannelInfo \return Concealment state. */ -CConcealmentState - CConcealment_GetState ( - CConcealmentInfo *pConcealChannelInfo - ) -{ +CConcealmentState CConcealment_GetState(CConcealmentInfo *pConcealChannelInfo) { CConcealmentState state = ConcealState_Ok; if (pConcealChannelInfo != NULL) { @@ -557,254 +538,247 @@ CConcealmentState return (state); } - -static void CConcealment_fakePnsData ( - CPnsData *pPnsData, - CIcsInfo *pIcsInfo, - const SamplingRateInfo *pSamplingRateInfo, - SHORT *pSpecScale, - SHORT *pScaleFactor, - const int level ) -{ - CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; - - int pnsBand, band, group, win; - //int delta = 0; - int windowsPerFrame = GetWindowsPerFrame(pIcsInfo); - int refLevel = (windowsPerFrame > 1) ? 82 : 91; - - FDK_ASSERT(level >= 0 && level <= 127); - - for (win = 0; win < windowsPerFrame; win++) { - pSpecScale[win] = 31; - } - - /* fake ICS info if necessary */ - if (!IsValid(pIcsInfo)) { - pIcsInfo->WindowGroups = 1; - if (IsLongBlock(pIcsInfo)) { - pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long; - pIcsInfo->WindowGroupLength[0] = 1; - } - else { - pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short; - pIcsInfo->WindowGroupLength[0] = 8; - } - pIcsInfo->MaxSfBands = pIcsInfo->TotalSfBands; - } - - /* global activate PNS */ - pPnsData->PnsActive = 1; - /* set energy level */ - pPnsData->CurrentEnergy = fixMax( 0, refLevel - level ); - - /* - value: | Avg. RMS power | Avg. RMS power | - | specScale = 22 | specScale = 31 | - -------+----------------+----------------+ - 5 | | -99.0 dB - 15 | | -90.0 dB - 25 | | -89.7 dB - 35 | | -85.3 dB - ... | ... | ... - 45 | -69.9 dB | -70.0 dB - 50 | -62.2 dB | - 55 | -55.6 dB | -54.6 dB - 60 | -47.0 dB | - 65 | -39.5 dB | -39.5 dB - 70 | -31.9 dB | - 75 | -24.4 dB | -24.4 dB - 80 | -16.9 dB | - 85 | -9.4 dB (c) | -9.4 dB - 90 | -3.9 dB (c) | - 95 | | -2.1 dB - 100 | | -1.6 dB - 105 | | -1.4 dB - */ - - for (group=0; group < GetWindowGroups(pIcsInfo); group++) - { - for (band=0; band < GetScaleFactorBandsTransmitted(pIcsInfo); band++) - { - pnsBand = group * 16 + band; - - if (pnsBand >= NO_OFBANDS) { - return; - } - //pPnsData->CurrentEnergy += delta ; - pScaleFactor[pnsBand] = pPnsData->CurrentEnergy; - pInterChannelData->correlated[pnsBand] = 0; - pPnsData->pnsUsed[pnsBand] = 1; - } - } -} - - /*! \brief Store data for concealment techniques applied later Interface function to store data for different concealment strategies - - \return none */ -void - CConcealment_Store ( +void CConcealment_Store( CConcealmentInfo *hConcealmentInfo, CAacDecoderChannelInfo *pAacDecoderChannelInfo, - CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo ) -{ - if ( !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD - ) ) + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + UCHAR nbDiv = NB_DIV; + + if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderChannelInfo->data.usac.mod[nbDiv - 1] == 0)) + { - FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); - SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; - CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; - SHORT tSpecScale[8]; - UCHAR tWindowShape, tWindowSequence; + SHORT tSpecScale[8]; + UCHAR tWindowShape; + BLOCK_TYPE tWindowSequence; /* store old window infos for swapping */ tWindowSequence = hConcealmentInfo->windowSequence; - tWindowShape = hConcealmentInfo->windowShape; + tWindowShape = hConcealmentInfo->windowShape; /* store old scale factors for swapping */ - FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8*sizeof(SHORT)); + FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT)); /* store new window infos */ hConcealmentInfo->windowSequence = GetWindowSequence(pIcsInfo); - hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo); - hConcealmentInfo->lastWinGrpLen = *(GetWindowGroupLengthTable(pIcsInfo)+GetWindowGroups(pIcsInfo)-1); + hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo); + hConcealmentInfo->lastWinGrpLen = + *(GetWindowGroupLengthTable(pIcsInfo) + GetWindowGroups(pIcsInfo) - 1); /* store new scale factors */ - FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8*sizeof(SHORT)); + FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8 * sizeof(SHORT)); - if (CConcealment_GetDelay(hConcealmentInfo->pConcealParams) == 0) - { - /* store new spectral bins */ + if (hConcealmentInfo->pConcealParams->method < ConcealMethodInter) { + /* store new spectral bins */ #if (CNCL_FRACT_BITS == DFRACT_BITS) - FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL)); + FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient, + 1024 * sizeof(FIXP_CNCL)); #else - FIXP_CNCL *RESTRICT pCncl = &hConcealmentInfo->spectralCoefficient[1024-1]; - FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024-1]; + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; int i; - for (i = 1024; i != 0; i--) { *pCncl-- = FX_DBL2FX_CNCL(*pSpec--); } #endif - } - else - { - FIXP_CNCL *RESTRICT pCncl = &hConcealmentInfo->spectralCoefficient[1024-1]; - FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024-1]; - int i; + } else { + /* swap spectral data */ +#if (FIXP_CNCL == FIXP_DBL) + C_ALLOC_SCRATCH_START(pSpecTmp, FIXP_DBL, 1024); + FDKmemcpy(pSpecTmp, pSpectralCoefficient, 1024 * sizeof(FIXP_DBL)); + FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient, + 1024 * sizeof(FIXP_DBL)); + FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpecTmp, + 1024 * sizeof(FIXP_DBL)); + C_ALLOC_SCRATCH_END(pSpecTmp, FIXP_DBL, 1024); +#else + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + FIXP_DBL tSpec; - /* swap spectral data */ - for (i = 1024; i != 0; i--) { - FIXP_DBL tSpec = *pSpec; + for (int i = 1024; i != 0; i--) { + tSpec = *pSpec; *pSpec-- = FX_CNCL2FX_DBL(*pCncl); - *pCncl-- = FX_DBL2FX_CNCL( tSpec); + *pCncl-- = FX_DBL2FX_CNCL(tSpec); } +#endif /* complete swapping of window infos */ pIcsInfo->WindowSequence = tWindowSequence; - pIcsInfo->WindowShape = tWindowShape; + pIcsInfo->WindowShape = tWindowShape; /* complete swapping of scale factors */ - FDKmemcpy(pSpecScale, tSpecScale, 8*sizeof(SHORT)); + FDKmemcpy(pSpecScale, tSpecScale, 8 * sizeof(SHORT)); } } - -} + if (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD) { + /* Store LSF4 */ + FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf, + sizeof(hConcealmentInfo->lsf4)); + /* Store TCX gain */ + hConcealmentInfo->last_tcx_gain = + pAacDecoderStaticChannelInfo->last_tcx_gain; + hConcealmentInfo->last_tcx_gain_e = + pAacDecoderStaticChannelInfo->last_tcx_gain_e; + } +} /*! \brief Apply concealment Interface function to different concealment strategies - - \return none */ -int - CConcealment_Apply ( +int CConcealment_Apply( CConcealmentInfo *hConcealmentInfo, CAacDecoderChannelInfo *pAacDecoderChannelInfo, CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - const SamplingRateInfo *pSamplingRateInfo, - const int samplesPerFrame, - const UCHAR lastLpdMode, - const int frameOk, - const UINT flags) -{ + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UCHAR lastLpdMode, const int frameOk, const UINT flags) { int appliedProcessing = 0; - - if ( (frameOk == 0) - && (pAacDecoderChannelInfo->renderMode != (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode) ) { - /* restore the last render mode to stay in the same domain which allows to do a proper concealment */ - pAacDecoderChannelInfo->renderMode = (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode; - } else { - /* otherwise store the current mode */ - hConcealmentInfo->lastRenderMode = (SCHAR)pAacDecoderChannelInfo->renderMode; + const int mute_release_active = + frameOk && (hConcealmentInfo->concealState >= ConcealState_Mute) && + (hConcealmentInfo->cntValidFrames + 1 <= + hConcealmentInfo->pConcealParams->numMuteReleaseFrames); + + if (hConcealmentInfo->windowShape == CONCEAL_NOT_DEFINED) { + /* Initialize window_shape with same value as in the current (parsed) frame. + Because section 4.6.11.3.2 (Windowing and block switching) of ISO/IEC + 14496-3:2009 says: For the first raw_data_block() to be decoded the + window_shape of the left and right half of the window are identical. */ + hConcealmentInfo->windowShape = pAacDecoderChannelInfo->icsInfo.WindowShape; } - if ( frameOk ) - { + if (frameOk && !mute_release_active) { + /* Update render mode if frameOk except for ongoing mute release state. */ + hConcealmentInfo->lastRenderMode = + (SCHAR)pAacDecoderChannelInfo->renderMode; + /* Rescue current data for concealment in future frames */ - CConcealment_Store ( hConcealmentInfo, - pAacDecoderChannelInfo, - pAacDecoderStaticChannelInfo ); - /* Reset index to random sign vector to make sign calculation frame agnostic + CConcealment_Store(hConcealmentInfo, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo); + /* Reset index to random sign vector to make sign calculation frame agnostic (only depends on number of subsequently concealed spectral blocks) */ - hConcealmentInfo->iRandomPhase = 0; + hConcealmentInfo->iRandomPhase = 0; + } else { + if (hConcealmentInfo->lastRenderMode == AACDEC_RENDER_INVALID) { + hConcealmentInfo->lastRenderMode = AACDEC_RENDER_IMDCT; + } + pAacDecoderChannelInfo->renderMode = + (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode; } /* hand current frame status to the state machine */ - CConcealment_UpdateState( hConcealmentInfo, - frameOk ); + CConcealment_UpdateState(hConcealmentInfo, frameOk, + pAacDecoderStaticChannelInfo, samplesPerFrame, + pAacDecoderChannelInfo); { - /* Create data for signal rendering according to the selected concealment method and decoder operating mode. */ + if (!frameOk && pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_IMDCT) { + /* LPC extrapolation */ + CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff, + pAacDecoderStaticChannelInfo->lpc4_lsf, + pAacDecoderStaticChannelInfo->lsf_adaptive_mean, + hConcealmentInfo->lastRenderMode == AACDEC_RENDER_IMDCT); + FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf, + sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf)); + } + /* Create data for signal rendering according to the selected concealment + * method and decoder operating mode. */ + + if ((!frameOk || mute_release_active) && + (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD)) { + /* Restore old LSF4 */ + FDKmemcpy(pAacDecoderStaticChannelInfo->lpc4_lsf, hConcealmentInfo->lsf4, + sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf)); + /* Restore old TCX gain */ + pAacDecoderStaticChannelInfo->last_tcx_gain = + hConcealmentInfo->last_tcx_gain; + pAacDecoderStaticChannelInfo->last_tcx_gain_e = + hConcealmentInfo->last_tcx_gain_e; + } - if ( !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD - ) - ) - { - switch (hConcealmentInfo->pConcealParams->method) - { - default: - case ConcealMethodMute: - if (!frameOk) { - /* Mute spectral data in case of errors */ - FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); - /* Set last window shape */ - pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape; - appliedProcessing = 1; - } - break; + if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderStaticChannelInfo->last_lpd_mode == 0)) { + switch (hConcealmentInfo->pConcealParams->method) { + default: + case ConcealMethodMute: + if (!frameOk) { + /* Mute spectral data in case of errors */ + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, + samplesPerFrame * sizeof(FIXP_DBL)); + /* Set last window shape */ + pAacDecoderChannelInfo->icsInfo.WindowShape = + hConcealmentInfo->windowShape; + appliedProcessing = 1; + } + break; + + case ConcealMethodNoise: + /* Noise substitution error concealment technique */ + appliedProcessing = CConcealment_ApplyNoise( + hConcealmentInfo, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo, pSamplingRateInfo, samplesPerFrame, + flags); + break; + + case ConcealMethodInter: + /* Energy interpolation concealment based on 3GPP */ + appliedProcessing = CConcealment_ApplyInter( + hConcealmentInfo, pAacDecoderChannelInfo, pSamplingRateInfo, + samplesPerFrame, 0, /* don't use tonal improvement */ + frameOk, mute_release_active); + break; + } + } else if (!frameOk || mute_release_active) { + /* simply restore the buffer */ + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; +#if (CNCL_FRACT_BITS != DFRACT_BITS) + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + int i; +#endif - case ConcealMethodNoise: - /* Noise substitution error concealment technique */ - appliedProcessing = - CConcealment_ApplyNoise (hConcealmentInfo, - pAacDecoderChannelInfo, - pAacDecoderStaticChannelInfo, - pSamplingRateInfo, - samplesPerFrame, - flags); - break; + /* restore window infos (gri) do we need that? */ + pIcsInfo->WindowSequence = hConcealmentInfo->windowSequence; + pIcsInfo->WindowShape = hConcealmentInfo->windowShape; - case ConcealMethodInter: - /* Energy interpolation concealment based on 3GPP */ - appliedProcessing = - CConcealment_ApplyInter (hConcealmentInfo, - pAacDecoderChannelInfo, - pSamplingRateInfo, - samplesPerFrame, - 0, /* don't use tonal improvement */ - frameOk); - break; + if (hConcealmentInfo->concealState != ConcealState_Mute) { + /* restore scale factors */ + FDKmemcpy(pSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT)); + + /* restore spectral bins */ +#if (CNCL_FRACT_BITS == DFRACT_BITS) + FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient, + 1024 * sizeof(FIXP_DBL)); +#else + for (i = 1024; i != 0; i--) { + *pSpec-- = FX_CNCL2FX_DBL(*pCncl--); + } +#endif + } else { + /* clear scale factors */ + FDKmemclear(pSpecScale, 8 * sizeof(SHORT)); + /* clear buffer */ + FDKmemclear(pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL)); } } } @@ -812,7 +786,7 @@ int hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1]; hConcealmentInfo->prevFrameOk[1] = frameOk; - return appliedProcessing; + return mute_release_active ? -1 : appliedProcessing; } /*! @@ -820,308 +794,191 @@ int In case of frame lost this function produces a noisy frame with respect to the energies values of past frame. - -\return none */ -static int - CConcealment_ApplyNoise (CConcealmentInfo *pConcealmentInfo, - CAacDecoderChannelInfo *pAacDecoderChannelInfo, - CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, - const SamplingRateInfo *pSamplingRateInfo, - const int samplesPerFrame, - const UINT flags) -{ - CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; - - FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); - SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; - CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; +static int CConcealment_ApplyNoise( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UINT flags) { + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; int appliedProcessing = 0; - FDK_ASSERT((samplesPerFrame>=480) && (samplesPerFrame<=1024)); - FDK_ASSERT((samplesPerFrame&0x1F) == 0); + FDK_ASSERT(pConcealmentInfo != NULL); + FDK_ASSERT((samplesPerFrame >= 120) && (samplesPerFrame <= 1024)); - switch (pConcealmentInfo->concealState) - { - case ConcealState_Ok: - /* Nothing to do here! */ - break; - - case ConcealState_Single: - case ConcealState_FadeOut: - { - /* restore frequency coefficients from buffer with a specific muting */ - FIXP_SGL fac; - int win, numWindows = 1; - int windowLen = samplesPerFrame; - int tFadeFrames, lastWindow = 0; - int win_idx_stride = 1; - - FDK_ASSERT(pConcealmentInfo != NULL); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames <= pConcealCommonData->numFadeOutFrames); - - /* get attenuation factor */ - tFadeFrames = pConcealmentInfo->cntFadeFrames; - fac = pConcealCommonData->fadeOutFactor[tFadeFrames]; - - /* set old window parameters */ - { - pIcsInfo->WindowShape = pConcealmentInfo->windowShape; - pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; - - if (pConcealmentInfo->windowSequence == 2) { - /* short block handling */ - numWindows = 8; - windowLen = samplesPerFrame >> 3; - lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen; - } - } - - for (win = 0; win < numWindows; win++) { - FIXP_CNCL *pCncl = pConcealmentInfo->spectralCoefficient + (lastWindow * windowLen); - FIXP_DBL *pOut = pSpectralCoefficient + (win * windowLen); - int i; - - FDK_ASSERT((lastWindow * windowLen + windowLen) <= samplesPerFrame); - - /* restore frequency coefficients from buffer with a specific attenuation */ - for (i = 0; i < windowLen; i++) { - pOut[i] = fMult(pCncl[i], fac); - } - - /* apply random change of sign for spectral coefficients */ - CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, - pOut, - windowLen ); - - /* Increment random phase index to avoid repetition artifacts. */ - pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); - - /* set old scale factors */ - pSpecScale[win*win_idx_stride] = pConcealmentInfo->specScale[win_idx_stride*lastWindow++]; - - if ( (lastWindow >= numWindows) - && (numWindows > 1) ) - { - /* end of sequence -> rewind */ - lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen; - /* update the attenuation factor to get a faster fade-out */ - tFadeFrames += 1; - if (tFadeFrames < pConcealCommonData->numFadeOutFrames) { - fac = pConcealCommonData->fadeOutFactor[tFadeFrames]; - } else { - fac = (FIXP_SGL)0; - } - } - } + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + /* Nothing to do here! */ + break; - /* store temp vars */ - pConcealmentInfo->cntFadeFrames = tFadeFrames; - appliedProcessing = 1; - } - break; + case ConcealState_Single: + case ConcealState_FadeOut: + appliedProcessing = CConcealment_ApplyFadeOut( + /*mode =*/1, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + break; - case ConcealState_Mute: - { + case ConcealState_Mute: { /* set dummy window parameters */ - pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ - pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */ - pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); - pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = + pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape + (required for F/T transform) */ + pIcsInfo->WindowSequence = + CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = + pIcsInfo->WindowSequence; /* Store for next frame + (spectrum in concealment + buffer can't be used at + all) */ /* mute spectral data */ FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + FDKmemclear(pConcealmentInfo->spectralCoefficient, + samplesPerFrame * sizeof(FIXP_DBL)); - if ( !(flags & (AC_USAC|AC_RSVD50)) - && pConcealCommonData->comfortNoiseLevel >= 0 - && pConcealCommonData->comfortNoiseLevel <= 61 /* -90dB */) - { - /* insert comfort noise using PNS */ - CConcealment_fakePnsData ( - &pAacDecoderChannelInfo->data.aac.PnsData, - pIcsInfo, - pSamplingRateInfo, - pAacDecoderChannelInfo->pDynData->aSfbScale, - pAacDecoderChannelInfo->pDynData->aScaleFactor, - pConcealCommonData->comfortNoiseLevel - ); - - CPns_Apply ( - &pAacDecoderChannelInfo->data.aac.PnsData, - pIcsInfo, - pAacDecoderChannelInfo->pSpectralCoefficient, - pAacDecoderChannelInfo->specScale, - pAacDecoderChannelInfo->pDynData->aScaleFactor, - pSamplingRateInfo, - pAacDecoderChannelInfo->granuleLength, - 0 /* always apply to first channel */ - ); - } appliedProcessing = 1; - } - break; + } break; - case ConcealState_FadeIn: - { - FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames); + case ConcealState_FadeIn: { + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ - /* attenuate signal to get a smooth fade-in */ - FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1]; - FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames]; - int i; - - for (i = samplesPerFrame; i != 0; i--) { - *pOut = fMult(*pOut, fac); - pOut--; - } appliedProcessing = 1; - } - break; + } break; - default: - /* we shouldn't come here anyway */ - FDK_ASSERT(0); - break; + default: + /* we shouldn't come here anyway */ + FDK_ASSERT(0); + break; } return appliedProcessing; } - /*! \brief Apply concealment interpolation The function swaps the data from the current and the previous frame. If an error has occured, frame interpolation is performed to restore the missing frame. In case of multiple faulty frames, fade-in and fade-out is applied. - - \return none */ -static int - CConcealment_ApplyInter ( - CConcealmentInfo *pConcealmentInfo, +static int CConcealment_ApplyInter( + CConcealmentInfo *pConcealmentInfo, CAacDecoderChannelInfo *pAacDecoderChannelInfo, - const SamplingRateInfo *pSamplingRateInfo, - const int samplesPerFrame, - const int improveTonal, - const int frameOk ) -{ - CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; - - FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); - CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; - SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const int improveTonal, const int frameOk, const int mute_release_active) { +#if defined(FDK_ASSERT_ENABLE) + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; +#endif + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; int sfbEnergyPrev[64]; - int sfbEnergyAct [64]; + int sfbEnergyAct[64]; int i, appliedProcessing = 0; /* clear/init */ FDKmemclear(sfbEnergyPrev, 64 * sizeof(int)); - FDKmemclear(sfbEnergyAct, 64 * sizeof(int)); - + FDKmemclear(sfbEnergyAct, 64 * sizeof(int)); - if (!frameOk) - { + if (!frameOk || mute_release_active) { /* Restore last frame from concealment buffer */ - pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; /* Restore spectral data */ for (i = 0; i < samplesPerFrame; i++) { - pSpectralCoefficient[i] = FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]); + pSpectralCoefficient[i] = + FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]); } /* Restore scale factors */ - FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8*sizeof(SHORT)); + FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8 * sizeof(SHORT)); } /* if previous frame was not ok */ - if (!pConcealmentInfo->prevFrameOk[1]) { - + if (!pConcealmentInfo->prevFrameOk[1] || mute_release_active) { /* if current frame (f_n) is ok and the last but one frame (f_(n-2)) was ok, too, then interpolate both frames in order to generate the current output frame (f_(n-1)). Otherwise, use the last stored frame (f_(n-2) or f_(n-3) or ...). */ - if (frameOk && pConcealmentInfo->prevFrameOk[0]) - { + if (frameOk && pConcealmentInfo->prevFrameOk[0] && !mute_release_active) { appliedProcessing = 1; - - /* Interpolate both frames in order to generate the current output frame (f_(n-1)). */ - if (pIcsInfo->WindowSequence == EightShortSequence) { - /* f_(n-2) == EightShortSequence */ + /* Interpolate both frames in order to generate the current output frame + * (f_(n-1)). */ + if (pIcsInfo->WindowSequence == BLOCK_SHORT) { + /* f_(n-2) == BLOCK_SHORT */ /* short--??????--short, short--??????--long interpolation */ /* short--short---short, short---long---long interpolation */ int wnd; - if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */ + if (pConcealmentInfo->windowSequence == + BLOCK_SHORT) { /* f_n == BLOCK_SHORT */ /* short--short---short interpolation */ - int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short; - const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; - pIcsInfo->WindowShape = 1; - pIcsInfo->WindowSequence = EightShortSequence; + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1; + pIcsInfo->WindowSequence = BLOCK_SHORT; - for (wnd = 0; wnd < 8; wnd++) - { + for (wnd = 0; wnd < 8; wnd++) { CConcealment_CalcBandEnergy( - &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-2) */ - pSamplingRateInfo, - EightShortSequence, - CConcealment_NoExpand, - sfbEnergyPrev); + &pSpectralCoefficient[wnd * + (samplesPerFrame / 8)], /* spec_(n-2) */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand, + sfbEnergyPrev); CConcealment_CalcBandEnergy( - &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_n */ - pSamplingRateInfo, - EightShortSequence, - CConcealment_NoExpand, - sfbEnergyAct); + &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame / + 8)], /* spec_n */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand, + sfbEnergyAct); CConcealment_InterpolateBuffer( - &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-1) */ - &pSpecScale[wnd], - &pConcealmentInfo->specScale[wnd], - &pSpecScale[wnd], - sfbEnergyPrev, - sfbEnergyAct, - scaleFactorBandsTotal, - pSfbOffset); - + &pSpectralCoefficient[wnd * + (samplesPerFrame / 8)], /* spec_(n-1) */ + &pSpecScale[wnd], &pConcealmentInfo->specScale[wnd], + &pSpecScale[wnd], sfbEnergyPrev, sfbEnergyAct, + scaleFactorBandsTotal, pSfbOffset); } - } else { /* f_n != EightShortSequence */ + } else { /* f_n != BLOCK_SHORT */ /* short---long---long interpolation */ - int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; - const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; SHORT specScaleOut; - CConcealment_CalcBandEnergy(&pSpectralCoefficient[samplesPerFrame - (samplesPerFrame / 8)], /* [wnd] spec_(n-2) */ - pSamplingRateInfo, - EightShortSequence, - CConcealment_Expand, - sfbEnergyAct); + CConcealment_CalcBandEnergy( + &pSpectralCoefficient[samplesPerFrame - + (samplesPerFrame / + 8)], /* [wnd] spec_(n-2) */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, + sfbEnergyAct); - CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */ - pSamplingRateInfo, - OnlyLongSequence, - CConcealment_NoExpand, - sfbEnergyPrev); + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand, + sfbEnergyPrev); pIcsInfo->WindowShape = 0; - pIcsInfo->WindowSequence = LongStopSequence; + pIcsInfo->WindowSequence = BLOCK_STOP; - for (i = 0; i < samplesPerFrame ; i++) { - pSpectralCoefficient[i] = pConcealmentInfo->spectralCoefficient[i]; /* spec_n */ + for (i = 0; i < samplesPerFrame; i++) { + pSpectralCoefficient[i] = + pConcealmentInfo->spectralCoefficient[i]; /* spec_n */ } for (i = 0; i < 8; i++) { /* search for max(specScale) */ @@ -1131,14 +988,9 @@ static int } CConcealment_InterpolateBuffer( - pSpectralCoefficient, /* spec_(n-1) */ - &pConcealmentInfo->specScale[0], - &pSpecScale[0], - &specScaleOut, - sfbEnergyPrev, - sfbEnergyAct, - scaleFactorBandsTotal, - pSfbOffset); + pSpectralCoefficient, /* spec_(n-1) */ + &pConcealmentInfo->specScale[0], &pSpecScale[0], &specScaleOut, + sfbEnergyPrev, sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset); pSpecScale[0] = specScaleOut; } @@ -1146,21 +998,21 @@ static int /* long--??????--short, long--??????--long interpolation */ /* long---long---short, long---long---long interpolation */ - int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; - const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; - SHORT specScaleAct = pConcealmentInfo->specScale[0]; + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + SHORT specScaleAct = pConcealmentInfo->specScale[0]; - CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */ - pSamplingRateInfo, - OnlyLongSequence, - CConcealment_NoExpand, - sfbEnergyPrev); + CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */ + pSamplingRateInfo, BLOCK_LONG, + CConcealment_NoExpand, sfbEnergyPrev); - if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */ + if (pConcealmentInfo->windowSequence == + BLOCK_SHORT) { /* f_n == BLOCK_SHORT */ /* long---long---short interpolation */ - pIcsInfo->WindowShape = 1; - pIcsInfo->WindowSequence = LongStartSequence; + pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1; + pIcsInfo->WindowSequence = BLOCK_START; for (i = 1; i < 8; i++) { /* search for max(specScale) */ if (pConcealmentInfo->specScale[i] > specScaleAct) { @@ -1169,310 +1021,277 @@ static int } /* Expand first short spectrum */ - CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */ - pSamplingRateInfo, - EightShortSequence, - CConcealment_Expand, /* !!! */ - sfbEnergyAct); + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, /* !!! */ + sfbEnergyAct); } else { /* long---long---long interpolation */ pIcsInfo->WindowShape = 0; - pIcsInfo->WindowSequence = OnlyLongSequence; + pIcsInfo->WindowSequence = BLOCK_LONG; - CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */ - pSamplingRateInfo, - OnlyLongSequence, - CConcealment_NoExpand, - sfbEnergyAct); + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand, + sfbEnergyAct); } - CConcealment_InterpolateBuffer( - pSpectralCoefficient, /* spec_(n-1) */ - &pSpecScale[0], - &specScaleAct, - &pSpecScale[0], - sfbEnergyPrev, - sfbEnergyAct, - scaleFactorBandsTotal, - pSfbOffset); - + CConcealment_InterpolateBuffer( + pSpectralCoefficient, /* spec_(n-1) */ + &pSpecScale[0], &specScaleAct, &pSpecScale[0], sfbEnergyPrev, + sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset); } } - /* Noise substitution of sign of the output spectral coefficients */ - CConcealment_ApplyRandomSign (pConcealmentInfo->iRandomPhase, - pSpectralCoefficient, - samplesPerFrame); - /* Increment random phase index to avoid repetition artifacts. */ - pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + /* Noise substitution of sign of the output spectral coefficients */ + CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, + pSpectralCoefficient, samplesPerFrame); + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = + (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); } /* scale spectrum according to concealment state */ - switch (pConcealmentInfo->concealState) - { - case ConcealState_Single: - appliedProcessing = 1; - break; + switch (pConcealmentInfo->concealState) { + case ConcealState_Single: + appliedProcessing = 1; + break; - case ConcealState_FadeOut: - { + case ConcealState_FadeOut: { FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeOutFrames); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + pConcealCommonData->numFadeOutFrames); - /* restore frequency coefficients from buffer with a specific muting */ - FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1]; - FIXP_SGL fac = pConcealCommonData->fadeOutFactor[pConcealmentInfo->cntFadeFrames]; + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ - for (i = samplesPerFrame; i != 0; i--) { - *pOut = fMult(*pOut, fac); - pOut--; - } appliedProcessing = 1; - } - break; + } break; - case ConcealState_FadeIn: - { + case ConcealState_FadeIn: { FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); - FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + pConcealCommonData->numFadeInFrames); - /* attenuate signal to get a smooth fade-in */ - FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1]; - FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames]; + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ - for (i = samplesPerFrame; i != 0; i--) { - *pOut = fMult(*pOut, fac); - pOut--; - } appliedProcessing = 1; - } - break; - - case ConcealState_Mute: - { - int fac = pConcealCommonData->comfortNoiseLevel; + } break; + case ConcealState_Mute: { /* set dummy window parameters */ - pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ - pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */ - pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); - pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = + pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape + (required for F/T transform) */ + pIcsInfo->WindowSequence = + CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = + pIcsInfo->WindowSequence; /* Store for next frame + (spectrum in concealment + buffer can't be used at + all) */ /* mute spectral data */ FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); - if (fac >= 0 && fac <= 61) { - /* insert comfort noise using PNS */ - CConcealment_fakePnsData ( - &pAacDecoderChannelInfo->data.aac.PnsData, - pIcsInfo, - pSamplingRateInfo, - pAacDecoderChannelInfo->specScale, - pAacDecoderChannelInfo->pDynData->aScaleFactor, - fac - ); - - CPns_Apply ( - &pAacDecoderChannelInfo->data.aac.PnsData, - pIcsInfo, - pAacDecoderChannelInfo->pSpectralCoefficient, - pAacDecoderChannelInfo->specScale, - pAacDecoderChannelInfo->pDynData->aScaleFactor, - pSamplingRateInfo, - pAacDecoderChannelInfo->granuleLength, - 0 /* always apply to first channel */ - ); - } appliedProcessing = 1; - } - break; + } break; - default: - /* nothing to do here */ - break; + default: + /* nothing to do here */ + break; } return appliedProcessing; } - /*! \brief Calculate the spectral energy The function calculates band-wise the spectral energy. This is used for frame interpolation. - - \return none */ -static void - CConcealment_CalcBandEnergy ( - FIXP_DBL *spectrum, - const SamplingRateInfo *pSamplingRateInfo, - const int blockType, - CConcealmentExpandType expandType, - int *sfbEnergy ) -{ +static void CConcealment_CalcBandEnergy( + FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo, + const int blockType, CConcealmentExpandType expandType, int *sfbEnergy) { const SHORT *pSfbOffset; int line, sfb, scaleFactorBandsTotal = 0; - - /* In the following calculations, enAccu is initialized with LSB-value in order to avoid zero energy-level */ - - line = 0; - switch(blockType) { + /* In the following calculations, enAccu is initialized with LSB-value in + * order to avoid zero energy-level */ - case OnlyLongSequence: - case LongStartSequence: - case LongStopSequence: - - if (expandType == CConcealment_NoExpand) { - /* standard long calculation */ - scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; - pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + line = 0; - for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { - FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; - int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; - /* scaling depends on sfb width. */ - for ( ; line < pSfbOffset[sfb+1]; line++) { - enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + switch (blockType) { + case BLOCK_LONG: + case BLOCK_START: + case BLOCK_STOP: + + if (expandType == CConcealment_NoExpand) { + /* standard long calculation */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; } - *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; - } - } - else { - /* compress long to short */ - scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short; - pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; - - for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { - FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; - int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; - /* scaling depends on sfb width. */ - for (; line < pSfbOffset[sfb+1] << 3; line++) { - enAccu += (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3; + } else { + /* compress long to short */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1] << 3; line++) { + enAccu += + (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; } - *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; } - } - break; - - case EightShortSequence: - - if (expandType == CConcealment_NoExpand) { - /* standard short calculation */ - scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short; - pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + break; - for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { - FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; - int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; - /* scaling depends on sfb width. */ - for ( ; line < pSfbOffset[sfb+1]; line++) { - enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + case BLOCK_SHORT: + + if (expandType == CConcealment_NoExpand) { + /* standard short calculation */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; } - *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; - } - } - else { - /* expand short to long spectrum */ - scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; - pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; - - for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { - FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; - int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; - /* scaling depends on sfb width. */ - for ( ; line < pSfbOffset[sfb+1]; line++) { - enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale; + } else { + /* expand short to long spectrum */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; } - *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; } - } - break; + break; } } - /*! \brief Interpolate buffer The function creates the interpolated spectral data according to the energy of the last good frame and the current (good) frame. - - \return none */ -static void - CConcealment_InterpolateBuffer ( - FIXP_DBL *spectrum, - SHORT *pSpecScalePrv, - SHORT *pSpecScaleAct, - SHORT *pSpecScaleOut, - int *enPrv, - int *enAct, - int sfbCnt, - const SHORT *pSfbOffset ) -{ - int sfb, line = 0; - int fac_shift; - int fac_mod; +static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum, + SHORT *pSpecScalePrv, + SHORT *pSpecScaleAct, + SHORT *pSpecScaleOut, int *enPrv, + int *enAct, int sfbCnt, + const SHORT *pSfbOffset) { + int sfb, line = 0; + int fac_shift; + int fac_mod; FIXP_DBL accu; for (sfb = 0; sfb < sfbCnt; sfb++) { - - fac_shift = enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1); - fac_mod = fac_shift & 3; + fac_shift = + enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1); + fac_mod = fac_shift & 3; fac_shift = (fac_shift >> 2) + 1; fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct); - for (; line < pSfbOffset[sfb+1]; line++) { - accu = fMult(*(spectrum+line), facMod4Table[fac_mod]); + for (; line < pSfbOffset[sfb + 1]; line++) { + accu = fMult(*(spectrum + line), facMod4Table[fac_mod]); if (fac_shift < 0) { accu >>= -fac_shift; } else { accu <<= fac_shift; } - *(spectrum+line) = accu; + *(spectrum + line) = accu; } } *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct); } +/*! + \brief Find next fading frame in case of changing fading direction + \param pConcealCommonData Pointer to the concealment common data structure. + \param actFadeIndex Last index used for fading + \param direction Direction of change: 0 : change from FADE-OUT to FADE-IN, 1 + : change from FADE-IN to FADE-OUT + This function determines the next fading index to be used for the fading + direction to be changed to. +*/ -static INT findEquiFadeFrame ( - CConcealParams *pConcealCommonData, - INT actFadeIndex, - int direction ) -{ +static INT findEquiFadeFrame(CConcealParams *pConcealCommonData, + INT actFadeIndex, int direction) { FIXP_SGL *pFactor; - FIXP_SGL referenceVal; - FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL; + FIXP_SGL referenceVal; + FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL; - INT numFrames = 0; - INT nextFadeIndex = 0; + INT nextFadeIndex = 0; - int i; + int i; /* init depending on direction */ - if (direction == 0) { /* FADE-OUT => FADE-IN */ - numFrames = pConcealCommonData->numFadeInFrames; - referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1; + if (direction == 0) { /* FADE-OUT => FADE-IN */ + if (actFadeIndex < 0) { + referenceVal = (FIXP_SGL)MAXVAL_SGL; + } else { + referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1; + } pFactor = pConcealCommonData->fadeInFactor; - } - else { /* FADE-IN => FADE-OUT */ - numFrames = pConcealCommonData->numFadeOutFrames; - referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1; + } else { /* FADE-IN => FADE-OUT */ + if (actFadeIndex < 0) { + referenceVal = (FIXP_SGL)MAXVAL_SGL; + } else { + referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1; + } pFactor = pConcealCommonData->fadeOutFactor; } /* search for minimum difference */ - for (i = 0; i < numFrames; i++) { - FIXP_SGL diff = fixp_abs((pFactor[i]>>1) - referenceVal); + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + FIXP_SGL diff = fixp_abs((pFactor[i] >> 1) - referenceVal); if (diff < minDiff) { minDiff = diff; nextFadeIndex = i; @@ -1480,13 +1299,17 @@ static INT findEquiFadeFrame ( } /* check and adjust depending on direction */ - if (direction == 0) { /* FADE-OUT => FADE-IN */ - if (((pFactor[nextFadeIndex]>>1) <= referenceVal) && (nextFadeIndex > 0)) { + if (direction == 0) { /* FADE-OUT => FADE-IN */ + if (nextFadeIndex > pConcealCommonData->numFadeInFrames) { + nextFadeIndex = fMax(pConcealCommonData->numFadeInFrames - 1, 0); + } + if (((pFactor[nextFadeIndex] >> 1) <= referenceVal) && + (nextFadeIndex > 0)) { nextFadeIndex -= 1; } - } - else { /* FADE-IN => FADE-OUT */ - if (((pFactor[nextFadeIndex]>>1) >= referenceVal) && (nextFadeIndex < numFrames-1)) { + } else { /* FADE-IN => FADE-OUT */ + if (((pFactor[nextFadeIndex] >> 1) >= referenceVal) && + (nextFadeIndex < CONCEAL_MAX_NUM_FADE_FACTORS - 1)) { nextFadeIndex += 1; } } @@ -1494,268 +1317,304 @@ static INT findEquiFadeFrame ( return (nextFadeIndex); } - /*! \brief Update the concealment state The function updates the state of the concealment state-machine. The states are: mute, fade-in, fade-out, interpolate and frame-ok. - - \return none */ -static void - CConcealment_UpdateState ( - CConcealmentInfo *pConcealmentInfo, - int frameOk ) -{ +static void CConcealment_UpdateState( + CConcealmentInfo *pConcealmentInfo, int frameOk, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; - switch (pConcealCommonData->method) - { - case ConcealMethodNoise: - { + switch (pConcealCommonData->method) { + case ConcealMethodNoise: { if (pConcealmentInfo->concealState != ConcealState_Ok) { /* count the valid frames during concealment process */ if (frameOk) { pConcealmentInfo->cntValidFrames += 1; } else { - pConcealmentInfo->cntValidFrames = 0; + pConcealmentInfo->cntValidFrames = 0; } } /* -- STATE MACHINE for Noise Substitution -- */ - switch (pConcealmentInfo->concealState) - { - case ConcealState_Ok: - if (!frameOk) { - if (pConcealCommonData->numFadeOutFrames > 0) { - /* change to state SINGLE-FRAME-LOSS */ - pConcealmentInfo->concealState = ConcealState_Single; - } else { - /* change to state MUTE */ - pConcealmentInfo->concealState = ConcealState_Mute; + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + if (!frameOk) { + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state SINGLE-FRAME-LOSS */ + pConcealmentInfo->concealState = ConcealState_Single; + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } } - pConcealmentInfo->cntFadeFrames = 0; - pConcealmentInfo->cntValidFrames = 0; - } - break; + break; - case ConcealState_Single: /* Just a pre-stage before fade-out begins. Stay here only one frame! */ - pConcealmentInfo->cntFadeFrames += 1; - if (frameOk) { - if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { - /* change to state FADE-IN */ - pConcealmentInfo->concealState = ConcealState_FadeIn; - pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, - pConcealmentInfo->cntFadeFrames-1, - 0 /* FadeOut -> FadeIn */); - } else { + case ConcealState_Single: /* Just a pre-stage before fade-out begins. + Stay here only one frame! */ + if (frameOk) { /* change to state OK */ pConcealmentInfo->concealState = ConcealState_Ok; - } - } else { - if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) { - /* change to state MUTE */ - pConcealmentInfo->concealState = ConcealState_Mute; } else { - /* change to state FADE-OUT */ - pConcealmentInfo->concealState = ConcealState_FadeOut; + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } else { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } } - } - break; - - case ConcealState_FadeOut: - pConcealmentInfo->cntFadeFrames += 1; /* used to address the fade-out factors */ - if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { - if (pConcealCommonData->numFadeInFrames > 0) { - /* change to state FADE-IN */ - pConcealmentInfo->concealState = ConcealState_FadeIn; - pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, - pConcealmentInfo->cntFadeFrames-1, - 0 /* FadeOut -> FadeIn */); + break; + + case ConcealState_FadeOut: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } } else { - /* change to state OK */ - pConcealmentInfo->concealState = ConcealState_Ok; - } - } else { - if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) { - /* change to state MUTE */ - pConcealmentInfo->concealState = ConcealState_Mute; + if (frameOk) { + /* we have good frame information but stay fully in concealment - + * reset winGrpOffset/attGrpOffset */ + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + } + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } else /* Stay in FADE-OUT */ + { + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } } - } - break; - - case ConcealState_Mute: - if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { - if (pConcealCommonData->numFadeInFrames > 0) { - /* change to state FADE-IN */ - pConcealmentInfo->concealState = ConcealState_FadeIn; - pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1; + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = + pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } } else { - /* change to state OK */ - pConcealmentInfo->concealState = ConcealState_Ok; - } - } - break; - - case ConcealState_FadeIn: - pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */ - if (frameOk) { - if (pConcealmentInfo->cntFadeFrames < 0) { - /* change to state OK */ - pConcealmentInfo->concealState = ConcealState_Ok; + if (frameOk) { + /* we have good frame information but stay fully in concealment - + * reset winGrpOffset/attGrpOffset */ + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + } } - } else { - if (pConcealCommonData->numFadeOutFrames > 0) { - /* change to state FADE-OUT */ - pConcealmentInfo->concealState = ConcealState_FadeOut; - pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, - pConcealmentInfo->cntFadeFrames+1, - 1 /* FadeIn -> FadeOut */); + break; + + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= 1; + if (frameOk) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } } else { - /* change to state MUTE */ - pConcealmentInfo->concealState = ConcealState_Mute; + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1, + 1 /* FadeIn -> FadeOut */); + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + + pConcealmentInfo + ->cntFadeFrames--; /* decrease because + CConcealment_ApplyFadeOut() will + increase, accordingly */ + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } } - } - break; + break; - default: - FDK_ASSERT(0); - break; + default: + FDK_ASSERT(0); + break; } - } - break; + } break; - case ConcealMethodInter: - case ConcealMethodTonal: - { + case ConcealMethodInter: + case ConcealMethodTonal: { if (pConcealmentInfo->concealState != ConcealState_Ok) { /* count the valid frames during concealment process */ - if ( pConcealmentInfo->prevFrameOk[1] || - (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk) ) { - /* The frame is OK even if it can be estimated by the energy interpolation algorithm */ + if (pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && + !pConcealmentInfo->prevFrameOk[1] && frameOk)) { + /* The frame is OK even if it can be estimated by the energy + * interpolation algorithm */ pConcealmentInfo->cntValidFrames += 1; } else { - pConcealmentInfo->cntValidFrames = 0; + pConcealmentInfo->cntValidFrames = 0; } } /* -- STATE MACHINE for energy interpolation -- */ - switch (pConcealmentInfo->concealState) - { - case ConcealState_Ok: - if (!(pConcealmentInfo->prevFrameOk[1] || - (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk))) { - if (pConcealCommonData->numFadeOutFrames > 0) { - /* Fade out only if the energy interpolation algorithm can not be applied! */ - pConcealmentInfo->concealState = ConcealState_FadeOut; - } else { - /* change to state MUTE */ - pConcealmentInfo->concealState = ConcealState_Mute; + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + if (!(pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && + !pConcealmentInfo->prevFrameOk[1] && frameOk))) { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* Fade out only if the energy interpolation algorithm can not be + * applied! */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; } - pConcealmentInfo->cntFadeFrames = 0; - pConcealmentInfo->cntValidFrames = 0; - } - break; - - case ConcealState_Single: - pConcealmentInfo->concealState = ConcealState_Ok; - break; - - case ConcealState_FadeOut: - pConcealmentInfo->cntFadeFrames += 1; - - if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { - if (pConcealCommonData->numFadeInFrames > 0) { - /* change to state FADE-IN */ - pConcealmentInfo->concealState = ConcealState_FadeIn; - pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, - pConcealmentInfo->cntFadeFrames-1, - 0 /* FadeOut -> FadeIn */); + break; + + case ConcealState_Single: + pConcealmentInfo->concealState = ConcealState_Ok; + break; + + case ConcealState_FadeOut: + pConcealmentInfo->cntFadeFrames += 1; + + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames - 1, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } } else { - /* change to state OK */ - pConcealmentInfo->concealState = ConcealState_Ok; - } - } else { - if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) { - /* change to state MUTE */ - pConcealmentInfo->concealState = ConcealState_Mute; + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } } - } - break; - - case ConcealState_Mute: - if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { - if (pConcealCommonData->numFadeInFrames > 0) { - /* change to state FADE-IN */ - pConcealmentInfo->concealState = ConcealState_FadeIn; - pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1; - } else { - /* change to state OK */ - pConcealmentInfo->concealState = ConcealState_Ok; + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = + pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } } - } - break; + break; - case ConcealState_FadeIn: - pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */ + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= + 1; /* used to address the fade-in factors */ - if (frameOk || pConcealmentInfo->prevFrameOk[1]) { - if (pConcealmentInfo->cntFadeFrames < 0) { - /* change to state OK */ - pConcealmentInfo->concealState = ConcealState_Ok; - } - } else { - if (pConcealCommonData->numFadeOutFrames > 0) { - /* change to state FADE-OUT */ - pConcealmentInfo->concealState = ConcealState_FadeOut; - pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, - pConcealmentInfo->cntFadeFrames+1, - 1 /* FadeIn -> FadeOut */); + if (frameOk || pConcealmentInfo->prevFrameOk[1]) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } } else { - /* change to state MUTE */ - pConcealmentInfo->concealState = ConcealState_Mute; + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1, + 1 /* FadeIn -> FadeOut */); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } } - } - break; + break; } /* End switch(pConcealmentInfo->concealState) */ - } - break; + } break; - default: - /* Don't need a state machine for other concealment methods. */ - break; + default: + /* Don't need a state machine for other concealment methods. */ + break; } - } - /*! \brief Randomizes the sign of the spectral data The function toggles the sign of the spectral data randomly. This is useful to ensure the quality of the concealed frames. - -\return none */ -static -void CConcealment_ApplyRandomSign (int randomPhase, - FIXP_DBL *spec, - int samplesPerFrame - ) -{ +static void CConcealment_ApplyRandomSign(int randomPhase, FIXP_DBL *spec, + int samplesPerFrame) { int i; - USHORT packedSign=0; + USHORT packedSign = 0; - /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit */ + /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit + */ /* read current packed sign word */ - packedSign = randomSign[randomPhase>>4]; - packedSign >>= (randomPhase&0xf); + packedSign = AacDec_randomSign[randomPhase >> 4]; + packedSign >>= (randomPhase & 0xf); - for (i = 0; i < samplesPerFrame ; i++) { + for (i = 0; i < samplesPerFrame; i++) { if ((randomPhase & 0xf) == 0) { - packedSign = randomSign[randomPhase>>4]; + packedSign = AacDec_randomSign[randomPhase >> 4]; } if (packedSign & 0x1) { @@ -1767,53 +1626,6 @@ void CConcealment_ApplyRandomSign (int randomPhase, } } - -/*! - \brief Get fadeing factor for current concealment state. - - The function returns the factor used for fading that belongs to the current internal state. - - \return Fade factor - */ -FIXP_DBL - CConcealment_GetFadeFactor ( - CConcealmentInfo *hConcealmentInfo, - const int fPreviousFactor - ) -{ - FIXP_DBL fac = (FIXP_DBL)0; - - CConcealParams *pConcealCommonData = hConcealmentInfo->pConcealParams; - - if (hConcealmentInfo->pConcealParams->method > ConcealMethodMute) { - switch (hConcealmentInfo->concealState) { - default: - case ConcealState_Mute: - /* Nothing to do here */ - break; - case ConcealState_Ok: - fac = (FIXP_DBL)MAXVAL_DBL; - break; - case ConcealState_Single: - case ConcealState_FadeOut: - { - int idx = hConcealmentInfo->cntFadeFrames - ((fPreviousFactor != 0) ? 1 : 0); - fac = (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(pConcealCommonData->fadeOutFactor[idx]); - } - break; - case ConcealState_FadeIn: - { - int idx = hConcealmentInfo->cntFadeFrames + ((fPreviousFactor != 0) ? 1 : 0); - fac = (idx >= hConcealmentInfo->pConcealParams->numFadeInFrames) ? (FIXP_DBL)0 : FX_SGL2FX_DBL(pConcealCommonData->fadeInFactor[idx]); - } - break; - } - } - - return (fac); -} - - /*! \brief Get fadeing factor for current concealment state. @@ -1823,12 +1635,8 @@ FIXP_DBL \return Frame OK flag of previous frame. */ -int - CConcealment_GetLastFrameOk ( - CConcealmentInfo *hConcealmentInfo, - const int fBeforeApply - ) -{ +int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo, + const int fBeforeApply) { int prevFrameOk = 1; if (hConcealmentInfo != NULL) { @@ -1839,28 +1647,448 @@ int } /*! - \brief Get the number of delay frames introduced by concealment technique. + \brief Get the number of delay frames introduced by concealment technique. \return Number of delay frames. */ -UINT - CConcealment_GetDelay ( - CConcealParams *pConcealCommonData - ) -{ +UINT CConcealment_GetDelay(CConcealParams *pConcealCommonData) { UINT frameDelay = 0; if (pConcealCommonData != NULL) { switch (pConcealCommonData->method) { - case ConcealMethodTonal: - case ConcealMethodInter: - frameDelay = 1; + case ConcealMethodTonal: + case ConcealMethodInter: + frameDelay = 1; + break; + default: + break; + } + } + + return frameDelay; +} + +static int CConcealment_ApplyFadeOut( + int mode, CConcealmentInfo *pConcealmentInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + /* mode 1 = apply RandomSign and mute spectral coefficients if necessary, * + * mode 0 = Update cntFadeFrames */ + + /* restore frequency coefficients from buffer with a specific muting */ + int srcWin, dstWin, numWindows = 1; + int windowLen = samplesPerFrame; + int srcGrpStart = 0; + int winIdxStride = 1; + int numWinGrpPerFac, attIdx, attIdxStride; + int i; + int appliedProcessing = 0; + + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + /* set old window parameters */ + if (pConcealmentInfo->lastRenderMode == AACDEC_RENDER_LPD) { + switch (pAacDecoderStaticChannelInfo->last_lpd_mode) { + case 1: + numWindows = 4; + srcGrpStart = 3; + windowLen = samplesPerFrame >> 2; + break; + case 2: + numWindows = 2; + srcGrpStart = 1; + windowLen = samplesPerFrame >> 1; + winIdxStride = 2; + break; + case 3: + numWindows = 1; + srcGrpStart = 0; + windowLen = samplesPerFrame; + winIdxStride = 4; + break; + } + pConcealmentInfo->lastWinGrpLen = 1; + } else { + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; + + if (pConcealmentInfo->windowSequence == BLOCK_SHORT) { + /* short block handling */ + numWindows = 8; + windowLen = samplesPerFrame >> 3; + srcGrpStart = numWindows - pConcealmentInfo->lastWinGrpLen; + } + } + + attIdxStride = + fMax(1, (int)(numWindows / (pConcealmentInfo->lastWinGrpLen + 1))); + + /* load last state */ + attIdx = pConcealmentInfo->cntFadeFrames; + numWinGrpPerFac = pConcealmentInfo->attGrpOffset[mode]; + srcWin = srcGrpStart + pConcealmentInfo->winGrpOffset[mode]; + + FDK_ASSERT((srcGrpStart * windowLen + windowLen) <= samplesPerFrame); + FDK_ASSERT((srcWin * windowLen + windowLen) <= 1024); + + for (dstWin = 0; dstWin < numWindows; dstWin += 1) { + FIXP_CNCL *pCncl = + pConcealmentInfo->spectralCoefficient + (srcWin * windowLen); + FIXP_DBL *pOut = pSpectralCoefficient + (dstWin * windowLen); + + if (mode == 1) { + /* mute if attIdx gets large enaugh */ + if (attIdx > pConcealmentInfo->pConcealParams->numFadeOutFrames) { + FDKmemclear(pCncl, sizeof(FIXP_DBL) * windowLen); + } + + /* restore frequency coefficients from buffer - attenuation is done later + */ + for (i = 0; i < windowLen; i++) { + pOut[i] = pCncl[i]; + } + + /* apply random change of sign for spectral coefficients */ + CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, pOut, + windowLen); + + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = + (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + + /* set old scale factors */ + pSpecScale[dstWin * winIdxStride] = + pConcealmentInfo->specScale[srcWin * winIdxStride]; + } + + srcWin += 1; + + if (srcWin >= numWindows) { + /* end of sequence -> rewind to first window of group */ + srcWin = srcGrpStart; + numWinGrpPerFac += 1; + if (numWinGrpPerFac >= attIdxStride) { + numWinGrpPerFac = 0; + attIdx += 1; + } + } + } + + /* store current state */ + + pConcealmentInfo->winGrpOffset[mode] = srcWin - srcGrpStart; + FDK_ASSERT((pConcealmentInfo->winGrpOffset[mode] >= 0) && + (pConcealmentInfo->winGrpOffset[mode] < 8)); + pConcealmentInfo->attGrpOffset[mode] = numWinGrpPerFac; + FDK_ASSERT((pConcealmentInfo->attGrpOffset[mode] >= 0) && + (pConcealmentInfo->attGrpOffset[mode] < attIdxStride)); + + if (mode == 0) { + pConcealmentInfo->cntFadeFrames = attIdx; + } + + appliedProcessing = 1; + + return appliedProcessing; +} + +/*! + \brief Do Time domain fading (TDFading) in concealment case + + In case of concealment, this function takes care of the fading, after time +domain signal has been rendered by the respective signal rendering functions. + The fading out in case of ACELP decoding is not done by this function but by +the ACELP decoder for the first concealed frame if CONCEAL_CORE_IGNORANT_FADE is +not set. + + TimeDomain fading never creates jumps in energy / discontinuities, it always +does a continuous fading. To achieve this, fading is always done from a starting +point to a target point, while the starting point is always determined to be the +last target point. By varying the target point of a fading, the fading slope can +be controlled. + + This principle is applied to the fading within a frame and the fading from +frame to frame. + + One frame is divided into 8 subframes to obtain 8 parts of fading slopes +within a frame, each maybe with its own gradient. + + Workflow: + 1.) Determine Fading behavior and end-of-frame target fading level, based on +concealmentState (determined by CConcealment_UpdateState()) and the core mode. + - By _DEFAULT_, + The target fading level is determined by fadeOutFactor[cntFadeFrames] +in case of fadeOut, or fadeInFactor[cntFadeFrames] in case of fadeIn. + --> fading type is FADE_TIMEDOMAIN in this case. Target fading level +is determined by fading index cntFadeFrames. + + - If concealmentState is signalling a _MUTED SIGNAL_, + TDFading decays to 0 within 1/8th of a frame if numFadeOutFrames == 0. + --> fading type is FADE_TIMEDOMAIN_TOSPECTRALMUTE in this case. + + - If concealmentState is signalling the _END OF MUTING_, + TDFading fades to target fading level within 1/8th of a frame if +numFadeInFrames == 0. + --> fading type is FADE_TIMEDOMAIN_FROMSPECTRALMUTE in this case. +Target fading level is determined by fading index cntFadeFrames. + +#ifndef CONCEAL_CORE_IGNORANT_FADE + - In case of an _ACELP FADEOUT_, + TDFading leaves fading control to ACELP decoder for 1/2 frame. + --> fading type is FADE_ACELPDOMAIN in this case. +#endif + + 2.) Render fading levels within current frame and do the final fading: + Map Fading slopes to fading levels and apply to time domain signal. + + +*/ + +INT CConcealment_TDFading( + int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, + FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1) { + /* + Do the fading in Time domain based on concealment states and core mode + */ + FIXP_DBL fadeStop, attMute = (FIXP_DBL)0; + int idx = 0, ii; + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo = + *ppAacDecoderStaticChannelInfo; + CConcealmentInfo *pConcealmentInfo = + &pAacDecoderStaticChannelInfo->concealmentInfo; + CConcealParams *pConcealParams = pConcealmentInfo->pConcealParams; + const CConcealmentState concealState = pConcealmentInfo->concealState; + TDfadingType fadingType; + FIXP_DBL fadingStations[9] = {0}; + int fadingSteps[8] = {0}; + const FIXP_DBL fadeStart = + pConcealmentInfo + ->fade_old; /* start fading at last end-of-frame attenuation */ + FIXP_SGL *fadeFactor = pConcealParams->fadeOutFactor; + const INT cntFadeFrames = pConcealmentInfo->cntFadeFrames; + int TDFadeOutStopBeforeMute = 1; + int TDFadeInStopBeforeFullLevel = 1; + + /* + determine Fading behaviour (end-of-frame attenuation and fading type) (1.) + */ + + switch (concealState) { + case ConcealState_Single: + case ConcealState_Mute: + case ConcealState_FadeOut: + idx = (pConcealParams->method == ConcealMethodNoise) ? cntFadeFrames - 1 + : cntFadeFrames; + fadingType = FADE_TIMEDOMAIN; + + if (concealState == ConcealState_Mute || + (cntFadeFrames + TDFadeOutStopBeforeMute) > + pConcealmentInfo->pConcealParams->numFadeOutFrames) { + fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE; + } + + break; + case ConcealState_FadeIn: + idx = cntFadeFrames; + idx -= TDFadeInStopBeforeFullLevel; + case ConcealState_Ok: + fadeFactor = pConcealParams->fadeInFactor; + idx = (concealState == ConcealState_Ok) ? -1 : idx; + fadingType = (pConcealmentInfo->concealState_old == ConcealState_Mute) + ? FADE_TIMEDOMAIN_FROMSPECTRALMUTE + : FADE_TIMEDOMAIN; break; default: + FDK_ASSERT(0); + fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE; break; + } + + /* determine Target end-of-frame fading level and fading slope */ + switch (fadingType) { + case FADE_TIMEDOMAIN_FROMSPECTRALMUTE: + fadeStop = + (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]); + if (pConcealmentInfo->pConcealParams->numFadeInFrames == 0) { + /* do step as fast as possible */ + fadingSteps[0] = 1; + break; + } + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + case FADE_TIMEDOMAIN: + fadeStop = + (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]); + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + case FADE_TIMEDOMAIN_TOSPECTRALMUTE: + fadeStop = attMute; + if (pConcealmentInfo->pConcealParams->numFadeOutFrames == 0) { + /* do step as fast as possible */ + fadingSteps[0] = 1; + break; + } + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + } + + /* + Render fading levels within current frame and do the final fading (2.) + */ + + len >>= 3; + CConcealment_TDFadeFillFadingStations(fadingStations, fadingSteps, fadeStop, + fadeStart, fadingType); + + if ((fadingStations[8] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[7] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[6] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[5] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[4] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[3] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[2] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[1] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[0] != + (FIXP_DBL)MAXVAL_DBL)) /* if there's something to fade */ + { + int start = 0; + for (ii = 0; ii < 8; ii++) { + CConcealment_TDFadePcmAtt(start, len, fadingStations[ii], + fadingStations[ii + 1], pcmdata); + start += len; } } + CConcealment_TDNoise_Apply(pConcealmentInfo, len, pcmdata); - return frameDelay; + /* Save end-of-frame attenuation and fading type */ + pConcealmentInfo->lastFadingType = fadingType; + pConcealmentInfo->fade_old = fadeStop; + pConcealmentInfo->concealState_old = concealState; + + return 1; +} + +/* attenuate pcmdata in Time Domain Fading process */ +static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, + FIXP_DBL fadeStop, FIXP_PCM *pcmdata) { + int i; + FIXP_DBL dStep; + FIXP_DBL dGain; + FIXP_DBL dGain_apply; + int bitshift = (DFRACT_BITS - SAMPLE_BITS); + + /* set start energy */ + dGain = fadeStart; + /* determine energy steps from sample to sample */ + dStep = (FIXP_DBL)((int)((fadeStart >> 1) - (fadeStop >> 1)) / len) << 1; + + for (i = start; i < (start + len); i++) { + dGain -= dStep; + /* prevent gain from getting negative due to possible fixpoint inaccuracies + */ + dGain_apply = fMax((FIXP_DBL)0, dGain); + /* finally, attenuate samples */ + pcmdata[i] = (FIXP_PCM)((fMult(pcmdata[i], (dGain_apply))) >> bitshift); + } +} + +/* +\brief Fill FadingStations + +The fadingstations are the attenuation factors, being applied to its dedicated +portions of pcm data. They are calculated using the fadingsteps. One fadingstep +is the weighted contribution to the fading slope within its dedicated portion of +pcm data. + +*Fadingsteps : 0 0 0 1 0 1 2 0 + + |<- 1 Frame pcm data ->| + fadeStart-->|__________ | + ^ ^ ^ ^ \____ | + Attenuation : | | | | ^ ^\__ | + | | | | | | ^\ | + | | | | | | | \___|<-- fadeStop + | | | | | | | ^ ^ + | | | | | | | | | +Fadingstations: [0][1][2][3][4][5][6][7][8] + +(Fadingstations "[0]" is "[8] from previous frame", therefore its not meaningful +to be edited) + +*/ +static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations, + int *fadingSteps, + FIXP_DBL fadeStop, + FIXP_DBL fadeStart, + TDfadingType fadingType) { + int i; + INT fadingSteps_sum = 0; + INT fadeDiff; + + fadingSteps_sum = fadingSteps[0] + fadingSteps[1] + fadingSteps[2] + + fadingSteps[3] + fadingSteps[4] + fadingSteps[5] + + fadingSteps[6] + fadingSteps[7]; + fadeDiff = ((INT)(fadeStop - fadeStart) / fMax(fadingSteps_sum, (INT)1)); + fadingStations[0] = fadeStart; + for (i = 1; i < 8; i++) { + fadingStations[i] = + fadingStations[i - 1] + (FIXP_DBL)(fadeDiff * fadingSteps[i - 1]); + } + fadingStations[8] = fadeStop; } +static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps) { + fadingSteps[0] = fadingSteps[1] = fadingSteps[2] = fadingSteps[3] = + fadingSteps[4] = fadingSteps[5] = fadingSteps[6] = fadingSteps[7] = 1; +} + +/* end of TimeDomainFading functions */ + +/* derived from int UsacRandomSign() */ +static int CConcealment_TDNoise_Random(ULONG *seed) { + *seed = (ULONG)(((UINT64)(*seed) * 69069) + 5); + return (int)(*seed); +} + +static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, + const int len, FIXP_PCM *const pcmdata) { + FIXP_PCM *states = pConcealmentInfo->TDNoiseStates; + FIXP_PCM noiseVal; + FIXP_DBL noiseValLong; + FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef; + FIXP_DBL TDNoiseAtt; + ULONG seed = pConcealmentInfo->TDNoiseSeed = + (ULONG)CConcealment_TDNoise_Random(&pConcealmentInfo->TDNoiseSeed) + 1; + + TDNoiseAtt = pConcealmentInfo->pConcealParams->comfortNoiseLevel; + + int ii; + + if ((pConcealmentInfo->concealState != ConcealState_Ok || + pConcealmentInfo->concealState_old != ConcealState_Ok) && + TDNoiseAtt != (FIXP_DBL)0) { + for (ii = 0; ii < (len << 3); ii++) { + /* create filtered noise */ + states[2] = states[1]; + states[1] = states[0]; + states[0] = ((FIXP_PCM)CConcealment_TDNoise_Random(&seed)); + noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) + + fMult(states[2], coef[2]); + noiseVal = FX_DBL2FX_PCM(fMult(noiseValLong, TDNoiseAtt)); + + /* add filtered noise - check for clipping, before */ + if (pcmdata[ii] > (FIXP_PCM)MAXVAL_FIXP_PCM - noiseVal && + noiseVal > (FIXP_PCM)0) { + noiseVal = noiseVal * (FIXP_PCM)-1; + } else if (pcmdata[ii] < (FIXP_PCM)MINVAL_FIXP_PCM - noiseVal && + noiseVal < (FIXP_PCM)0) { + noiseVal = noiseVal * (FIXP_PCM)-1; + } + + pcmdata[ii] += noiseVal; + } + } +} |