1*e5436536SAndroid Build Coastguard Worker /* -----------------------------------------------------------------------------
2*e5436536SAndroid Build Coastguard Worker Software License for The Fraunhofer FDK AAC Codec Library for Android
3*e5436536SAndroid Build Coastguard Worker
4*e5436536SAndroid Build Coastguard Worker © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
5*e5436536SAndroid Build Coastguard Worker Forschung e.V. All rights reserved.
6*e5436536SAndroid Build Coastguard Worker
7*e5436536SAndroid Build Coastguard Worker 1. INTRODUCTION
8*e5436536SAndroid Build Coastguard Worker The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9*e5436536SAndroid Build Coastguard Worker that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10*e5436536SAndroid Build Coastguard Worker scheme for digital audio. This FDK AAC Codec software is intended to be used on
11*e5436536SAndroid Build Coastguard Worker a wide variety of Android devices.
12*e5436536SAndroid Build Coastguard Worker
13*e5436536SAndroid Build Coastguard Worker AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14*e5436536SAndroid Build Coastguard Worker general perceptual audio codecs. AAC-ELD is considered the best-performing
15*e5436536SAndroid Build Coastguard Worker full-bandwidth communications codec by independent studies and is widely
16*e5436536SAndroid Build Coastguard Worker deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17*e5436536SAndroid Build Coastguard Worker specifications.
18*e5436536SAndroid Build Coastguard Worker
19*e5436536SAndroid Build Coastguard Worker Patent licenses for necessary patent claims for the FDK AAC Codec (including
20*e5436536SAndroid Build Coastguard Worker those of Fraunhofer) may be obtained through Via Licensing
21*e5436536SAndroid Build Coastguard Worker (www.vialicensing.com) or through the respective patent owners individually for
22*e5436536SAndroid Build Coastguard Worker the purpose of encoding or decoding bit streams in products that are compliant
23*e5436536SAndroid Build Coastguard Worker with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24*e5436536SAndroid Build Coastguard Worker Android devices already license these patent claims through Via Licensing or
25*e5436536SAndroid Build Coastguard Worker directly from the patent owners, and therefore FDK AAC Codec software may
26*e5436536SAndroid Build Coastguard Worker already be covered under those patent licenses when it is used for those
27*e5436536SAndroid Build Coastguard Worker licensed purposes only.
28*e5436536SAndroid Build Coastguard Worker
29*e5436536SAndroid Build Coastguard Worker Commercially-licensed AAC software libraries, including floating-point versions
30*e5436536SAndroid Build Coastguard Worker with enhanced sound quality, are also available from Fraunhofer. Users are
31*e5436536SAndroid Build Coastguard Worker encouraged to check the Fraunhofer website for additional applications
32*e5436536SAndroid Build Coastguard Worker information and documentation.
33*e5436536SAndroid Build Coastguard Worker
34*e5436536SAndroid Build Coastguard Worker 2. COPYRIGHT LICENSE
35*e5436536SAndroid Build Coastguard Worker
36*e5436536SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification,
37*e5436536SAndroid Build Coastguard Worker are permitted without payment of copyright license fees provided that you
38*e5436536SAndroid Build Coastguard Worker satisfy the following conditions:
39*e5436536SAndroid Build Coastguard Worker
40*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in redistributions of
41*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec or your modifications thereto in source code form.
42*e5436536SAndroid Build Coastguard Worker
43*e5436536SAndroid Build Coastguard Worker You must retain the complete text of this software license in the documentation
44*e5436536SAndroid Build Coastguard Worker and/or other materials provided with redistributions of the FDK AAC Codec or
45*e5436536SAndroid Build Coastguard Worker your modifications thereto in binary form. You must make available free of
46*e5436536SAndroid Build Coastguard Worker charge copies of the complete source code of the FDK AAC Codec and your
47*e5436536SAndroid Build Coastguard Worker modifications thereto to recipients of copies in binary form.
48*e5436536SAndroid Build Coastguard Worker
49*e5436536SAndroid Build Coastguard Worker The name of Fraunhofer may not be used to endorse or promote products derived
50*e5436536SAndroid Build Coastguard Worker from this library without prior written permission.
51*e5436536SAndroid Build Coastguard Worker
52*e5436536SAndroid Build Coastguard Worker You may not charge copyright license fees for anyone to use, copy or distribute
53*e5436536SAndroid Build Coastguard Worker the FDK AAC Codec software or your modifications thereto.
54*e5436536SAndroid Build Coastguard Worker
55*e5436536SAndroid Build Coastguard Worker Your modified versions of the FDK AAC Codec must carry prominent notices stating
56*e5436536SAndroid Build Coastguard Worker that you changed the software and the date of any change. For modified versions
57*e5436536SAndroid Build Coastguard Worker of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58*e5436536SAndroid Build Coastguard Worker must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59*e5436536SAndroid Build Coastguard Worker AAC Codec Library for Android."
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker 3. NO PATENT LICENSE
62*e5436536SAndroid Build Coastguard Worker
63*e5436536SAndroid Build Coastguard Worker NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64*e5436536SAndroid Build Coastguard Worker limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65*e5436536SAndroid Build Coastguard Worker Fraunhofer provides no warranty of patent non-infringement with respect to this
66*e5436536SAndroid Build Coastguard Worker software.
67*e5436536SAndroid Build Coastguard Worker
68*e5436536SAndroid Build Coastguard Worker You may use this FDK AAC Codec software or modifications thereto only for
69*e5436536SAndroid Build Coastguard Worker purposes that are authorized by appropriate patent licenses.
70*e5436536SAndroid Build Coastguard Worker
71*e5436536SAndroid Build Coastguard Worker 4. DISCLAIMER
72*e5436536SAndroid Build Coastguard Worker
73*e5436536SAndroid Build Coastguard Worker This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74*e5436536SAndroid Build Coastguard Worker holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75*e5436536SAndroid Build Coastguard Worker including but not limited to the implied warranties of merchantability and
76*e5436536SAndroid Build Coastguard Worker fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77*e5436536SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78*e5436536SAndroid Build Coastguard Worker or consequential damages, including but not limited to procurement of substitute
79*e5436536SAndroid Build Coastguard Worker goods or services; loss of use, data, or profits, or business interruption,
80*e5436536SAndroid Build Coastguard Worker however caused and on any theory of liability, whether in contract, strict
81*e5436536SAndroid Build Coastguard Worker liability, or tort (including negligence), arising in any way out of the use of
82*e5436536SAndroid Build Coastguard Worker this software, even if advised of the possibility of such damage.
83*e5436536SAndroid Build Coastguard Worker
84*e5436536SAndroid Build Coastguard Worker 5. CONTACT INFORMATION
85*e5436536SAndroid Build Coastguard Worker
86*e5436536SAndroid Build Coastguard Worker Fraunhofer Institute for Integrated Circuits IIS
87*e5436536SAndroid Build Coastguard Worker Attention: Audio and Multimedia Departments - FDK AAC LL
88*e5436536SAndroid Build Coastguard Worker Am Wolfsmantel 33
89*e5436536SAndroid Build Coastguard Worker 91058 Erlangen, Germany
90*e5436536SAndroid Build Coastguard Worker
91*e5436536SAndroid Build Coastguard Worker www.iis.fraunhofer.de/amm
92*e5436536SAndroid Build Coastguard Worker [email protected]
93*e5436536SAndroid Build Coastguard Worker ----------------------------------------------------------------------------- */
94*e5436536SAndroid Build Coastguard Worker
95*e5436536SAndroid Build Coastguard Worker /**************************** AAC decoder library ******************************
96*e5436536SAndroid Build Coastguard Worker
97*e5436536SAndroid Build Coastguard Worker Author(s): Josef Hoepfl
98*e5436536SAndroid Build Coastguard Worker
99*e5436536SAndroid Build Coastguard Worker Description: independent channel concealment
100*e5436536SAndroid Build Coastguard Worker
101*e5436536SAndroid Build Coastguard Worker *******************************************************************************/
102*e5436536SAndroid Build Coastguard Worker
103*e5436536SAndroid Build Coastguard Worker /*!
104*e5436536SAndroid Build Coastguard Worker \page concealment AAC core concealment
105*e5436536SAndroid Build Coastguard Worker
106*e5436536SAndroid Build Coastguard Worker This AAC core implementation includes a concealment function, which can be
107*e5436536SAndroid Build Coastguard Worker enabled using the several defines during compilation.
108*e5436536SAndroid Build Coastguard Worker
109*e5436536SAndroid Build Coastguard Worker There are various tests inside the core, starting with simple CRC tests and
110*e5436536SAndroid Build Coastguard Worker ending in a variety of plausibility checks. If such a check indicates an
111*e5436536SAndroid Build Coastguard Worker invalid bitstream, then concealment is applied.
112*e5436536SAndroid Build Coastguard Worker
113*e5436536SAndroid Build Coastguard Worker Concealment is also applied when the calling main program indicates a
114*e5436536SAndroid Build Coastguard Worker distorted or missing data frame using the frameOK flag. This is used for error
115*e5436536SAndroid Build Coastguard Worker detection on the transport layer. (See below)
116*e5436536SAndroid Build Coastguard Worker
117*e5436536SAndroid Build Coastguard Worker There are three concealment-modes:
118*e5436536SAndroid Build Coastguard Worker
119*e5436536SAndroid Build Coastguard Worker 1) Muting: The spectral data is simply set to zero in case of an detected
120*e5436536SAndroid Build Coastguard Worker error.
121*e5436536SAndroid Build Coastguard Worker
122*e5436536SAndroid Build Coastguard Worker 2) Noise substitution: In case of an detected error, concealment copies the
123*e5436536SAndroid Build Coastguard Worker last frame and adds attenuates the spectral data. For this mode you have to
124*e5436536SAndroid Build Coastguard Worker set the #CONCEAL_NOISE define. Noise substitution adds no additional delay.
125*e5436536SAndroid Build Coastguard Worker
126*e5436536SAndroid Build Coastguard Worker 3) Interpolation: The interpolation routine swaps the spectral data from the
127*e5436536SAndroid Build Coastguard Worker previous and the current frame just before the final frequency to time
128*e5436536SAndroid Build Coastguard Worker conversion. In case a single frame is corrupted, concealmant interpolates
129*e5436536SAndroid Build Coastguard Worker between the last good and the first good frame to create the spectral data for
130*e5436536SAndroid Build Coastguard Worker the missing frame. If multiple frames are corrupted, concealment implements
131*e5436536SAndroid Build Coastguard Worker first a fade out based on slightly modified spectral values from the last good
132*e5436536SAndroid Build Coastguard Worker frame. As soon as good frames are available, concealmant fades in the new
133*e5436536SAndroid Build Coastguard Worker spectral data. For this mode you have to set the #CONCEAL_INTER define. Note
134*e5436536SAndroid Build Coastguard Worker that in this case, you also need to set #SBR_BS_DELAY_ENABLE, which basically
135*e5436536SAndroid Build Coastguard Worker adds approriate delay in the SBR decoder. Note that the
136*e5436536SAndroid Build Coastguard Worker Interpolating-Concealment increases the delay of your decoder by one frame and
137*e5436536SAndroid Build Coastguard Worker that it does require additional resources such as memory and computational
138*e5436536SAndroid Build Coastguard Worker complexity.
139*e5436536SAndroid Build Coastguard Worker
140*e5436536SAndroid Build Coastguard Worker <h2>How concealment can be used with errors on the transport layer</h2>
141*e5436536SAndroid Build Coastguard Worker
142*e5436536SAndroid Build Coastguard Worker Many errors can or have to be detected on the transport layer. For example in
143*e5436536SAndroid Build Coastguard Worker IP based systems packet loss can occur. The transport protocol used should
144*e5436536SAndroid Build Coastguard Worker indicate such packet loss by inserting an empty frame with frameOK=0.
145*e5436536SAndroid Build Coastguard Worker */
146*e5436536SAndroid Build Coastguard Worker
147*e5436536SAndroid Build Coastguard Worker #include "conceal.h"
148*e5436536SAndroid Build Coastguard Worker
149*e5436536SAndroid Build Coastguard Worker #include "aac_rom.h"
150*e5436536SAndroid Build Coastguard Worker #include "genericStds.h"
151*e5436536SAndroid Build Coastguard Worker
152*e5436536SAndroid Build Coastguard Worker /* PNS (of block) */
153*e5436536SAndroid Build Coastguard Worker #include "aacdec_pns.h"
154*e5436536SAndroid Build Coastguard Worker #include "block.h"
155*e5436536SAndroid Build Coastguard Worker
156*e5436536SAndroid Build Coastguard Worker #define CONCEAL_DFLT_COMF_NOISE_LEVEL (0x100000)
157*e5436536SAndroid Build Coastguard Worker
158*e5436536SAndroid Build Coastguard Worker #define CONCEAL_NOT_DEFINED ((UCHAR)-1)
159*e5436536SAndroid Build Coastguard Worker
160*e5436536SAndroid Build Coastguard Worker /* default settings */
161*e5436536SAndroid Build Coastguard Worker #define CONCEAL_DFLT_FADEOUT_FRAMES (6)
162*e5436536SAndroid Build Coastguard Worker #define CONCEAL_DFLT_FADEIN_FRAMES (5)
163*e5436536SAndroid Build Coastguard Worker #define CONCEAL_DFLT_MUTE_RELEASE_FRAMES (0)
164*e5436536SAndroid Build Coastguard Worker
165*e5436536SAndroid Build Coastguard Worker #define CONCEAL_DFLT_FADE_FACTOR (0.707106781186548f) /* 1/sqrt(2) */
166*e5436536SAndroid Build Coastguard Worker
167*e5436536SAndroid Build Coastguard Worker /* some often used constants: */
168*e5436536SAndroid Build Coastguard Worker #define FIXP_ZERO FL2FXCONST_DBL(0.0f)
169*e5436536SAndroid Build Coastguard Worker #define FIXP_ONE FL2FXCONST_DBL(1.0f)
170*e5436536SAndroid Build Coastguard Worker #define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f)
171*e5436536SAndroid Build Coastguard Worker
172*e5436536SAndroid Build Coastguard Worker /* For parameter conversion */
173*e5436536SAndroid Build Coastguard Worker #define CONCEAL_PARAMETER_BITS (8)
174*e5436536SAndroid Build Coastguard Worker #define CONCEAL_MAX_QUANT_FACTOR ((1 << CONCEAL_PARAMETER_BITS) - 1)
175*e5436536SAndroid Build Coastguard Worker /*#define CONCEAL_MIN_ATTENUATION_FACTOR_025 ( FL2FXCONST_DBL(0.971627951577106174) )*/ /* -0.25 dB */
176*e5436536SAndroid Build Coastguard Worker #define CONCEAL_MIN_ATTENUATION_FACTOR_025_LD \
177*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(-0.041524101186092029596853445212299)
178*e5436536SAndroid Build Coastguard Worker /*#define CONCEAL_MIN_ATTENUATION_FACTOR_050 ( FL2FXCONST_DBL(0.944060876285923380) )*/ /* -0.50 dB */
179*e5436536SAndroid Build Coastguard Worker #define CONCEAL_MIN_ATTENUATION_FACTOR_050_LD \
180*e5436536SAndroid Build Coastguard Worker FL2FXCONST_DBL(-0.083048202372184059253597008145293)
181*e5436536SAndroid Build Coastguard Worker
182*e5436536SAndroid Build Coastguard Worker typedef enum {
183*e5436536SAndroid Build Coastguard Worker CConcealment_NoExpand,
184*e5436536SAndroid Build Coastguard Worker CConcealment_Expand,
185*e5436536SAndroid Build Coastguard Worker CConcealment_Compress
186*e5436536SAndroid Build Coastguard Worker } CConcealmentExpandType;
187*e5436536SAndroid Build Coastguard Worker
188*e5436536SAndroid Build Coastguard Worker static const FIXP_SGL facMod4Table[4] = {
189*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(0.500000000f), /* FIXP_SGL(0x4000), 2^-(1-0,00) */
190*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(0.594603558f), /* FIXP_SGL(0x4c1b), 2^-(1-0,25) */
191*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(0.707106781f), /* FIXP_SGL(0x5a82), 2^-(1-0,50) */
192*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(0.840896415f) /* FIXP_SGL(0x6ba2) 2^-(1-0,75) */
193*e5436536SAndroid Build Coastguard Worker };
194*e5436536SAndroid Build Coastguard Worker
195*e5436536SAndroid Build Coastguard Worker static void CConcealment_CalcBandEnergy(
196*e5436536SAndroid Build Coastguard Worker FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo,
197*e5436536SAndroid Build Coastguard Worker const int blockType, CConcealmentExpandType ex, int *sfbEnergy);
198*e5436536SAndroid Build Coastguard Worker
199*e5436536SAndroid Build Coastguard Worker static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum,
200*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScalePrev,
201*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScaleAct,
202*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScaleOut, int *enPrv,
203*e5436536SAndroid Build Coastguard Worker int *enAct, int sfbCnt,
204*e5436536SAndroid Build Coastguard Worker const SHORT *pSfbOffset);
205*e5436536SAndroid Build Coastguard Worker
206*e5436536SAndroid Build Coastguard Worker static int CConcealment_ApplyInter(
207*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *pConcealmentInfo,
208*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo,
209*e5436536SAndroid Build Coastguard Worker const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
210*e5436536SAndroid Build Coastguard Worker const int improveTonal, const int frameOk, const int mute_release_active);
211*e5436536SAndroid Build Coastguard Worker
212*e5436536SAndroid Build Coastguard Worker static int CConcealment_ApplyNoise(
213*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *pConcealmentInfo,
214*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo,
215*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
216*e5436536SAndroid Build Coastguard Worker const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
217*e5436536SAndroid Build Coastguard Worker const UINT flags);
218*e5436536SAndroid Build Coastguard Worker
219*e5436536SAndroid Build Coastguard Worker static void CConcealment_UpdateState(
220*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *pConcealmentInfo, int frameOk,
221*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
222*e5436536SAndroid Build Coastguard Worker const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo);
223*e5436536SAndroid Build Coastguard Worker
224*e5436536SAndroid Build Coastguard Worker static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec,
225*e5436536SAndroid Build Coastguard Worker int samplesPerFrame);
226*e5436536SAndroid Build Coastguard Worker
227*e5436536SAndroid Build Coastguard Worker /* TimeDomainFading */
228*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
229*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadeStop, PCM_DEC *pcmdata);
230*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations,
231*e5436536SAndroid Build Coastguard Worker int *fadingSteps,
232*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadeStop,
233*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadeStart,
234*e5436536SAndroid Build Coastguard Worker TDfadingType fadingType);
235*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps);
236*e5436536SAndroid Build Coastguard Worker
237*e5436536SAndroid Build Coastguard Worker /* Streamline the state machine */
238*e5436536SAndroid Build Coastguard Worker static int CConcealment_ApplyFadeOut(
239*e5436536SAndroid Build Coastguard Worker int mode, CConcealmentInfo *pConcealmentInfo,
240*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
241*e5436536SAndroid Build Coastguard Worker const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo);
242*e5436536SAndroid Build Coastguard Worker
243*e5436536SAndroid Build Coastguard Worker static int CConcealment_TDNoise_Random(ULONG *seed);
244*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
245*e5436536SAndroid Build Coastguard Worker const int len,
246*e5436536SAndroid Build Coastguard Worker const INT aacOutDataHeadroom,
247*e5436536SAndroid Build Coastguard Worker PCM_DEC *const pcmdata);
248*e5436536SAndroid Build Coastguard Worker
CConcealment_GetWinSeq(int prevWinSeq)249*e5436536SAndroid Build Coastguard Worker static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) {
250*e5436536SAndroid Build Coastguard Worker BLOCK_TYPE newWinSeq = BLOCK_LONG;
251*e5436536SAndroid Build Coastguard Worker
252*e5436536SAndroid Build Coastguard Worker /* Try to have only long blocks */
253*e5436536SAndroid Build Coastguard Worker if (prevWinSeq == BLOCK_START || prevWinSeq == BLOCK_SHORT) {
254*e5436536SAndroid Build Coastguard Worker newWinSeq = BLOCK_STOP;
255*e5436536SAndroid Build Coastguard Worker }
256*e5436536SAndroid Build Coastguard Worker
257*e5436536SAndroid Build Coastguard Worker return (newWinSeq);
258*e5436536SAndroid Build Coastguard Worker }
259*e5436536SAndroid Build Coastguard Worker
260*e5436536SAndroid Build Coastguard Worker /*!
261*e5436536SAndroid Build Coastguard Worker \brief Init common concealment information data
262*e5436536SAndroid Build Coastguard Worker
263*e5436536SAndroid Build Coastguard Worker \param pConcealCommonData Pointer to the concealment common data structure.
264*e5436536SAndroid Build Coastguard Worker */
CConcealment_InitCommonData(CConcealParams * pConcealCommonData)265*e5436536SAndroid Build Coastguard Worker void CConcealment_InitCommonData(CConcealParams *pConcealCommonData) {
266*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData != NULL) {
267*e5436536SAndroid Build Coastguard Worker int i;
268*e5436536SAndroid Build Coastguard Worker
269*e5436536SAndroid Build Coastguard Worker /* Set default error concealment technique */
270*e5436536SAndroid Build Coastguard Worker pConcealCommonData->method = ConcealMethodInter;
271*e5436536SAndroid Build Coastguard Worker
272*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES;
273*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES;
274*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numMuteReleaseFrames = CONCEAL_DFLT_MUTE_RELEASE_FRAMES;
275*e5436536SAndroid Build Coastguard Worker
276*e5436536SAndroid Build Coastguard Worker pConcealCommonData->comfortNoiseLevel =
277*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)CONCEAL_DFLT_COMF_NOISE_LEVEL;
278*e5436536SAndroid Build Coastguard Worker
279*e5436536SAndroid Build Coastguard Worker /* Init fade factors (symetric) */
280*e5436536SAndroid Build Coastguard Worker pConcealCommonData->fadeOutFactor[0] =
281*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR);
282*e5436536SAndroid Build Coastguard Worker pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0];
283*e5436536SAndroid Build Coastguard Worker
284*e5436536SAndroid Build Coastguard Worker for (i = 1; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
285*e5436536SAndroid Build Coastguard Worker pConcealCommonData->fadeOutFactor[i] =
286*e5436536SAndroid Build Coastguard Worker FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i - 1],
287*e5436536SAndroid Build Coastguard Worker FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR)));
288*e5436536SAndroid Build Coastguard Worker pConcealCommonData->fadeInFactor[i] =
289*e5436536SAndroid Build Coastguard Worker pConcealCommonData->fadeOutFactor[i];
290*e5436536SAndroid Build Coastguard Worker }
291*e5436536SAndroid Build Coastguard Worker }
292*e5436536SAndroid Build Coastguard Worker }
293*e5436536SAndroid Build Coastguard Worker
294*e5436536SAndroid Build Coastguard Worker /*!
295*e5436536SAndroid Build Coastguard Worker \brief Get current concealment method.
296*e5436536SAndroid Build Coastguard Worker
297*e5436536SAndroid Build Coastguard Worker \param pConcealCommonData Pointer to common concealment data (for all
298*e5436536SAndroid Build Coastguard Worker channels)
299*e5436536SAndroid Build Coastguard Worker */
CConcealment_GetMethod(CConcealParams * pConcealCommonData)300*e5436536SAndroid Build Coastguard Worker CConcealmentMethod CConcealment_GetMethod(CConcealParams *pConcealCommonData) {
301*e5436536SAndroid Build Coastguard Worker CConcealmentMethod method = ConcealMethodNone;
302*e5436536SAndroid Build Coastguard Worker
303*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData != NULL) {
304*e5436536SAndroid Build Coastguard Worker method = pConcealCommonData->method;
305*e5436536SAndroid Build Coastguard Worker }
306*e5436536SAndroid Build Coastguard Worker
307*e5436536SAndroid Build Coastguard Worker return (method);
308*e5436536SAndroid Build Coastguard Worker }
309*e5436536SAndroid Build Coastguard Worker
310*e5436536SAndroid Build Coastguard Worker /*!
311*e5436536SAndroid Build Coastguard Worker \brief Init concealment information for each channel
312*e5436536SAndroid Build Coastguard Worker
313*e5436536SAndroid Build Coastguard Worker \param pConcealChannelInfo Pointer to the channel related concealment info
314*e5436536SAndroid Build Coastguard Worker structure to be initialized. \param pConcealCommonData Pointer to common
315*e5436536SAndroid Build Coastguard Worker concealment data (for all channels) \param initRenderMode Initial render
316*e5436536SAndroid Build Coastguard Worker mode to be set for the current channel. \param samplesPerFrame The number
317*e5436536SAndroid Build Coastguard Worker of samples per frame.
318*e5436536SAndroid Build Coastguard Worker */
CConcealment_InitChannelData(CConcealmentInfo * pConcealChannelInfo,CConcealParams * pConcealCommonData,AACDEC_RENDER_MODE initRenderMode,int samplesPerFrame)319*e5436536SAndroid Build Coastguard Worker void CConcealment_InitChannelData(CConcealmentInfo *pConcealChannelInfo,
320*e5436536SAndroid Build Coastguard Worker CConcealParams *pConcealCommonData,
321*e5436536SAndroid Build Coastguard Worker AACDEC_RENDER_MODE initRenderMode,
322*e5436536SAndroid Build Coastguard Worker int samplesPerFrame) {
323*e5436536SAndroid Build Coastguard Worker int i;
324*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->TDNoiseSeed = 0;
325*e5436536SAndroid Build Coastguard Worker FDKmemclear(pConcealChannelInfo->TDNoiseStates,
326*e5436536SAndroid Build Coastguard Worker sizeof(pConcealChannelInfo->TDNoiseStates));
327*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->TDNoiseCoef[0] = FL2FXCONST_SGL(0.05f);
328*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->TDNoiseCoef[1] = FL2FXCONST_SGL(0.5f);
329*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->TDNoiseCoef[2] = FL2FXCONST_SGL(0.45f);
330*e5436536SAndroid Build Coastguard Worker
331*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->pConcealParams = pConcealCommonData;
332*e5436536SAndroid Build Coastguard Worker
333*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->lastRenderMode = initRenderMode;
334*e5436536SAndroid Build Coastguard Worker
335*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->windowShape = CONCEAL_NOT_DEFINED;
336*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->windowSequence = BLOCK_LONG; /* default type */
337*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->lastWinGrpLen = 1;
338*e5436536SAndroid Build Coastguard Worker
339*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->concealState = ConcealState_Ok;
340*e5436536SAndroid Build Coastguard Worker
341*e5436536SAndroid Build Coastguard Worker FDKmemclear(pConcealChannelInfo->spectralCoefficient,
342*e5436536SAndroid Build Coastguard Worker 1024 * sizeof(FIXP_CNCL));
343*e5436536SAndroid Build Coastguard Worker
344*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
345*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->specScale[i] = 0;
346*e5436536SAndroid Build Coastguard Worker }
347*e5436536SAndroid Build Coastguard Worker
348*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->iRandomPhase = 0;
349*e5436536SAndroid Build Coastguard Worker
350*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->prevFrameOk[0] = 1;
351*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->prevFrameOk[1] = 1;
352*e5436536SAndroid Build Coastguard Worker
353*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->cntFadeFrames = 0;
354*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->cntValidFrames = 0;
355*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->fade_old = (FIXP_DBL)MAXVAL_DBL;
356*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->winGrpOffset[0] = 0;
357*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->winGrpOffset[1] = 0;
358*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->attGrpOffset[0] = 0;
359*e5436536SAndroid Build Coastguard Worker pConcealChannelInfo->attGrpOffset[1] = 0;
360*e5436536SAndroid Build Coastguard Worker }
361*e5436536SAndroid Build Coastguard Worker
362*e5436536SAndroid Build Coastguard Worker /*!
363*e5436536SAndroid Build Coastguard Worker \brief Set error concealment parameters
364*e5436536SAndroid Build Coastguard Worker
365*e5436536SAndroid Build Coastguard Worker \param concealParams
366*e5436536SAndroid Build Coastguard Worker \param method
367*e5436536SAndroid Build Coastguard Worker \param fadeOutSlope
368*e5436536SAndroid Build Coastguard Worker \param fadeInSlope
369*e5436536SAndroid Build Coastguard Worker \param muteRelease
370*e5436536SAndroid Build Coastguard Worker \param comfNoiseLevel
371*e5436536SAndroid Build Coastguard Worker */
372*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR
CConcealment_SetParams(CConcealParams * concealParams,int method,int fadeOutSlope,int fadeInSlope,int muteRelease,FIXP_DBL comfNoiseLevel)373*e5436536SAndroid Build Coastguard Worker CConcealment_SetParams(CConcealParams *concealParams, int method,
374*e5436536SAndroid Build Coastguard Worker int fadeOutSlope, int fadeInSlope, int muteRelease,
375*e5436536SAndroid Build Coastguard Worker FIXP_DBL comfNoiseLevel) {
376*e5436536SAndroid Build Coastguard Worker /* set concealment technique */
377*e5436536SAndroid Build Coastguard Worker if (method != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
378*e5436536SAndroid Build Coastguard Worker switch ((CConcealmentMethod)method) {
379*e5436536SAndroid Build Coastguard Worker case ConcealMethodMute:
380*e5436536SAndroid Build Coastguard Worker case ConcealMethodNoise:
381*e5436536SAndroid Build Coastguard Worker case ConcealMethodInter:
382*e5436536SAndroid Build Coastguard Worker /* Be sure to enable delay adjustment of SBR decoder! */
383*e5436536SAndroid Build Coastguard Worker if (concealParams == NULL) {
384*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
385*e5436536SAndroid Build Coastguard Worker } else {
386*e5436536SAndroid Build Coastguard Worker /* set param */
387*e5436536SAndroid Build Coastguard Worker concealParams->method = (CConcealmentMethod)method;
388*e5436536SAndroid Build Coastguard Worker }
389*e5436536SAndroid Build Coastguard Worker break;
390*e5436536SAndroid Build Coastguard Worker
391*e5436536SAndroid Build Coastguard Worker default:
392*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
393*e5436536SAndroid Build Coastguard Worker }
394*e5436536SAndroid Build Coastguard Worker }
395*e5436536SAndroid Build Coastguard Worker
396*e5436536SAndroid Build Coastguard Worker /* set number of frames for fade-out slope */
397*e5436536SAndroid Build Coastguard Worker if (fadeOutSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
398*e5436536SAndroid Build Coastguard Worker if ((fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeOutSlope >= 0)) {
399*e5436536SAndroid Build Coastguard Worker if (concealParams == NULL) {
400*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
401*e5436536SAndroid Build Coastguard Worker } else {
402*e5436536SAndroid Build Coastguard Worker /* set param */
403*e5436536SAndroid Build Coastguard Worker concealParams->numFadeOutFrames = fadeOutSlope;
404*e5436536SAndroid Build Coastguard Worker }
405*e5436536SAndroid Build Coastguard Worker } else {
406*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
407*e5436536SAndroid Build Coastguard Worker }
408*e5436536SAndroid Build Coastguard Worker }
409*e5436536SAndroid Build Coastguard Worker
410*e5436536SAndroid Build Coastguard Worker /* set number of frames for fade-in slope */
411*e5436536SAndroid Build Coastguard Worker if (fadeInSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
412*e5436536SAndroid Build Coastguard Worker if ((fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeInSlope >= 0)) {
413*e5436536SAndroid Build Coastguard Worker if (concealParams == NULL) {
414*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
415*e5436536SAndroid Build Coastguard Worker } else {
416*e5436536SAndroid Build Coastguard Worker /* set param */
417*e5436536SAndroid Build Coastguard Worker concealParams->numFadeInFrames = fadeInSlope;
418*e5436536SAndroid Build Coastguard Worker }
419*e5436536SAndroid Build Coastguard Worker } else {
420*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
421*e5436536SAndroid Build Coastguard Worker }
422*e5436536SAndroid Build Coastguard Worker }
423*e5436536SAndroid Build Coastguard Worker
424*e5436536SAndroid Build Coastguard Worker /* set number of error-free frames after which the muting will be released */
425*e5436536SAndroid Build Coastguard Worker if (muteRelease != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
426*e5436536SAndroid Build Coastguard Worker if ((muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS << 1)) &&
427*e5436536SAndroid Build Coastguard Worker (muteRelease >= 0)) {
428*e5436536SAndroid Build Coastguard Worker if (concealParams == NULL) {
429*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
430*e5436536SAndroid Build Coastguard Worker } else {
431*e5436536SAndroid Build Coastguard Worker /* set param */
432*e5436536SAndroid Build Coastguard Worker concealParams->numMuteReleaseFrames = muteRelease;
433*e5436536SAndroid Build Coastguard Worker }
434*e5436536SAndroid Build Coastguard Worker } else {
435*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
436*e5436536SAndroid Build Coastguard Worker }
437*e5436536SAndroid Build Coastguard Worker }
438*e5436536SAndroid Build Coastguard Worker
439*e5436536SAndroid Build Coastguard Worker /* set confort noise level which will be inserted while in state 'muting' */
440*e5436536SAndroid Build Coastguard Worker if (comfNoiseLevel != (FIXP_DBL)AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
441*e5436536SAndroid Build Coastguard Worker if ((comfNoiseLevel < (FIXP_DBL)0) ||
442*e5436536SAndroid Build Coastguard Worker (comfNoiseLevel > (FIXP_DBL)MAXVAL_DBL)) {
443*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
444*e5436536SAndroid Build Coastguard Worker }
445*e5436536SAndroid Build Coastguard Worker if (concealParams == NULL) {
446*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
447*e5436536SAndroid Build Coastguard Worker } else {
448*e5436536SAndroid Build Coastguard Worker concealParams->comfortNoiseLevel = (FIXP_DBL)comfNoiseLevel;
449*e5436536SAndroid Build Coastguard Worker }
450*e5436536SAndroid Build Coastguard Worker }
451*e5436536SAndroid Build Coastguard Worker
452*e5436536SAndroid Build Coastguard Worker return (AAC_DEC_OK);
453*e5436536SAndroid Build Coastguard Worker }
454*e5436536SAndroid Build Coastguard Worker
455*e5436536SAndroid Build Coastguard Worker /*!
456*e5436536SAndroid Build Coastguard Worker \brief Set fade-out/in attenuation factor vectors
457*e5436536SAndroid Build Coastguard Worker
458*e5436536SAndroid Build Coastguard Worker \param concealParams
459*e5436536SAndroid Build Coastguard Worker \param fadeOutAttenuationVector
460*e5436536SAndroid Build Coastguard Worker \param fadeInAttenuationVector
461*e5436536SAndroid Build Coastguard Worker
462*e5436536SAndroid Build Coastguard Worker \return 0 if OK all other values indicate errors
463*e5436536SAndroid Build Coastguard Worker */
464*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR
CConcealment_SetAttenuation(CConcealParams * concealParams,const SHORT * fadeOutAttenuationVector,const SHORT * fadeInAttenuationVector)465*e5436536SAndroid Build Coastguard Worker CConcealment_SetAttenuation(CConcealParams *concealParams,
466*e5436536SAndroid Build Coastguard Worker const SHORT *fadeOutAttenuationVector,
467*e5436536SAndroid Build Coastguard Worker const SHORT *fadeInAttenuationVector) {
468*e5436536SAndroid Build Coastguard Worker if ((fadeOutAttenuationVector == NULL) && (fadeInAttenuationVector == NULL)) {
469*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
470*e5436536SAndroid Build Coastguard Worker }
471*e5436536SAndroid Build Coastguard Worker
472*e5436536SAndroid Build Coastguard Worker /* Fade-out factors */
473*e5436536SAndroid Build Coastguard Worker if (fadeOutAttenuationVector != NULL) {
474*e5436536SAndroid Build Coastguard Worker int i;
475*e5436536SAndroid Build Coastguard Worker
476*e5436536SAndroid Build Coastguard Worker /* check quantized factors first */
477*e5436536SAndroid Build Coastguard Worker for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
478*e5436536SAndroid Build Coastguard Worker if ((fadeOutAttenuationVector[i] < 0) ||
479*e5436536SAndroid Build Coastguard Worker (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) {
480*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
481*e5436536SAndroid Build Coastguard Worker }
482*e5436536SAndroid Build Coastguard Worker }
483*e5436536SAndroid Build Coastguard Worker if (concealParams == NULL) {
484*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
485*e5436536SAndroid Build Coastguard Worker }
486*e5436536SAndroid Build Coastguard Worker
487*e5436536SAndroid Build Coastguard Worker /* now dequantize factors */
488*e5436536SAndroid Build Coastguard Worker for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
489*e5436536SAndroid Build Coastguard Worker concealParams->fadeOutFactor[i] =
490*e5436536SAndroid Build Coastguard Worker FX_DBL2FX_SGL(fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0,
491*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0 / 2.0) >>
492*e5436536SAndroid Build Coastguard Worker (CONCEAL_PARAMETER_BITS - 1)) *
493*e5436536SAndroid Build Coastguard Worker (INT)fadeOutAttenuationVector[i]),
494*e5436536SAndroid Build Coastguard Worker CONCEAL_PARAMETER_BITS));
495*e5436536SAndroid Build Coastguard Worker }
496*e5436536SAndroid Build Coastguard Worker }
497*e5436536SAndroid Build Coastguard Worker
498*e5436536SAndroid Build Coastguard Worker /* Fade-in factors */
499*e5436536SAndroid Build Coastguard Worker if (fadeInAttenuationVector != NULL) {
500*e5436536SAndroid Build Coastguard Worker int i;
501*e5436536SAndroid Build Coastguard Worker
502*e5436536SAndroid Build Coastguard Worker /* check quantized factors first */
503*e5436536SAndroid Build Coastguard Worker for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
504*e5436536SAndroid Build Coastguard Worker if ((fadeInAttenuationVector[i] < 0) ||
505*e5436536SAndroid Build Coastguard Worker (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) {
506*e5436536SAndroid Build Coastguard Worker return AAC_DEC_SET_PARAM_FAIL;
507*e5436536SAndroid Build Coastguard Worker }
508*e5436536SAndroid Build Coastguard Worker }
509*e5436536SAndroid Build Coastguard Worker if (concealParams == NULL) {
510*e5436536SAndroid Build Coastguard Worker return AAC_DEC_INVALID_HANDLE;
511*e5436536SAndroid Build Coastguard Worker }
512*e5436536SAndroid Build Coastguard Worker
513*e5436536SAndroid Build Coastguard Worker /* now dequantize factors */
514*e5436536SAndroid Build Coastguard Worker for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
515*e5436536SAndroid Build Coastguard Worker concealParams->fadeInFactor[i] = FX_DBL2FX_SGL(
516*e5436536SAndroid Build Coastguard Worker fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0,
517*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)((INT)(FIXP_ONE >> CONCEAL_PARAMETER_BITS) *
518*e5436536SAndroid Build Coastguard Worker (INT)fadeInAttenuationVector[i]),
519*e5436536SAndroid Build Coastguard Worker CONCEAL_PARAMETER_BITS));
520*e5436536SAndroid Build Coastguard Worker }
521*e5436536SAndroid Build Coastguard Worker }
522*e5436536SAndroid Build Coastguard Worker
523*e5436536SAndroid Build Coastguard Worker return (AAC_DEC_OK);
524*e5436536SAndroid Build Coastguard Worker }
525*e5436536SAndroid Build Coastguard Worker
526*e5436536SAndroid Build Coastguard Worker /*!
527*e5436536SAndroid Build Coastguard Worker \brief Get state of concealment module.
528*e5436536SAndroid Build Coastguard Worker
529*e5436536SAndroid Build Coastguard Worker \param pConcealChannelInfo
530*e5436536SAndroid Build Coastguard Worker
531*e5436536SAndroid Build Coastguard Worker \return Concealment state.
532*e5436536SAndroid Build Coastguard Worker */
CConcealment_GetState(CConcealmentInfo * pConcealChannelInfo)533*e5436536SAndroid Build Coastguard Worker CConcealmentState CConcealment_GetState(CConcealmentInfo *pConcealChannelInfo) {
534*e5436536SAndroid Build Coastguard Worker CConcealmentState state = ConcealState_Ok;
535*e5436536SAndroid Build Coastguard Worker
536*e5436536SAndroid Build Coastguard Worker if (pConcealChannelInfo != NULL) {
537*e5436536SAndroid Build Coastguard Worker state = pConcealChannelInfo->concealState;
538*e5436536SAndroid Build Coastguard Worker }
539*e5436536SAndroid Build Coastguard Worker
540*e5436536SAndroid Build Coastguard Worker return (state);
541*e5436536SAndroid Build Coastguard Worker }
542*e5436536SAndroid Build Coastguard Worker
543*e5436536SAndroid Build Coastguard Worker /*!
544*e5436536SAndroid Build Coastguard Worker \brief Store data for concealment techniques applied later
545*e5436536SAndroid Build Coastguard Worker
546*e5436536SAndroid Build Coastguard Worker Interface function to store data for different concealment strategies
547*e5436536SAndroid Build Coastguard Worker */
CConcealment_Store(CConcealmentInfo * hConcealmentInfo,CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo)548*e5436536SAndroid Build Coastguard Worker void CConcealment_Store(
549*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *hConcealmentInfo,
550*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo,
551*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) {
552*e5436536SAndroid Build Coastguard Worker UCHAR nbDiv = NB_DIV;
553*e5436536SAndroid Build Coastguard Worker
554*e5436536SAndroid Build Coastguard Worker if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD &&
555*e5436536SAndroid Build Coastguard Worker pAacDecoderChannelInfo->data.usac.mod[nbDiv - 1] == 0))
556*e5436536SAndroid Build Coastguard Worker
557*e5436536SAndroid Build Coastguard Worker {
558*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pSpectralCoefficient =
559*e5436536SAndroid Build Coastguard Worker SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
560*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
561*e5436536SAndroid Build Coastguard Worker CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
562*e5436536SAndroid Build Coastguard Worker
563*e5436536SAndroid Build Coastguard Worker SHORT tSpecScale[8];
564*e5436536SAndroid Build Coastguard Worker UCHAR tWindowShape;
565*e5436536SAndroid Build Coastguard Worker BLOCK_TYPE tWindowSequence;
566*e5436536SAndroid Build Coastguard Worker
567*e5436536SAndroid Build Coastguard Worker /* store old window infos for swapping */
568*e5436536SAndroid Build Coastguard Worker tWindowSequence = hConcealmentInfo->windowSequence;
569*e5436536SAndroid Build Coastguard Worker tWindowShape = hConcealmentInfo->windowShape;
570*e5436536SAndroid Build Coastguard Worker
571*e5436536SAndroid Build Coastguard Worker /* store old scale factors for swapping */
572*e5436536SAndroid Build Coastguard Worker FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT));
573*e5436536SAndroid Build Coastguard Worker
574*e5436536SAndroid Build Coastguard Worker /* store new window infos */
575*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->windowSequence = GetWindowSequence(pIcsInfo);
576*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo);
577*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->lastWinGrpLen =
578*e5436536SAndroid Build Coastguard Worker *(GetWindowGroupLengthTable(pIcsInfo) + GetWindowGroups(pIcsInfo) - 1);
579*e5436536SAndroid Build Coastguard Worker
580*e5436536SAndroid Build Coastguard Worker /* store new scale factors */
581*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8 * sizeof(SHORT));
582*e5436536SAndroid Build Coastguard Worker
583*e5436536SAndroid Build Coastguard Worker if (hConcealmentInfo->pConcealParams->method < ConcealMethodInter) {
584*e5436536SAndroid Build Coastguard Worker /* store new spectral bins */
585*e5436536SAndroid Build Coastguard Worker #if (CNCL_FRACT_BITS == DFRACT_BITS)
586*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient,
587*e5436536SAndroid Build Coastguard Worker 1024 * sizeof(FIXP_CNCL));
588*e5436536SAndroid Build Coastguard Worker #else
589*e5436536SAndroid Build Coastguard Worker FIXP_CNCL *RESTRICT pCncl =
590*e5436536SAndroid Build Coastguard Worker &hConcealmentInfo->spectralCoefficient[1024 - 1];
591*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1];
592*e5436536SAndroid Build Coastguard Worker int i;
593*e5436536SAndroid Build Coastguard Worker for (i = 1024; i != 0; i--) {
594*e5436536SAndroid Build Coastguard Worker *pCncl-- = FX_DBL2FX_CNCL(*pSpec--);
595*e5436536SAndroid Build Coastguard Worker }
596*e5436536SAndroid Build Coastguard Worker #endif
597*e5436536SAndroid Build Coastguard Worker } else {
598*e5436536SAndroid Build Coastguard Worker /* swap spectral data */
599*e5436536SAndroid Build Coastguard Worker #if (FIXP_CNCL == FIXP_DBL)
600*e5436536SAndroid Build Coastguard Worker C_ALLOC_SCRATCH_START(pSpecTmp, FIXP_DBL, 1024);
601*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pSpecTmp, pSpectralCoefficient, 1024 * sizeof(FIXP_DBL));
602*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient,
603*e5436536SAndroid Build Coastguard Worker 1024 * sizeof(FIXP_DBL));
604*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpecTmp,
605*e5436536SAndroid Build Coastguard Worker 1024 * sizeof(FIXP_DBL));
606*e5436536SAndroid Build Coastguard Worker C_ALLOC_SCRATCH_END(pSpecTmp, FIXP_DBL, 1024);
607*e5436536SAndroid Build Coastguard Worker #else
608*e5436536SAndroid Build Coastguard Worker FIXP_CNCL *RESTRICT pCncl =
609*e5436536SAndroid Build Coastguard Worker &hConcealmentInfo->spectralCoefficient[1024 - 1];
610*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1];
611*e5436536SAndroid Build Coastguard Worker FIXP_DBL tSpec;
612*e5436536SAndroid Build Coastguard Worker
613*e5436536SAndroid Build Coastguard Worker for (int i = 1024; i != 0; i--) {
614*e5436536SAndroid Build Coastguard Worker tSpec = *pSpec;
615*e5436536SAndroid Build Coastguard Worker *pSpec-- = FX_CNCL2FX_DBL(*pCncl);
616*e5436536SAndroid Build Coastguard Worker *pCncl-- = FX_DBL2FX_CNCL(tSpec);
617*e5436536SAndroid Build Coastguard Worker }
618*e5436536SAndroid Build Coastguard Worker #endif
619*e5436536SAndroid Build Coastguard Worker
620*e5436536SAndroid Build Coastguard Worker /* complete swapping of window infos */
621*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = tWindowSequence;
622*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = tWindowShape;
623*e5436536SAndroid Build Coastguard Worker
624*e5436536SAndroid Build Coastguard Worker /* complete swapping of scale factors */
625*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pSpecScale, tSpecScale, 8 * sizeof(SHORT));
626*e5436536SAndroid Build Coastguard Worker }
627*e5436536SAndroid Build Coastguard Worker }
628*e5436536SAndroid Build Coastguard Worker
629*e5436536SAndroid Build Coastguard Worker if (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD) {
630*e5436536SAndroid Build Coastguard Worker /* Store LSF4 */
631*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf,
632*e5436536SAndroid Build Coastguard Worker sizeof(hConcealmentInfo->lsf4));
633*e5436536SAndroid Build Coastguard Worker /* Store TCX gain */
634*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->last_tcx_gain =
635*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo->last_tcx_gain;
636*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->last_tcx_gain_e =
637*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo->last_tcx_gain_e;
638*e5436536SAndroid Build Coastguard Worker }
639*e5436536SAndroid Build Coastguard Worker }
640*e5436536SAndroid Build Coastguard Worker
641*e5436536SAndroid Build Coastguard Worker /*!
642*e5436536SAndroid Build Coastguard Worker \brief Apply concealment
643*e5436536SAndroid Build Coastguard Worker
644*e5436536SAndroid Build Coastguard Worker Interface function to different concealment strategies
645*e5436536SAndroid Build Coastguard Worker */
CConcealment_Apply(CConcealmentInfo * hConcealmentInfo,CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,const SamplingRateInfo * pSamplingRateInfo,const int samplesPerFrame,const UCHAR lastLpdMode,const int frameOk,const UINT flags)646*e5436536SAndroid Build Coastguard Worker int CConcealment_Apply(
647*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *hConcealmentInfo,
648*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo,
649*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
650*e5436536SAndroid Build Coastguard Worker const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
651*e5436536SAndroid Build Coastguard Worker const UCHAR lastLpdMode, const int frameOk, const UINT flags) {
652*e5436536SAndroid Build Coastguard Worker int appliedProcessing = 0;
653*e5436536SAndroid Build Coastguard Worker const int mute_release_active =
654*e5436536SAndroid Build Coastguard Worker frameOk && (hConcealmentInfo->concealState >= ConcealState_Mute) &&
655*e5436536SAndroid Build Coastguard Worker (hConcealmentInfo->cntValidFrames + 1 <=
656*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->pConcealParams->numMuteReleaseFrames);
657*e5436536SAndroid Build Coastguard Worker
658*e5436536SAndroid Build Coastguard Worker if (hConcealmentInfo->windowShape == CONCEAL_NOT_DEFINED) {
659*e5436536SAndroid Build Coastguard Worker /* Initialize window_shape with same value as in the current (parsed) frame.
660*e5436536SAndroid Build Coastguard Worker Because section 4.6.11.3.2 (Windowing and block switching) of ISO/IEC
661*e5436536SAndroid Build Coastguard Worker 14496-3:2009 says: For the first raw_data_block() to be decoded the
662*e5436536SAndroid Build Coastguard Worker window_shape of the left and right half of the window are identical. */
663*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->windowShape = pAacDecoderChannelInfo->icsInfo.WindowShape;
664*e5436536SAndroid Build Coastguard Worker }
665*e5436536SAndroid Build Coastguard Worker
666*e5436536SAndroid Build Coastguard Worker if (frameOk && !mute_release_active) {
667*e5436536SAndroid Build Coastguard Worker /* Update render mode if frameOk except for ongoing mute release state. */
668*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->lastRenderMode =
669*e5436536SAndroid Build Coastguard Worker (SCHAR)pAacDecoderChannelInfo->renderMode;
670*e5436536SAndroid Build Coastguard Worker
671*e5436536SAndroid Build Coastguard Worker /* Rescue current data for concealment in future frames */
672*e5436536SAndroid Build Coastguard Worker CConcealment_Store(hConcealmentInfo, pAacDecoderChannelInfo,
673*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo);
674*e5436536SAndroid Build Coastguard Worker /* Reset index to random sign vector to make sign calculation frame agnostic
675*e5436536SAndroid Build Coastguard Worker (only depends on number of subsequently concealed spectral blocks) */
676*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->iRandomPhase = 0;
677*e5436536SAndroid Build Coastguard Worker } else {
678*e5436536SAndroid Build Coastguard Worker if (hConcealmentInfo->lastRenderMode == AACDEC_RENDER_INVALID) {
679*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->lastRenderMode = AACDEC_RENDER_IMDCT;
680*e5436536SAndroid Build Coastguard Worker }
681*e5436536SAndroid Build Coastguard Worker pAacDecoderChannelInfo->renderMode =
682*e5436536SAndroid Build Coastguard Worker (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode;
683*e5436536SAndroid Build Coastguard Worker }
684*e5436536SAndroid Build Coastguard Worker
685*e5436536SAndroid Build Coastguard Worker /* hand current frame status to the state machine */
686*e5436536SAndroid Build Coastguard Worker CConcealment_UpdateState(hConcealmentInfo, frameOk,
687*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo, samplesPerFrame,
688*e5436536SAndroid Build Coastguard Worker pAacDecoderChannelInfo);
689*e5436536SAndroid Build Coastguard Worker
690*e5436536SAndroid Build Coastguard Worker {
691*e5436536SAndroid Build Coastguard Worker if (!frameOk && pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_IMDCT) {
692*e5436536SAndroid Build Coastguard Worker /* LPC extrapolation */
693*e5436536SAndroid Build Coastguard Worker CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff,
694*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo->lpc4_lsf,
695*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo->lsf_adaptive_mean,
696*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->lastRenderMode == AACDEC_RENDER_IMDCT);
697*e5436536SAndroid Build Coastguard Worker FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf,
698*e5436536SAndroid Build Coastguard Worker sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf));
699*e5436536SAndroid Build Coastguard Worker }
700*e5436536SAndroid Build Coastguard Worker
701*e5436536SAndroid Build Coastguard Worker /* Create data for signal rendering according to the selected concealment
702*e5436536SAndroid Build Coastguard Worker * method and decoder operating mode. */
703*e5436536SAndroid Build Coastguard Worker
704*e5436536SAndroid Build Coastguard Worker if ((!frameOk || mute_release_active) &&
705*e5436536SAndroid Build Coastguard Worker (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD)) {
706*e5436536SAndroid Build Coastguard Worker /* Restore old LSF4 */
707*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pAacDecoderStaticChannelInfo->lpc4_lsf, hConcealmentInfo->lsf4,
708*e5436536SAndroid Build Coastguard Worker sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf));
709*e5436536SAndroid Build Coastguard Worker /* Restore old TCX gain */
710*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo->last_tcx_gain =
711*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->last_tcx_gain;
712*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo->last_tcx_gain_e =
713*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->last_tcx_gain_e;
714*e5436536SAndroid Build Coastguard Worker }
715*e5436536SAndroid Build Coastguard Worker
716*e5436536SAndroid Build Coastguard Worker if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD &&
717*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo->last_lpd_mode == 0)) {
718*e5436536SAndroid Build Coastguard Worker switch (hConcealmentInfo->pConcealParams->method) {
719*e5436536SAndroid Build Coastguard Worker default:
720*e5436536SAndroid Build Coastguard Worker case ConcealMethodMute:
721*e5436536SAndroid Build Coastguard Worker if (!frameOk) {
722*e5436536SAndroid Build Coastguard Worker /* Mute spectral data in case of errors */
723*e5436536SAndroid Build Coastguard Worker FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient,
724*e5436536SAndroid Build Coastguard Worker samplesPerFrame * sizeof(FIXP_DBL));
725*e5436536SAndroid Build Coastguard Worker /* Set last window shape */
726*e5436536SAndroid Build Coastguard Worker pAacDecoderChannelInfo->icsInfo.WindowShape =
727*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->windowShape;
728*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
729*e5436536SAndroid Build Coastguard Worker }
730*e5436536SAndroid Build Coastguard Worker break;
731*e5436536SAndroid Build Coastguard Worker
732*e5436536SAndroid Build Coastguard Worker case ConcealMethodNoise:
733*e5436536SAndroid Build Coastguard Worker /* Noise substitution error concealment technique */
734*e5436536SAndroid Build Coastguard Worker appliedProcessing = CConcealment_ApplyNoise(
735*e5436536SAndroid Build Coastguard Worker hConcealmentInfo, pAacDecoderChannelInfo,
736*e5436536SAndroid Build Coastguard Worker pAacDecoderStaticChannelInfo, pSamplingRateInfo, samplesPerFrame,
737*e5436536SAndroid Build Coastguard Worker flags);
738*e5436536SAndroid Build Coastguard Worker break;
739*e5436536SAndroid Build Coastguard Worker
740*e5436536SAndroid Build Coastguard Worker case ConcealMethodInter:
741*e5436536SAndroid Build Coastguard Worker /* Energy interpolation concealment based on 3GPP */
742*e5436536SAndroid Build Coastguard Worker appliedProcessing = CConcealment_ApplyInter(
743*e5436536SAndroid Build Coastguard Worker hConcealmentInfo, pAacDecoderChannelInfo, pSamplingRateInfo,
744*e5436536SAndroid Build Coastguard Worker samplesPerFrame, 0, /* don't use tonal improvement */
745*e5436536SAndroid Build Coastguard Worker frameOk, mute_release_active);
746*e5436536SAndroid Build Coastguard Worker break;
747*e5436536SAndroid Build Coastguard Worker }
748*e5436536SAndroid Build Coastguard Worker } else if (!frameOk || mute_release_active) {
749*e5436536SAndroid Build Coastguard Worker /* simply restore the buffer */
750*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pSpectralCoefficient =
751*e5436536SAndroid Build Coastguard Worker SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
752*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
753*e5436536SAndroid Build Coastguard Worker CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
754*e5436536SAndroid Build Coastguard Worker #if (CNCL_FRACT_BITS != DFRACT_BITS)
755*e5436536SAndroid Build Coastguard Worker FIXP_CNCL *RESTRICT pCncl =
756*e5436536SAndroid Build Coastguard Worker &hConcealmentInfo->spectralCoefficient[1024 - 1];
757*e5436536SAndroid Build Coastguard Worker FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1];
758*e5436536SAndroid Build Coastguard Worker int i;
759*e5436536SAndroid Build Coastguard Worker #endif
760*e5436536SAndroid Build Coastguard Worker
761*e5436536SAndroid Build Coastguard Worker /* restore window infos (gri) do we need that? */
762*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = hConcealmentInfo->windowSequence;
763*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = hConcealmentInfo->windowShape;
764*e5436536SAndroid Build Coastguard Worker
765*e5436536SAndroid Build Coastguard Worker if (hConcealmentInfo->concealState != ConcealState_Mute) {
766*e5436536SAndroid Build Coastguard Worker /* restore scale factors */
767*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT));
768*e5436536SAndroid Build Coastguard Worker
769*e5436536SAndroid Build Coastguard Worker /* restore spectral bins */
770*e5436536SAndroid Build Coastguard Worker #if (CNCL_FRACT_BITS == DFRACT_BITS)
771*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient,
772*e5436536SAndroid Build Coastguard Worker 1024 * sizeof(FIXP_DBL));
773*e5436536SAndroid Build Coastguard Worker #else
774*e5436536SAndroid Build Coastguard Worker for (i = 1024; i != 0; i--) {
775*e5436536SAndroid Build Coastguard Worker *pSpec-- = FX_CNCL2FX_DBL(*pCncl--);
776*e5436536SAndroid Build Coastguard Worker }
777*e5436536SAndroid Build Coastguard Worker #endif
778*e5436536SAndroid Build Coastguard Worker } else {
779*e5436536SAndroid Build Coastguard Worker /* clear scale factors */
780*e5436536SAndroid Build Coastguard Worker FDKmemclear(pSpecScale, 8 * sizeof(SHORT));
781*e5436536SAndroid Build Coastguard Worker
782*e5436536SAndroid Build Coastguard Worker /* clear buffer */
783*e5436536SAndroid Build Coastguard Worker FDKmemclear(pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL));
784*e5436536SAndroid Build Coastguard Worker }
785*e5436536SAndroid Build Coastguard Worker }
786*e5436536SAndroid Build Coastguard Worker }
787*e5436536SAndroid Build Coastguard Worker /* update history */
788*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1];
789*e5436536SAndroid Build Coastguard Worker hConcealmentInfo->prevFrameOk[1] = frameOk;
790*e5436536SAndroid Build Coastguard Worker
791*e5436536SAndroid Build Coastguard Worker return mute_release_active ? -1 : appliedProcessing;
792*e5436536SAndroid Build Coastguard Worker }
793*e5436536SAndroid Build Coastguard Worker
794*e5436536SAndroid Build Coastguard Worker /*!
795*e5436536SAndroid Build Coastguard Worker \brief Apply concealment noise substitution
796*e5436536SAndroid Build Coastguard Worker
797*e5436536SAndroid Build Coastguard Worker In case of frame lost this function produces a noisy frame with respect to the
798*e5436536SAndroid Build Coastguard Worker energies values of past frame.
799*e5436536SAndroid Build Coastguard Worker */
CConcealment_ApplyNoise(CConcealmentInfo * pConcealmentInfo,CAacDecoderChannelInfo * pAacDecoderChannelInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,const SamplingRateInfo * pSamplingRateInfo,const int samplesPerFrame,const UINT flags)800*e5436536SAndroid Build Coastguard Worker static int CConcealment_ApplyNoise(
801*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *pConcealmentInfo,
802*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo,
803*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
804*e5436536SAndroid Build Coastguard Worker const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
805*e5436536SAndroid Build Coastguard Worker const UINT flags) {
806*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pSpectralCoefficient =
807*e5436536SAndroid Build Coastguard Worker SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
808*e5436536SAndroid Build Coastguard Worker CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
809*e5436536SAndroid Build Coastguard Worker
810*e5436536SAndroid Build Coastguard Worker int appliedProcessing = 0;
811*e5436536SAndroid Build Coastguard Worker
812*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pConcealmentInfo != NULL);
813*e5436536SAndroid Build Coastguard Worker FDK_ASSERT((samplesPerFrame >= 120) && (samplesPerFrame <= 1024));
814*e5436536SAndroid Build Coastguard Worker
815*e5436536SAndroid Build Coastguard Worker switch (pConcealmentInfo->concealState) {
816*e5436536SAndroid Build Coastguard Worker case ConcealState_Ok:
817*e5436536SAndroid Build Coastguard Worker /* Nothing to do here! */
818*e5436536SAndroid Build Coastguard Worker break;
819*e5436536SAndroid Build Coastguard Worker
820*e5436536SAndroid Build Coastguard Worker case ConcealState_Single:
821*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeOut:
822*e5436536SAndroid Build Coastguard Worker appliedProcessing = CConcealment_ApplyFadeOut(
823*e5436536SAndroid Build Coastguard Worker /*mode =*/1, pConcealmentInfo, pAacDecoderStaticChannelInfo,
824*e5436536SAndroid Build Coastguard Worker samplesPerFrame, pAacDecoderChannelInfo);
825*e5436536SAndroid Build Coastguard Worker break;
826*e5436536SAndroid Build Coastguard Worker
827*e5436536SAndroid Build Coastguard Worker case ConcealState_Mute: {
828*e5436536SAndroid Build Coastguard Worker /* set dummy window parameters */
829*e5436536SAndroid Build Coastguard Worker pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
830*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape =
831*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape
832*e5436536SAndroid Build Coastguard Worker (required for F/T transform) */
833*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence =
834*e5436536SAndroid Build Coastguard Worker CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
835*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->windowSequence =
836*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence; /* Store for next frame
837*e5436536SAndroid Build Coastguard Worker (spectrum in concealment
838*e5436536SAndroid Build Coastguard Worker buffer can't be used at
839*e5436536SAndroid Build Coastguard Worker all) */
840*e5436536SAndroid Build Coastguard Worker
841*e5436536SAndroid Build Coastguard Worker /* mute spectral data */
842*e5436536SAndroid Build Coastguard Worker FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
843*e5436536SAndroid Build Coastguard Worker FDKmemclear(pConcealmentInfo->spectralCoefficient,
844*e5436536SAndroid Build Coastguard Worker samplesPerFrame * sizeof(FIXP_DBL));
845*e5436536SAndroid Build Coastguard Worker
846*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
847*e5436536SAndroid Build Coastguard Worker } break;
848*e5436536SAndroid Build Coastguard Worker
849*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeIn: {
850*e5436536SAndroid Build Coastguard Worker /* TimeDomainFading: */
851*e5436536SAndroid Build Coastguard Worker /* Attenuation of signal is done in CConcealment_TDFading() */
852*e5436536SAndroid Build Coastguard Worker
853*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
854*e5436536SAndroid Build Coastguard Worker } break;
855*e5436536SAndroid Build Coastguard Worker
856*e5436536SAndroid Build Coastguard Worker default:
857*e5436536SAndroid Build Coastguard Worker /* we shouldn't come here anyway */
858*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(0);
859*e5436536SAndroid Build Coastguard Worker break;
860*e5436536SAndroid Build Coastguard Worker }
861*e5436536SAndroid Build Coastguard Worker
862*e5436536SAndroid Build Coastguard Worker return appliedProcessing;
863*e5436536SAndroid Build Coastguard Worker }
864*e5436536SAndroid Build Coastguard Worker
865*e5436536SAndroid Build Coastguard Worker /*!
866*e5436536SAndroid Build Coastguard Worker \brief Apply concealment interpolation
867*e5436536SAndroid Build Coastguard Worker
868*e5436536SAndroid Build Coastguard Worker The function swaps the data from the current and the previous frame. If an
869*e5436536SAndroid Build Coastguard Worker error has occured, frame interpolation is performed to restore the missing
870*e5436536SAndroid Build Coastguard Worker frame. In case of multiple faulty frames, fade-in and fade-out is applied.
871*e5436536SAndroid Build Coastguard Worker */
CConcealment_ApplyInter(CConcealmentInfo * pConcealmentInfo,CAacDecoderChannelInfo * pAacDecoderChannelInfo,const SamplingRateInfo * pSamplingRateInfo,const int samplesPerFrame,const int improveTonal,const int frameOk,const int mute_release_active)872*e5436536SAndroid Build Coastguard Worker static int CConcealment_ApplyInter(
873*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *pConcealmentInfo,
874*e5436536SAndroid Build Coastguard Worker CAacDecoderChannelInfo *pAacDecoderChannelInfo,
875*e5436536SAndroid Build Coastguard Worker const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
876*e5436536SAndroid Build Coastguard Worker const int improveTonal, const int frameOk, const int mute_release_active) {
877*e5436536SAndroid Build Coastguard Worker #if defined(FDK_ASSERT_ENABLE)
878*e5436536SAndroid Build Coastguard Worker CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
879*e5436536SAndroid Build Coastguard Worker #endif
880*e5436536SAndroid Build Coastguard Worker
881*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pSpectralCoefficient =
882*e5436536SAndroid Build Coastguard Worker SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
883*e5436536SAndroid Build Coastguard Worker CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
884*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
885*e5436536SAndroid Build Coastguard Worker
886*e5436536SAndroid Build Coastguard Worker int sfbEnergyPrev[64];
887*e5436536SAndroid Build Coastguard Worker int sfbEnergyAct[64];
888*e5436536SAndroid Build Coastguard Worker
889*e5436536SAndroid Build Coastguard Worker int i, appliedProcessing = 0;
890*e5436536SAndroid Build Coastguard Worker
891*e5436536SAndroid Build Coastguard Worker /* clear/init */
892*e5436536SAndroid Build Coastguard Worker FDKmemclear(sfbEnergyPrev, 64 * sizeof(int));
893*e5436536SAndroid Build Coastguard Worker FDKmemclear(sfbEnergyAct, 64 * sizeof(int));
894*e5436536SAndroid Build Coastguard Worker
895*e5436536SAndroid Build Coastguard Worker if (!frameOk || mute_release_active) {
896*e5436536SAndroid Build Coastguard Worker /* Restore last frame from concealment buffer */
897*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
898*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
899*e5436536SAndroid Build Coastguard Worker
900*e5436536SAndroid Build Coastguard Worker /* Restore spectral data */
901*e5436536SAndroid Build Coastguard Worker for (i = 0; i < samplesPerFrame; i++) {
902*e5436536SAndroid Build Coastguard Worker pSpectralCoefficient[i] =
903*e5436536SAndroid Build Coastguard Worker FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]);
904*e5436536SAndroid Build Coastguard Worker }
905*e5436536SAndroid Build Coastguard Worker
906*e5436536SAndroid Build Coastguard Worker /* Restore scale factors */
907*e5436536SAndroid Build Coastguard Worker FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8 * sizeof(SHORT));
908*e5436536SAndroid Build Coastguard Worker }
909*e5436536SAndroid Build Coastguard Worker
910*e5436536SAndroid Build Coastguard Worker /* if previous frame was not ok */
911*e5436536SAndroid Build Coastguard Worker if (!pConcealmentInfo->prevFrameOk[1] || mute_release_active) {
912*e5436536SAndroid Build Coastguard Worker /* if current frame (f_n) is ok and the last but one frame (f_(n-2))
913*e5436536SAndroid Build Coastguard Worker was ok, too, then interpolate both frames in order to generate
914*e5436536SAndroid Build Coastguard Worker the current output frame (f_(n-1)). Otherwise, use the last stored
915*e5436536SAndroid Build Coastguard Worker frame (f_(n-2) or f_(n-3) or ...). */
916*e5436536SAndroid Build Coastguard Worker if (frameOk && pConcealmentInfo->prevFrameOk[0] && !mute_release_active) {
917*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
918*e5436536SAndroid Build Coastguard Worker
919*e5436536SAndroid Build Coastguard Worker /* Interpolate both frames in order to generate the current output frame
920*e5436536SAndroid Build Coastguard Worker * (f_(n-1)). */
921*e5436536SAndroid Build Coastguard Worker if (pIcsInfo->WindowSequence == BLOCK_SHORT) {
922*e5436536SAndroid Build Coastguard Worker /* f_(n-2) == BLOCK_SHORT */
923*e5436536SAndroid Build Coastguard Worker /* short--??????--short, short--??????--long interpolation */
924*e5436536SAndroid Build Coastguard Worker /* short--short---short, short---long---long interpolation */
925*e5436536SAndroid Build Coastguard Worker
926*e5436536SAndroid Build Coastguard Worker int wnd;
927*e5436536SAndroid Build Coastguard Worker
928*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->windowSequence ==
929*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT) { /* f_n == BLOCK_SHORT */
930*e5436536SAndroid Build Coastguard Worker /* short--short---short interpolation */
931*e5436536SAndroid Build Coastguard Worker
932*e5436536SAndroid Build Coastguard Worker int scaleFactorBandsTotal =
933*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo->NumberOfScaleFactorBands_Short;
934*e5436536SAndroid Build Coastguard Worker const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
935*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1;
936*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = BLOCK_SHORT;
937*e5436536SAndroid Build Coastguard Worker
938*e5436536SAndroid Build Coastguard Worker for (wnd = 0; wnd < 8; wnd++) {
939*e5436536SAndroid Build Coastguard Worker CConcealment_CalcBandEnergy(
940*e5436536SAndroid Build Coastguard Worker &pSpectralCoefficient[wnd *
941*e5436536SAndroid Build Coastguard Worker (samplesPerFrame / 8)], /* spec_(n-2) */
942*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand,
943*e5436536SAndroid Build Coastguard Worker sfbEnergyPrev);
944*e5436536SAndroid Build Coastguard Worker
945*e5436536SAndroid Build Coastguard Worker CConcealment_CalcBandEnergy(
946*e5436536SAndroid Build Coastguard Worker &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame /
947*e5436536SAndroid Build Coastguard Worker 8)], /* spec_n */
948*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand,
949*e5436536SAndroid Build Coastguard Worker sfbEnergyAct);
950*e5436536SAndroid Build Coastguard Worker
951*e5436536SAndroid Build Coastguard Worker CConcealment_InterpolateBuffer(
952*e5436536SAndroid Build Coastguard Worker &pSpectralCoefficient[wnd *
953*e5436536SAndroid Build Coastguard Worker (samplesPerFrame / 8)], /* spec_(n-1) */
954*e5436536SAndroid Build Coastguard Worker &pSpecScale[wnd], &pConcealmentInfo->specScale[wnd],
955*e5436536SAndroid Build Coastguard Worker &pSpecScale[wnd], sfbEnergyPrev, sfbEnergyAct,
956*e5436536SAndroid Build Coastguard Worker scaleFactorBandsTotal, pSfbOffset);
957*e5436536SAndroid Build Coastguard Worker }
958*e5436536SAndroid Build Coastguard Worker } else { /* f_n != BLOCK_SHORT */
959*e5436536SAndroid Build Coastguard Worker /* short---long---long interpolation */
960*e5436536SAndroid Build Coastguard Worker
961*e5436536SAndroid Build Coastguard Worker int scaleFactorBandsTotal =
962*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo->NumberOfScaleFactorBands_Long;
963*e5436536SAndroid Build Coastguard Worker const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
964*e5436536SAndroid Build Coastguard Worker SHORT specScaleOut;
965*e5436536SAndroid Build Coastguard Worker
966*e5436536SAndroid Build Coastguard Worker CConcealment_CalcBandEnergy(
967*e5436536SAndroid Build Coastguard Worker &pSpectralCoefficient[samplesPerFrame -
968*e5436536SAndroid Build Coastguard Worker (samplesPerFrame /
969*e5436536SAndroid Build Coastguard Worker 8)], /* [wnd] spec_(n-2) */
970*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand,
971*e5436536SAndroid Build Coastguard Worker sfbEnergyAct);
972*e5436536SAndroid Build Coastguard Worker
973*e5436536SAndroid Build Coastguard Worker CConcealment_CalcBandEnergy(
974*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->spectralCoefficient, /* spec_n */
975*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand,
976*e5436536SAndroid Build Coastguard Worker sfbEnergyPrev);
977*e5436536SAndroid Build Coastguard Worker
978*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = 0;
979*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = BLOCK_STOP;
980*e5436536SAndroid Build Coastguard Worker
981*e5436536SAndroid Build Coastguard Worker for (i = 0; i < samplesPerFrame; i++) {
982*e5436536SAndroid Build Coastguard Worker pSpectralCoefficient[i] =
983*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->spectralCoefficient[i]; /* spec_n */
984*e5436536SAndroid Build Coastguard Worker }
985*e5436536SAndroid Build Coastguard Worker
986*e5436536SAndroid Build Coastguard Worker for (i = 0; i < 8; i++) { /* search for max(specScale) */
987*e5436536SAndroid Build Coastguard Worker if (pSpecScale[i] > pSpecScale[0]) {
988*e5436536SAndroid Build Coastguard Worker pSpecScale[0] = pSpecScale[i];
989*e5436536SAndroid Build Coastguard Worker }
990*e5436536SAndroid Build Coastguard Worker }
991*e5436536SAndroid Build Coastguard Worker
992*e5436536SAndroid Build Coastguard Worker CConcealment_InterpolateBuffer(
993*e5436536SAndroid Build Coastguard Worker pSpectralCoefficient, /* spec_(n-1) */
994*e5436536SAndroid Build Coastguard Worker &pConcealmentInfo->specScale[0], &pSpecScale[0], &specScaleOut,
995*e5436536SAndroid Build Coastguard Worker sfbEnergyPrev, sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset);
996*e5436536SAndroid Build Coastguard Worker
997*e5436536SAndroid Build Coastguard Worker pSpecScale[0] = specScaleOut;
998*e5436536SAndroid Build Coastguard Worker }
999*e5436536SAndroid Build Coastguard Worker } else {
1000*e5436536SAndroid Build Coastguard Worker /* long--??????--short, long--??????--long interpolation */
1001*e5436536SAndroid Build Coastguard Worker /* long---long---short, long---long---long interpolation */
1002*e5436536SAndroid Build Coastguard Worker
1003*e5436536SAndroid Build Coastguard Worker int scaleFactorBandsTotal =
1004*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1005*e5436536SAndroid Build Coastguard Worker const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1006*e5436536SAndroid Build Coastguard Worker SHORT specScaleAct = pConcealmentInfo->specScale[0];
1007*e5436536SAndroid Build Coastguard Worker
1008*e5436536SAndroid Build Coastguard Worker CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */
1009*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo, BLOCK_LONG,
1010*e5436536SAndroid Build Coastguard Worker CConcealment_NoExpand, sfbEnergyPrev);
1011*e5436536SAndroid Build Coastguard Worker
1012*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->windowSequence ==
1013*e5436536SAndroid Build Coastguard Worker BLOCK_SHORT) { /* f_n == BLOCK_SHORT */
1014*e5436536SAndroid Build Coastguard Worker /* long---long---short interpolation */
1015*e5436536SAndroid Build Coastguard Worker
1016*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1;
1017*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = BLOCK_START;
1018*e5436536SAndroid Build Coastguard Worker
1019*e5436536SAndroid Build Coastguard Worker for (i = 1; i < 8; i++) { /* search for max(specScale) */
1020*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->specScale[i] > specScaleAct) {
1021*e5436536SAndroid Build Coastguard Worker specScaleAct = pConcealmentInfo->specScale[i];
1022*e5436536SAndroid Build Coastguard Worker }
1023*e5436536SAndroid Build Coastguard Worker }
1024*e5436536SAndroid Build Coastguard Worker
1025*e5436536SAndroid Build Coastguard Worker /* Expand first short spectrum */
1026*e5436536SAndroid Build Coastguard Worker CConcealment_CalcBandEnergy(
1027*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->spectralCoefficient, /* spec_n */
1028*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, /* !!! */
1029*e5436536SAndroid Build Coastguard Worker sfbEnergyAct);
1030*e5436536SAndroid Build Coastguard Worker } else {
1031*e5436536SAndroid Build Coastguard Worker /* long---long---long interpolation */
1032*e5436536SAndroid Build Coastguard Worker
1033*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = 0;
1034*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = BLOCK_LONG;
1035*e5436536SAndroid Build Coastguard Worker
1036*e5436536SAndroid Build Coastguard Worker CConcealment_CalcBandEnergy(
1037*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->spectralCoefficient, /* spec_n */
1038*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand,
1039*e5436536SAndroid Build Coastguard Worker sfbEnergyAct);
1040*e5436536SAndroid Build Coastguard Worker }
1041*e5436536SAndroid Build Coastguard Worker
1042*e5436536SAndroid Build Coastguard Worker CConcealment_InterpolateBuffer(
1043*e5436536SAndroid Build Coastguard Worker pSpectralCoefficient, /* spec_(n-1) */
1044*e5436536SAndroid Build Coastguard Worker &pSpecScale[0], &specScaleAct, &pSpecScale[0], sfbEnergyPrev,
1045*e5436536SAndroid Build Coastguard Worker sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset);
1046*e5436536SAndroid Build Coastguard Worker }
1047*e5436536SAndroid Build Coastguard Worker }
1048*e5436536SAndroid Build Coastguard Worker
1049*e5436536SAndroid Build Coastguard Worker /* Noise substitution of sign of the output spectral coefficients */
1050*e5436536SAndroid Build Coastguard Worker CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase,
1051*e5436536SAndroid Build Coastguard Worker pSpectralCoefficient, samplesPerFrame);
1052*e5436536SAndroid Build Coastguard Worker /* Increment random phase index to avoid repetition artifacts. */
1053*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->iRandomPhase =
1054*e5436536SAndroid Build Coastguard Worker (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
1055*e5436536SAndroid Build Coastguard Worker }
1056*e5436536SAndroid Build Coastguard Worker
1057*e5436536SAndroid Build Coastguard Worker /* scale spectrum according to concealment state */
1058*e5436536SAndroid Build Coastguard Worker switch (pConcealmentInfo->concealState) {
1059*e5436536SAndroid Build Coastguard Worker case ConcealState_Single:
1060*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
1061*e5436536SAndroid Build Coastguard Worker break;
1062*e5436536SAndroid Build Coastguard Worker
1063*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeOut: {
1064*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
1065*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1066*e5436536SAndroid Build Coastguard Worker CONCEAL_MAX_NUM_FADE_FACTORS);
1067*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1068*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeOutFrames);
1069*e5436536SAndroid Build Coastguard Worker
1070*e5436536SAndroid Build Coastguard Worker /* TimeDomainFading: */
1071*e5436536SAndroid Build Coastguard Worker /* Attenuation of signal is done in CConcealment_TDFading() */
1072*e5436536SAndroid Build Coastguard Worker
1073*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
1074*e5436536SAndroid Build Coastguard Worker } break;
1075*e5436536SAndroid Build Coastguard Worker
1076*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeIn: {
1077*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
1078*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1079*e5436536SAndroid Build Coastguard Worker CONCEAL_MAX_NUM_FADE_FACTORS);
1080*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1081*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeInFrames);
1082*e5436536SAndroid Build Coastguard Worker
1083*e5436536SAndroid Build Coastguard Worker /* TimeDomainFading: */
1084*e5436536SAndroid Build Coastguard Worker /* Attenuation of signal is done in CConcealment_TDFading() */
1085*e5436536SAndroid Build Coastguard Worker
1086*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
1087*e5436536SAndroid Build Coastguard Worker } break;
1088*e5436536SAndroid Build Coastguard Worker
1089*e5436536SAndroid Build Coastguard Worker case ConcealState_Mute: {
1090*e5436536SAndroid Build Coastguard Worker /* set dummy window parameters */
1091*e5436536SAndroid Build Coastguard Worker pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
1092*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape =
1093*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape
1094*e5436536SAndroid Build Coastguard Worker (required for F/T transform) */
1095*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence =
1096*e5436536SAndroid Build Coastguard Worker CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
1097*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->windowSequence =
1098*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence; /* Store for next frame
1099*e5436536SAndroid Build Coastguard Worker (spectrum in concealment
1100*e5436536SAndroid Build Coastguard Worker buffer can't be used at
1101*e5436536SAndroid Build Coastguard Worker all) */
1102*e5436536SAndroid Build Coastguard Worker
1103*e5436536SAndroid Build Coastguard Worker /* mute spectral data */
1104*e5436536SAndroid Build Coastguard Worker FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
1105*e5436536SAndroid Build Coastguard Worker
1106*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
1107*e5436536SAndroid Build Coastguard Worker } break;
1108*e5436536SAndroid Build Coastguard Worker
1109*e5436536SAndroid Build Coastguard Worker default:
1110*e5436536SAndroid Build Coastguard Worker /* nothing to do here */
1111*e5436536SAndroid Build Coastguard Worker break;
1112*e5436536SAndroid Build Coastguard Worker }
1113*e5436536SAndroid Build Coastguard Worker
1114*e5436536SAndroid Build Coastguard Worker return appliedProcessing;
1115*e5436536SAndroid Build Coastguard Worker }
1116*e5436536SAndroid Build Coastguard Worker
1117*e5436536SAndroid Build Coastguard Worker /*!
1118*e5436536SAndroid Build Coastguard Worker \brief Calculate the spectral energy
1119*e5436536SAndroid Build Coastguard Worker
1120*e5436536SAndroid Build Coastguard Worker The function calculates band-wise the spectral energy. This is used for
1121*e5436536SAndroid Build Coastguard Worker frame interpolation.
1122*e5436536SAndroid Build Coastguard Worker */
CConcealment_CalcBandEnergy(FIXP_DBL * spectrum,const SamplingRateInfo * pSamplingRateInfo,const int blockType,CConcealmentExpandType expandType,int * sfbEnergy)1123*e5436536SAndroid Build Coastguard Worker static void CConcealment_CalcBandEnergy(
1124*e5436536SAndroid Build Coastguard Worker FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo,
1125*e5436536SAndroid Build Coastguard Worker const int blockType, CConcealmentExpandType expandType, int *sfbEnergy) {
1126*e5436536SAndroid Build Coastguard Worker const SHORT *pSfbOffset;
1127*e5436536SAndroid Build Coastguard Worker int line, sfb, scaleFactorBandsTotal = 0;
1128*e5436536SAndroid Build Coastguard Worker
1129*e5436536SAndroid Build Coastguard Worker /* In the following calculations, enAccu is initialized with LSB-value in
1130*e5436536SAndroid Build Coastguard Worker * order to avoid zero energy-level */
1131*e5436536SAndroid Build Coastguard Worker
1132*e5436536SAndroid Build Coastguard Worker line = 0;
1133*e5436536SAndroid Build Coastguard Worker
1134*e5436536SAndroid Build Coastguard Worker switch (blockType) {
1135*e5436536SAndroid Build Coastguard Worker case BLOCK_LONG:
1136*e5436536SAndroid Build Coastguard Worker case BLOCK_START:
1137*e5436536SAndroid Build Coastguard Worker case BLOCK_STOP:
1138*e5436536SAndroid Build Coastguard Worker
1139*e5436536SAndroid Build Coastguard Worker if (expandType == CConcealment_NoExpand) {
1140*e5436536SAndroid Build Coastguard Worker /* standard long calculation */
1141*e5436536SAndroid Build Coastguard Worker scaleFactorBandsTotal =
1142*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1143*e5436536SAndroid Build Coastguard Worker pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1144*e5436536SAndroid Build Coastguard Worker
1145*e5436536SAndroid Build Coastguard Worker for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1146*e5436536SAndroid Build Coastguard Worker FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1147*e5436536SAndroid Build Coastguard Worker int sfbScale =
1148*e5436536SAndroid Build Coastguard Worker (sizeof(LONG) << 3) -
1149*e5436536SAndroid Build Coastguard Worker CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1150*e5436536SAndroid Build Coastguard Worker /* scaling depends on sfb width. */
1151*e5436536SAndroid Build Coastguard Worker for (; line < pSfbOffset[sfb + 1]; line++) {
1152*e5436536SAndroid Build Coastguard Worker enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
1153*e5436536SAndroid Build Coastguard Worker }
1154*e5436536SAndroid Build Coastguard Worker *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1155*e5436536SAndroid Build Coastguard Worker }
1156*e5436536SAndroid Build Coastguard Worker } else {
1157*e5436536SAndroid Build Coastguard Worker /* compress long to short */
1158*e5436536SAndroid Build Coastguard Worker scaleFactorBandsTotal =
1159*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo->NumberOfScaleFactorBands_Short;
1160*e5436536SAndroid Build Coastguard Worker pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
1161*e5436536SAndroid Build Coastguard Worker
1162*e5436536SAndroid Build Coastguard Worker for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1163*e5436536SAndroid Build Coastguard Worker FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1164*e5436536SAndroid Build Coastguard Worker int sfbScale =
1165*e5436536SAndroid Build Coastguard Worker (sizeof(LONG) << 3) -
1166*e5436536SAndroid Build Coastguard Worker CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1167*e5436536SAndroid Build Coastguard Worker /* scaling depends on sfb width. */
1168*e5436536SAndroid Build Coastguard Worker for (; line < pSfbOffset[sfb + 1] << 3; line++) {
1169*e5436536SAndroid Build Coastguard Worker enAccu +=
1170*e5436536SAndroid Build Coastguard Worker (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3;
1171*e5436536SAndroid Build Coastguard Worker }
1172*e5436536SAndroid Build Coastguard Worker *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1173*e5436536SAndroid Build Coastguard Worker }
1174*e5436536SAndroid Build Coastguard Worker }
1175*e5436536SAndroid Build Coastguard Worker break;
1176*e5436536SAndroid Build Coastguard Worker
1177*e5436536SAndroid Build Coastguard Worker case BLOCK_SHORT:
1178*e5436536SAndroid Build Coastguard Worker
1179*e5436536SAndroid Build Coastguard Worker if (expandType == CConcealment_NoExpand) {
1180*e5436536SAndroid Build Coastguard Worker /* standard short calculation */
1181*e5436536SAndroid Build Coastguard Worker scaleFactorBandsTotal =
1182*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo->NumberOfScaleFactorBands_Short;
1183*e5436536SAndroid Build Coastguard Worker pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
1184*e5436536SAndroid Build Coastguard Worker
1185*e5436536SAndroid Build Coastguard Worker for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1186*e5436536SAndroid Build Coastguard Worker FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1187*e5436536SAndroid Build Coastguard Worker int sfbScale =
1188*e5436536SAndroid Build Coastguard Worker (sizeof(LONG) << 3) -
1189*e5436536SAndroid Build Coastguard Worker CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1190*e5436536SAndroid Build Coastguard Worker /* scaling depends on sfb width. */
1191*e5436536SAndroid Build Coastguard Worker for (; line < pSfbOffset[sfb + 1]; line++) {
1192*e5436536SAndroid Build Coastguard Worker enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
1193*e5436536SAndroid Build Coastguard Worker }
1194*e5436536SAndroid Build Coastguard Worker *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1195*e5436536SAndroid Build Coastguard Worker }
1196*e5436536SAndroid Build Coastguard Worker } else {
1197*e5436536SAndroid Build Coastguard Worker /* expand short to long spectrum */
1198*e5436536SAndroid Build Coastguard Worker scaleFactorBandsTotal =
1199*e5436536SAndroid Build Coastguard Worker pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1200*e5436536SAndroid Build Coastguard Worker pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1201*e5436536SAndroid Build Coastguard Worker
1202*e5436536SAndroid Build Coastguard Worker for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1203*e5436536SAndroid Build Coastguard Worker FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1204*e5436536SAndroid Build Coastguard Worker int sfbScale =
1205*e5436536SAndroid Build Coastguard Worker (sizeof(LONG) << 3) -
1206*e5436536SAndroid Build Coastguard Worker CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1207*e5436536SAndroid Build Coastguard Worker /* scaling depends on sfb width. */
1208*e5436536SAndroid Build Coastguard Worker for (; line < pSfbOffset[sfb + 1]; line++) {
1209*e5436536SAndroid Build Coastguard Worker enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale;
1210*e5436536SAndroid Build Coastguard Worker }
1211*e5436536SAndroid Build Coastguard Worker *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1212*e5436536SAndroid Build Coastguard Worker }
1213*e5436536SAndroid Build Coastguard Worker }
1214*e5436536SAndroid Build Coastguard Worker break;
1215*e5436536SAndroid Build Coastguard Worker }
1216*e5436536SAndroid Build Coastguard Worker }
1217*e5436536SAndroid Build Coastguard Worker
1218*e5436536SAndroid Build Coastguard Worker /*!
1219*e5436536SAndroid Build Coastguard Worker \brief Interpolate buffer
1220*e5436536SAndroid Build Coastguard Worker
1221*e5436536SAndroid Build Coastguard Worker The function creates the interpolated spectral data according to the
1222*e5436536SAndroid Build Coastguard Worker energy of the last good frame and the current (good) frame.
1223*e5436536SAndroid Build Coastguard Worker */
CConcealment_InterpolateBuffer(FIXP_DBL * spectrum,SHORT * pSpecScalePrv,SHORT * pSpecScaleAct,SHORT * pSpecScaleOut,int * enPrv,int * enAct,int sfbCnt,const SHORT * pSfbOffset)1224*e5436536SAndroid Build Coastguard Worker static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum,
1225*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScalePrv,
1226*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScaleAct,
1227*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScaleOut, int *enPrv,
1228*e5436536SAndroid Build Coastguard Worker int *enAct, int sfbCnt,
1229*e5436536SAndroid Build Coastguard Worker const SHORT *pSfbOffset) {
1230*e5436536SAndroid Build Coastguard Worker int sfb, line = 0;
1231*e5436536SAndroid Build Coastguard Worker int fac_shift;
1232*e5436536SAndroid Build Coastguard Worker int fac_mod;
1233*e5436536SAndroid Build Coastguard Worker
1234*e5436536SAndroid Build Coastguard Worker for (sfb = 0; sfb < sfbCnt; sfb++) {
1235*e5436536SAndroid Build Coastguard Worker fac_shift =
1236*e5436536SAndroid Build Coastguard Worker enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1);
1237*e5436536SAndroid Build Coastguard Worker fac_mod = fac_shift & 3;
1238*e5436536SAndroid Build Coastguard Worker fac_shift = (fac_shift >> 2) + 1;
1239*e5436536SAndroid Build Coastguard Worker fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct);
1240*e5436536SAndroid Build Coastguard Worker fac_shift = fMax(fMin(fac_shift, DFRACT_BITS - 1), -(DFRACT_BITS - 1));
1241*e5436536SAndroid Build Coastguard Worker
1242*e5436536SAndroid Build Coastguard Worker for (; line < pSfbOffset[sfb + 1]; line++) {
1243*e5436536SAndroid Build Coastguard Worker FIXP_DBL accu = fMult(*(spectrum + line), facMod4Table[fac_mod]);
1244*e5436536SAndroid Build Coastguard Worker *(spectrum + line) = scaleValue(accu, fac_shift);
1245*e5436536SAndroid Build Coastguard Worker }
1246*e5436536SAndroid Build Coastguard Worker }
1247*e5436536SAndroid Build Coastguard Worker *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct);
1248*e5436536SAndroid Build Coastguard Worker }
1249*e5436536SAndroid Build Coastguard Worker
1250*e5436536SAndroid Build Coastguard Worker /*!
1251*e5436536SAndroid Build Coastguard Worker \brief Find next fading frame in case of changing fading direction
1252*e5436536SAndroid Build Coastguard Worker
1253*e5436536SAndroid Build Coastguard Worker \param pConcealCommonData Pointer to the concealment common data structure.
1254*e5436536SAndroid Build Coastguard Worker \param actFadeIndex Last index used for fading
1255*e5436536SAndroid Build Coastguard Worker \param direction Direction of change: 0 : change from FADE-OUT to FADE-IN, 1
1256*e5436536SAndroid Build Coastguard Worker : change from FADE-IN to FADE-OUT
1257*e5436536SAndroid Build Coastguard Worker
1258*e5436536SAndroid Build Coastguard Worker This function determines the next fading index to be used for the fading
1259*e5436536SAndroid Build Coastguard Worker direction to be changed to.
1260*e5436536SAndroid Build Coastguard Worker */
1261*e5436536SAndroid Build Coastguard Worker
findEquiFadeFrame(CConcealParams * pConcealCommonData,INT actFadeIndex,int direction)1262*e5436536SAndroid Build Coastguard Worker static INT findEquiFadeFrame(CConcealParams *pConcealCommonData,
1263*e5436536SAndroid Build Coastguard Worker INT actFadeIndex, int direction) {
1264*e5436536SAndroid Build Coastguard Worker FIXP_SGL *pFactor;
1265*e5436536SAndroid Build Coastguard Worker FIXP_SGL referenceVal;
1266*e5436536SAndroid Build Coastguard Worker FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL;
1267*e5436536SAndroid Build Coastguard Worker
1268*e5436536SAndroid Build Coastguard Worker INT nextFadeIndex = 0;
1269*e5436536SAndroid Build Coastguard Worker
1270*e5436536SAndroid Build Coastguard Worker int i;
1271*e5436536SAndroid Build Coastguard Worker
1272*e5436536SAndroid Build Coastguard Worker /* init depending on direction */
1273*e5436536SAndroid Build Coastguard Worker if (direction == 0) { /* FADE-OUT => FADE-IN */
1274*e5436536SAndroid Build Coastguard Worker if (actFadeIndex < 0) {
1275*e5436536SAndroid Build Coastguard Worker referenceVal = (FIXP_SGL)MAXVAL_SGL;
1276*e5436536SAndroid Build Coastguard Worker } else {
1277*e5436536SAndroid Build Coastguard Worker referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1;
1278*e5436536SAndroid Build Coastguard Worker }
1279*e5436536SAndroid Build Coastguard Worker pFactor = pConcealCommonData->fadeInFactor;
1280*e5436536SAndroid Build Coastguard Worker } else { /* FADE-IN => FADE-OUT */
1281*e5436536SAndroid Build Coastguard Worker if (actFadeIndex < 0) {
1282*e5436536SAndroid Build Coastguard Worker referenceVal = (FIXP_SGL)MAXVAL_SGL;
1283*e5436536SAndroid Build Coastguard Worker } else {
1284*e5436536SAndroid Build Coastguard Worker referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1;
1285*e5436536SAndroid Build Coastguard Worker }
1286*e5436536SAndroid Build Coastguard Worker pFactor = pConcealCommonData->fadeOutFactor;
1287*e5436536SAndroid Build Coastguard Worker }
1288*e5436536SAndroid Build Coastguard Worker
1289*e5436536SAndroid Build Coastguard Worker /* search for minimum difference */
1290*e5436536SAndroid Build Coastguard Worker for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
1291*e5436536SAndroid Build Coastguard Worker FIXP_SGL diff = fixp_abs((pFactor[i] >> 1) - referenceVal);
1292*e5436536SAndroid Build Coastguard Worker if (diff < minDiff) {
1293*e5436536SAndroid Build Coastguard Worker minDiff = diff;
1294*e5436536SAndroid Build Coastguard Worker nextFadeIndex = i;
1295*e5436536SAndroid Build Coastguard Worker }
1296*e5436536SAndroid Build Coastguard Worker }
1297*e5436536SAndroid Build Coastguard Worker
1298*e5436536SAndroid Build Coastguard Worker /* check and adjust depending on direction */
1299*e5436536SAndroid Build Coastguard Worker if (direction == 0) { /* FADE-OUT => FADE-IN */
1300*e5436536SAndroid Build Coastguard Worker if (nextFadeIndex > pConcealCommonData->numFadeInFrames) {
1301*e5436536SAndroid Build Coastguard Worker nextFadeIndex = fMax(pConcealCommonData->numFadeInFrames - 1, 0);
1302*e5436536SAndroid Build Coastguard Worker }
1303*e5436536SAndroid Build Coastguard Worker if (((pFactor[nextFadeIndex] >> 1) <= referenceVal) &&
1304*e5436536SAndroid Build Coastguard Worker (nextFadeIndex > 0)) {
1305*e5436536SAndroid Build Coastguard Worker nextFadeIndex -= 1;
1306*e5436536SAndroid Build Coastguard Worker }
1307*e5436536SAndroid Build Coastguard Worker } else { /* FADE-IN => FADE-OUT */
1308*e5436536SAndroid Build Coastguard Worker if (((pFactor[nextFadeIndex] >> 1) >= referenceVal) &&
1309*e5436536SAndroid Build Coastguard Worker (nextFadeIndex < CONCEAL_MAX_NUM_FADE_FACTORS - 1)) {
1310*e5436536SAndroid Build Coastguard Worker nextFadeIndex += 1;
1311*e5436536SAndroid Build Coastguard Worker }
1312*e5436536SAndroid Build Coastguard Worker }
1313*e5436536SAndroid Build Coastguard Worker
1314*e5436536SAndroid Build Coastguard Worker return (nextFadeIndex);
1315*e5436536SAndroid Build Coastguard Worker }
1316*e5436536SAndroid Build Coastguard Worker
1317*e5436536SAndroid Build Coastguard Worker /*!
1318*e5436536SAndroid Build Coastguard Worker \brief Update the concealment state
1319*e5436536SAndroid Build Coastguard Worker
1320*e5436536SAndroid Build Coastguard Worker The function updates the state of the concealment state-machine. The
1321*e5436536SAndroid Build Coastguard Worker states are: mute, fade-in, fade-out, interpolate and frame-ok.
1322*e5436536SAndroid Build Coastguard Worker */
CConcealment_UpdateState(CConcealmentInfo * pConcealmentInfo,int frameOk,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,const int samplesPerFrame,CAacDecoderChannelInfo * pAacDecoderChannelInfo)1323*e5436536SAndroid Build Coastguard Worker static void CConcealment_UpdateState(
1324*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *pConcealmentInfo, int frameOk,
1325*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
1326*e5436536SAndroid Build Coastguard Worker const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) {
1327*e5436536SAndroid Build Coastguard Worker CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
1328*e5436536SAndroid Build Coastguard Worker
1329*e5436536SAndroid Build Coastguard Worker switch (pConcealCommonData->method) {
1330*e5436536SAndroid Build Coastguard Worker case ConcealMethodNoise: {
1331*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->concealState != ConcealState_Ok) {
1332*e5436536SAndroid Build Coastguard Worker /* count the valid frames during concealment process */
1333*e5436536SAndroid Build Coastguard Worker if (frameOk) {
1334*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntValidFrames += 1;
1335*e5436536SAndroid Build Coastguard Worker } else {
1336*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntValidFrames = 0;
1337*e5436536SAndroid Build Coastguard Worker }
1338*e5436536SAndroid Build Coastguard Worker }
1339*e5436536SAndroid Build Coastguard Worker
1340*e5436536SAndroid Build Coastguard Worker /* -- STATE MACHINE for Noise Substitution -- */
1341*e5436536SAndroid Build Coastguard Worker switch (pConcealmentInfo->concealState) {
1342*e5436536SAndroid Build Coastguard Worker case ConcealState_Ok:
1343*e5436536SAndroid Build Coastguard Worker if (!frameOk) {
1344*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames = 0;
1345*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntValidFrames = 0;
1346*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[0] = 0;
1347*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[1] = 0;
1348*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[0] = 0;
1349*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[1] = 0;
1350*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeOutFrames > 0) {
1351*e5436536SAndroid Build Coastguard Worker /* change to state SINGLE-FRAME-LOSS */
1352*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Single;
1353*e5436536SAndroid Build Coastguard Worker /* mode 0 just updates the Fading counter */
1354*e5436536SAndroid Build Coastguard Worker CConcealment_ApplyFadeOut(
1355*e5436536SAndroid Build Coastguard Worker /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1356*e5436536SAndroid Build Coastguard Worker samplesPerFrame, pAacDecoderChannelInfo);
1357*e5436536SAndroid Build Coastguard Worker
1358*e5436536SAndroid Build Coastguard Worker } else {
1359*e5436536SAndroid Build Coastguard Worker /* change to state MUTE */
1360*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Mute;
1361*e5436536SAndroid Build Coastguard Worker }
1362*e5436536SAndroid Build Coastguard Worker }
1363*e5436536SAndroid Build Coastguard Worker break;
1364*e5436536SAndroid Build Coastguard Worker
1365*e5436536SAndroid Build Coastguard Worker case ConcealState_Single: /* Just a pre-stage before fade-out begins.
1366*e5436536SAndroid Build Coastguard Worker Stay here only one frame! */
1367*e5436536SAndroid Build Coastguard Worker if (frameOk) {
1368*e5436536SAndroid Build Coastguard Worker /* change to state OK */
1369*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1370*e5436536SAndroid Build Coastguard Worker } else {
1371*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntFadeFrames >=
1372*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeOutFrames) {
1373*e5436536SAndroid Build Coastguard Worker /* change to state MUTE */
1374*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Mute;
1375*e5436536SAndroid Build Coastguard Worker } else {
1376*e5436536SAndroid Build Coastguard Worker /* change to state FADE-OUT */
1377*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeOut;
1378*e5436536SAndroid Build Coastguard Worker /* mode 0 just updates the Fading counter */
1379*e5436536SAndroid Build Coastguard Worker CConcealment_ApplyFadeOut(
1380*e5436536SAndroid Build Coastguard Worker /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1381*e5436536SAndroid Build Coastguard Worker samplesPerFrame, pAacDecoderChannelInfo);
1382*e5436536SAndroid Build Coastguard Worker }
1383*e5436536SAndroid Build Coastguard Worker }
1384*e5436536SAndroid Build Coastguard Worker break;
1385*e5436536SAndroid Build Coastguard Worker
1386*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeOut:
1387*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntValidFrames >
1388*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numMuteReleaseFrames) {
1389*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeInFrames > 0) {
1390*e5436536SAndroid Build Coastguard Worker /* change to state FADE-IN */
1391*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeIn;
1392*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1393*e5436536SAndroid Build Coastguard Worker pConcealCommonData, pConcealmentInfo->cntFadeFrames,
1394*e5436536SAndroid Build Coastguard Worker 0 /* FadeOut -> FadeIn */);
1395*e5436536SAndroid Build Coastguard Worker } else {
1396*e5436536SAndroid Build Coastguard Worker /* change to state OK */
1397*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1398*e5436536SAndroid Build Coastguard Worker }
1399*e5436536SAndroid Build Coastguard Worker } else {
1400*e5436536SAndroid Build Coastguard Worker if (frameOk) {
1401*e5436536SAndroid Build Coastguard Worker /* we have good frame information but stay fully in concealment -
1402*e5436536SAndroid Build Coastguard Worker * reset winGrpOffset/attGrpOffset */
1403*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[0] = 0;
1404*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[1] = 0;
1405*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[0] = 0;
1406*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[1] = 0;
1407*e5436536SAndroid Build Coastguard Worker }
1408*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntFadeFrames >=
1409*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeOutFrames) {
1410*e5436536SAndroid Build Coastguard Worker /* change to state MUTE */
1411*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Mute;
1412*e5436536SAndroid Build Coastguard Worker } else /* Stay in FADE-OUT */
1413*e5436536SAndroid Build Coastguard Worker {
1414*e5436536SAndroid Build Coastguard Worker /* mode 0 just updates the Fading counter */
1415*e5436536SAndroid Build Coastguard Worker CConcealment_ApplyFadeOut(
1416*e5436536SAndroid Build Coastguard Worker /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1417*e5436536SAndroid Build Coastguard Worker samplesPerFrame, pAacDecoderChannelInfo);
1418*e5436536SAndroid Build Coastguard Worker }
1419*e5436536SAndroid Build Coastguard Worker }
1420*e5436536SAndroid Build Coastguard Worker break;
1421*e5436536SAndroid Build Coastguard Worker
1422*e5436536SAndroid Build Coastguard Worker case ConcealState_Mute:
1423*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntValidFrames >
1424*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numMuteReleaseFrames) {
1425*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeInFrames > 0) {
1426*e5436536SAndroid Build Coastguard Worker /* change to state FADE-IN */
1427*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeIn;
1428*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames =
1429*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeInFrames - 1;
1430*e5436536SAndroid Build Coastguard Worker } else {
1431*e5436536SAndroid Build Coastguard Worker /* change to state OK */
1432*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1433*e5436536SAndroid Build Coastguard Worker }
1434*e5436536SAndroid Build Coastguard Worker } else {
1435*e5436536SAndroid Build Coastguard Worker if (frameOk) {
1436*e5436536SAndroid Build Coastguard Worker /* we have good frame information but stay fully in concealment -
1437*e5436536SAndroid Build Coastguard Worker * reset winGrpOffset/attGrpOffset */
1438*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[0] = 0;
1439*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[1] = 0;
1440*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[0] = 0;
1441*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[1] = 0;
1442*e5436536SAndroid Build Coastguard Worker }
1443*e5436536SAndroid Build Coastguard Worker }
1444*e5436536SAndroid Build Coastguard Worker break;
1445*e5436536SAndroid Build Coastguard Worker
1446*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeIn:
1447*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames -= 1;
1448*e5436536SAndroid Build Coastguard Worker if (frameOk) {
1449*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntFadeFrames < 0) {
1450*e5436536SAndroid Build Coastguard Worker /* change to state OK */
1451*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1452*e5436536SAndroid Build Coastguard Worker }
1453*e5436536SAndroid Build Coastguard Worker } else {
1454*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeOutFrames > 0) {
1455*e5436536SAndroid Build Coastguard Worker /* change to state FADE-OUT */
1456*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeOut;
1457*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1458*e5436536SAndroid Build Coastguard Worker pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1,
1459*e5436536SAndroid Build Coastguard Worker 1 /* FadeIn -> FadeOut */);
1460*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[0] = 0;
1461*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[1] = 0;
1462*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[0] = 0;
1463*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[1] = 0;
1464*e5436536SAndroid Build Coastguard Worker
1465*e5436536SAndroid Build Coastguard Worker pConcealmentInfo
1466*e5436536SAndroid Build Coastguard Worker ->cntFadeFrames--; /* decrease because
1467*e5436536SAndroid Build Coastguard Worker CConcealment_ApplyFadeOut() will
1468*e5436536SAndroid Build Coastguard Worker increase, accordingly */
1469*e5436536SAndroid Build Coastguard Worker /* mode 0 just updates the Fading counter */
1470*e5436536SAndroid Build Coastguard Worker CConcealment_ApplyFadeOut(
1471*e5436536SAndroid Build Coastguard Worker /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1472*e5436536SAndroid Build Coastguard Worker samplesPerFrame, pAacDecoderChannelInfo);
1473*e5436536SAndroid Build Coastguard Worker } else {
1474*e5436536SAndroid Build Coastguard Worker /* change to state MUTE */
1475*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Mute;
1476*e5436536SAndroid Build Coastguard Worker }
1477*e5436536SAndroid Build Coastguard Worker }
1478*e5436536SAndroid Build Coastguard Worker break;
1479*e5436536SAndroid Build Coastguard Worker
1480*e5436536SAndroid Build Coastguard Worker default:
1481*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(0);
1482*e5436536SAndroid Build Coastguard Worker break;
1483*e5436536SAndroid Build Coastguard Worker }
1484*e5436536SAndroid Build Coastguard Worker } break;
1485*e5436536SAndroid Build Coastguard Worker
1486*e5436536SAndroid Build Coastguard Worker case ConcealMethodInter:
1487*e5436536SAndroid Build Coastguard Worker case ConcealMethodTonal: {
1488*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->concealState != ConcealState_Ok) {
1489*e5436536SAndroid Build Coastguard Worker /* count the valid frames during concealment process */
1490*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->prevFrameOk[1] ||
1491*e5436536SAndroid Build Coastguard Worker (pConcealmentInfo->prevFrameOk[0] &&
1492*e5436536SAndroid Build Coastguard Worker !pConcealmentInfo->prevFrameOk[1] && frameOk)) {
1493*e5436536SAndroid Build Coastguard Worker /* The frame is OK even if it can be estimated by the energy
1494*e5436536SAndroid Build Coastguard Worker * interpolation algorithm */
1495*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntValidFrames += 1;
1496*e5436536SAndroid Build Coastguard Worker } else {
1497*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntValidFrames = 0;
1498*e5436536SAndroid Build Coastguard Worker }
1499*e5436536SAndroid Build Coastguard Worker }
1500*e5436536SAndroid Build Coastguard Worker
1501*e5436536SAndroid Build Coastguard Worker /* -- STATE MACHINE for energy interpolation -- */
1502*e5436536SAndroid Build Coastguard Worker switch (pConcealmentInfo->concealState) {
1503*e5436536SAndroid Build Coastguard Worker case ConcealState_Ok:
1504*e5436536SAndroid Build Coastguard Worker if (!(pConcealmentInfo->prevFrameOk[1] ||
1505*e5436536SAndroid Build Coastguard Worker (pConcealmentInfo->prevFrameOk[0] &&
1506*e5436536SAndroid Build Coastguard Worker !pConcealmentInfo->prevFrameOk[1] && frameOk))) {
1507*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeOutFrames > 0) {
1508*e5436536SAndroid Build Coastguard Worker /* Fade out only if the energy interpolation algorithm can not be
1509*e5436536SAndroid Build Coastguard Worker * applied! */
1510*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeOut;
1511*e5436536SAndroid Build Coastguard Worker } else {
1512*e5436536SAndroid Build Coastguard Worker /* change to state MUTE */
1513*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Mute;
1514*e5436536SAndroid Build Coastguard Worker }
1515*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames = 0;
1516*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntValidFrames = 0;
1517*e5436536SAndroid Build Coastguard Worker }
1518*e5436536SAndroid Build Coastguard Worker break;
1519*e5436536SAndroid Build Coastguard Worker
1520*e5436536SAndroid Build Coastguard Worker case ConcealState_Single:
1521*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1522*e5436536SAndroid Build Coastguard Worker break;
1523*e5436536SAndroid Build Coastguard Worker
1524*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeOut:
1525*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames += 1;
1526*e5436536SAndroid Build Coastguard Worker
1527*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntValidFrames >
1528*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numMuteReleaseFrames) {
1529*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeInFrames > 0) {
1530*e5436536SAndroid Build Coastguard Worker /* change to state FADE-IN */
1531*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeIn;
1532*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1533*e5436536SAndroid Build Coastguard Worker pConcealCommonData, pConcealmentInfo->cntFadeFrames - 1,
1534*e5436536SAndroid Build Coastguard Worker 0 /* FadeOut -> FadeIn */);
1535*e5436536SAndroid Build Coastguard Worker } else {
1536*e5436536SAndroid Build Coastguard Worker /* change to state OK */
1537*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1538*e5436536SAndroid Build Coastguard Worker }
1539*e5436536SAndroid Build Coastguard Worker } else {
1540*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntFadeFrames >=
1541*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeOutFrames) {
1542*e5436536SAndroid Build Coastguard Worker /* change to state MUTE */
1543*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Mute;
1544*e5436536SAndroid Build Coastguard Worker }
1545*e5436536SAndroid Build Coastguard Worker }
1546*e5436536SAndroid Build Coastguard Worker break;
1547*e5436536SAndroid Build Coastguard Worker
1548*e5436536SAndroid Build Coastguard Worker case ConcealState_Mute:
1549*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntValidFrames >
1550*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numMuteReleaseFrames) {
1551*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeInFrames > 0) {
1552*e5436536SAndroid Build Coastguard Worker /* change to state FADE-IN */
1553*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeIn;
1554*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames =
1555*e5436536SAndroid Build Coastguard Worker pConcealCommonData->numFadeInFrames - 1;
1556*e5436536SAndroid Build Coastguard Worker } else {
1557*e5436536SAndroid Build Coastguard Worker /* change to state OK */
1558*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1559*e5436536SAndroid Build Coastguard Worker }
1560*e5436536SAndroid Build Coastguard Worker }
1561*e5436536SAndroid Build Coastguard Worker break;
1562*e5436536SAndroid Build Coastguard Worker
1563*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeIn:
1564*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames -=
1565*e5436536SAndroid Build Coastguard Worker 1; /* used to address the fade-in factors */
1566*e5436536SAndroid Build Coastguard Worker
1567*e5436536SAndroid Build Coastguard Worker if (frameOk || pConcealmentInfo->prevFrameOk[1]) {
1568*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->cntFadeFrames < 0) {
1569*e5436536SAndroid Build Coastguard Worker /* change to state OK */
1570*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Ok;
1571*e5436536SAndroid Build Coastguard Worker }
1572*e5436536SAndroid Build Coastguard Worker } else {
1573*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData->numFadeOutFrames > 0) {
1574*e5436536SAndroid Build Coastguard Worker /* change to state FADE-OUT */
1575*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_FadeOut;
1576*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1577*e5436536SAndroid Build Coastguard Worker pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1,
1578*e5436536SAndroid Build Coastguard Worker 1 /* FadeIn -> FadeOut */);
1579*e5436536SAndroid Build Coastguard Worker } else {
1580*e5436536SAndroid Build Coastguard Worker /* change to state MUTE */
1581*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState = ConcealState_Mute;
1582*e5436536SAndroid Build Coastguard Worker }
1583*e5436536SAndroid Build Coastguard Worker }
1584*e5436536SAndroid Build Coastguard Worker break;
1585*e5436536SAndroid Build Coastguard Worker } /* End switch(pConcealmentInfo->concealState) */
1586*e5436536SAndroid Build Coastguard Worker } break;
1587*e5436536SAndroid Build Coastguard Worker
1588*e5436536SAndroid Build Coastguard Worker default:
1589*e5436536SAndroid Build Coastguard Worker /* Don't need a state machine for other concealment methods. */
1590*e5436536SAndroid Build Coastguard Worker break;
1591*e5436536SAndroid Build Coastguard Worker }
1592*e5436536SAndroid Build Coastguard Worker }
1593*e5436536SAndroid Build Coastguard Worker
1594*e5436536SAndroid Build Coastguard Worker /*!
1595*e5436536SAndroid Build Coastguard Worker \brief Randomizes the sign of the spectral data
1596*e5436536SAndroid Build Coastguard Worker
1597*e5436536SAndroid Build Coastguard Worker The function toggles the sign of the spectral data randomly. This is
1598*e5436536SAndroid Build Coastguard Worker useful to ensure the quality of the concealed frames.
1599*e5436536SAndroid Build Coastguard Worker */
CConcealment_ApplyRandomSign(int randomPhase,FIXP_DBL * spec,int samplesPerFrame)1600*e5436536SAndroid Build Coastguard Worker static void CConcealment_ApplyRandomSign(int randomPhase, FIXP_DBL *spec,
1601*e5436536SAndroid Build Coastguard Worker int samplesPerFrame) {
1602*e5436536SAndroid Build Coastguard Worker int i;
1603*e5436536SAndroid Build Coastguard Worker USHORT packedSign = 0;
1604*e5436536SAndroid Build Coastguard Worker
1605*e5436536SAndroid Build Coastguard Worker /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit
1606*e5436536SAndroid Build Coastguard Worker */
1607*e5436536SAndroid Build Coastguard Worker
1608*e5436536SAndroid Build Coastguard Worker /* read current packed sign word */
1609*e5436536SAndroid Build Coastguard Worker packedSign = AacDec_randomSign[randomPhase >> 4];
1610*e5436536SAndroid Build Coastguard Worker packedSign >>= (randomPhase & 0xf);
1611*e5436536SAndroid Build Coastguard Worker
1612*e5436536SAndroid Build Coastguard Worker for (i = 0; i < samplesPerFrame; i++) {
1613*e5436536SAndroid Build Coastguard Worker if ((randomPhase & 0xf) == 0) {
1614*e5436536SAndroid Build Coastguard Worker packedSign = AacDec_randomSign[randomPhase >> 4];
1615*e5436536SAndroid Build Coastguard Worker }
1616*e5436536SAndroid Build Coastguard Worker
1617*e5436536SAndroid Build Coastguard Worker if (packedSign & 0x1) {
1618*e5436536SAndroid Build Coastguard Worker spec[i] = -fMax(spec[i], (FIXP_DBL)(MINVAL_DBL + 1));
1619*e5436536SAndroid Build Coastguard Worker }
1620*e5436536SAndroid Build Coastguard Worker packedSign >>= 1;
1621*e5436536SAndroid Build Coastguard Worker
1622*e5436536SAndroid Build Coastguard Worker randomPhase = (randomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
1623*e5436536SAndroid Build Coastguard Worker }
1624*e5436536SAndroid Build Coastguard Worker }
1625*e5436536SAndroid Build Coastguard Worker
1626*e5436536SAndroid Build Coastguard Worker /*!
1627*e5436536SAndroid Build Coastguard Worker \brief Get fadeing factor for current concealment state.
1628*e5436536SAndroid Build Coastguard Worker
1629*e5436536SAndroid Build Coastguard Worker The function returns the state (ok or not) of the previous frame.
1630*e5436536SAndroid Build Coastguard Worker If called before the function CConcealment_Apply() set the fBeforeApply
1631*e5436536SAndroid Build Coastguard Worker flag to get the correct value.
1632*e5436536SAndroid Build Coastguard Worker
1633*e5436536SAndroid Build Coastguard Worker \return Frame OK flag of previous frame.
1634*e5436536SAndroid Build Coastguard Worker */
CConcealment_GetLastFrameOk(CConcealmentInfo * hConcealmentInfo,const int fBeforeApply)1635*e5436536SAndroid Build Coastguard Worker int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo,
1636*e5436536SAndroid Build Coastguard Worker const int fBeforeApply) {
1637*e5436536SAndroid Build Coastguard Worker int prevFrameOk = 1;
1638*e5436536SAndroid Build Coastguard Worker
1639*e5436536SAndroid Build Coastguard Worker if (hConcealmentInfo != NULL) {
1640*e5436536SAndroid Build Coastguard Worker prevFrameOk = hConcealmentInfo->prevFrameOk[fBeforeApply & 0x1];
1641*e5436536SAndroid Build Coastguard Worker }
1642*e5436536SAndroid Build Coastguard Worker
1643*e5436536SAndroid Build Coastguard Worker return prevFrameOk;
1644*e5436536SAndroid Build Coastguard Worker }
1645*e5436536SAndroid Build Coastguard Worker
1646*e5436536SAndroid Build Coastguard Worker /*!
1647*e5436536SAndroid Build Coastguard Worker \brief Get the number of delay frames introduced by concealment technique.
1648*e5436536SAndroid Build Coastguard Worker
1649*e5436536SAndroid Build Coastguard Worker \return Number of delay frames.
1650*e5436536SAndroid Build Coastguard Worker */
CConcealment_GetDelay(CConcealParams * pConcealCommonData)1651*e5436536SAndroid Build Coastguard Worker UINT CConcealment_GetDelay(CConcealParams *pConcealCommonData) {
1652*e5436536SAndroid Build Coastguard Worker UINT frameDelay = 0;
1653*e5436536SAndroid Build Coastguard Worker
1654*e5436536SAndroid Build Coastguard Worker if (pConcealCommonData != NULL) {
1655*e5436536SAndroid Build Coastguard Worker switch (pConcealCommonData->method) {
1656*e5436536SAndroid Build Coastguard Worker case ConcealMethodTonal:
1657*e5436536SAndroid Build Coastguard Worker case ConcealMethodInter:
1658*e5436536SAndroid Build Coastguard Worker frameDelay = 1;
1659*e5436536SAndroid Build Coastguard Worker break;
1660*e5436536SAndroid Build Coastguard Worker default:
1661*e5436536SAndroid Build Coastguard Worker break;
1662*e5436536SAndroid Build Coastguard Worker }
1663*e5436536SAndroid Build Coastguard Worker }
1664*e5436536SAndroid Build Coastguard Worker
1665*e5436536SAndroid Build Coastguard Worker return frameDelay;
1666*e5436536SAndroid Build Coastguard Worker }
1667*e5436536SAndroid Build Coastguard Worker
CConcealment_ApplyFadeOut(int mode,CConcealmentInfo * pConcealmentInfo,CAacDecoderStaticChannelInfo * pAacDecoderStaticChannelInfo,const int samplesPerFrame,CAacDecoderChannelInfo * pAacDecoderChannelInfo)1668*e5436536SAndroid Build Coastguard Worker static int CConcealment_ApplyFadeOut(
1669*e5436536SAndroid Build Coastguard Worker int mode, CConcealmentInfo *pConcealmentInfo,
1670*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
1671*e5436536SAndroid Build Coastguard Worker const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) {
1672*e5436536SAndroid Build Coastguard Worker /* mode 1 = apply RandomSign and mute spectral coefficients if necessary, *
1673*e5436536SAndroid Build Coastguard Worker * mode 0 = Update cntFadeFrames */
1674*e5436536SAndroid Build Coastguard Worker
1675*e5436536SAndroid Build Coastguard Worker /* restore frequency coefficients from buffer with a specific muting */
1676*e5436536SAndroid Build Coastguard Worker int srcWin, dstWin, numWindows = 1;
1677*e5436536SAndroid Build Coastguard Worker int windowLen = samplesPerFrame;
1678*e5436536SAndroid Build Coastguard Worker int srcGrpStart = 0;
1679*e5436536SAndroid Build Coastguard Worker int winIdxStride = 1;
1680*e5436536SAndroid Build Coastguard Worker int numWinGrpPerFac, attIdx, attIdxStride;
1681*e5436536SAndroid Build Coastguard Worker int i;
1682*e5436536SAndroid Build Coastguard Worker int appliedProcessing = 0;
1683*e5436536SAndroid Build Coastguard Worker
1684*e5436536SAndroid Build Coastguard Worker CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
1685*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pSpectralCoefficient =
1686*e5436536SAndroid Build Coastguard Worker SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
1687*e5436536SAndroid Build Coastguard Worker SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
1688*e5436536SAndroid Build Coastguard Worker
1689*e5436536SAndroid Build Coastguard Worker /* set old window parameters */
1690*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->lastRenderMode == AACDEC_RENDER_LPD) {
1691*e5436536SAndroid Build Coastguard Worker switch (pAacDecoderStaticChannelInfo->last_lpd_mode) {
1692*e5436536SAndroid Build Coastguard Worker case 1:
1693*e5436536SAndroid Build Coastguard Worker numWindows = 4;
1694*e5436536SAndroid Build Coastguard Worker srcGrpStart = 3;
1695*e5436536SAndroid Build Coastguard Worker windowLen = samplesPerFrame >> 2;
1696*e5436536SAndroid Build Coastguard Worker break;
1697*e5436536SAndroid Build Coastguard Worker case 2:
1698*e5436536SAndroid Build Coastguard Worker numWindows = 2;
1699*e5436536SAndroid Build Coastguard Worker srcGrpStart = 1;
1700*e5436536SAndroid Build Coastguard Worker windowLen = samplesPerFrame >> 1;
1701*e5436536SAndroid Build Coastguard Worker winIdxStride = 2;
1702*e5436536SAndroid Build Coastguard Worker break;
1703*e5436536SAndroid Build Coastguard Worker case 3:
1704*e5436536SAndroid Build Coastguard Worker numWindows = 1;
1705*e5436536SAndroid Build Coastguard Worker srcGrpStart = 0;
1706*e5436536SAndroid Build Coastguard Worker windowLen = samplesPerFrame;
1707*e5436536SAndroid Build Coastguard Worker winIdxStride = 4;
1708*e5436536SAndroid Build Coastguard Worker break;
1709*e5436536SAndroid Build Coastguard Worker }
1710*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->lastWinGrpLen = 1;
1711*e5436536SAndroid Build Coastguard Worker } else {
1712*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
1713*e5436536SAndroid Build Coastguard Worker pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
1714*e5436536SAndroid Build Coastguard Worker
1715*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->windowSequence == BLOCK_SHORT) {
1716*e5436536SAndroid Build Coastguard Worker /* short block handling */
1717*e5436536SAndroid Build Coastguard Worker numWindows = 8;
1718*e5436536SAndroid Build Coastguard Worker windowLen = samplesPerFrame >> 3;
1719*e5436536SAndroid Build Coastguard Worker srcGrpStart = numWindows - pConcealmentInfo->lastWinGrpLen;
1720*e5436536SAndroid Build Coastguard Worker }
1721*e5436536SAndroid Build Coastguard Worker }
1722*e5436536SAndroid Build Coastguard Worker
1723*e5436536SAndroid Build Coastguard Worker attIdxStride =
1724*e5436536SAndroid Build Coastguard Worker fMax(1, (int)(numWindows / (pConcealmentInfo->lastWinGrpLen + 1)));
1725*e5436536SAndroid Build Coastguard Worker
1726*e5436536SAndroid Build Coastguard Worker /* load last state */
1727*e5436536SAndroid Build Coastguard Worker attIdx = pConcealmentInfo->cntFadeFrames;
1728*e5436536SAndroid Build Coastguard Worker numWinGrpPerFac = pConcealmentInfo->attGrpOffset[mode];
1729*e5436536SAndroid Build Coastguard Worker srcWin = srcGrpStart + pConcealmentInfo->winGrpOffset[mode];
1730*e5436536SAndroid Build Coastguard Worker
1731*e5436536SAndroid Build Coastguard Worker FDK_ASSERT((srcGrpStart * windowLen + windowLen) <= samplesPerFrame);
1732*e5436536SAndroid Build Coastguard Worker FDK_ASSERT((srcWin * windowLen + windowLen) <= 1024);
1733*e5436536SAndroid Build Coastguard Worker
1734*e5436536SAndroid Build Coastguard Worker for (dstWin = 0; dstWin < numWindows; dstWin += 1) {
1735*e5436536SAndroid Build Coastguard Worker FIXP_CNCL *pCncl =
1736*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->spectralCoefficient + (srcWin * windowLen);
1737*e5436536SAndroid Build Coastguard Worker FIXP_DBL *pOut = pSpectralCoefficient + (dstWin * windowLen);
1738*e5436536SAndroid Build Coastguard Worker
1739*e5436536SAndroid Build Coastguard Worker if (mode == 1) {
1740*e5436536SAndroid Build Coastguard Worker /* mute if attIdx gets large enaugh */
1741*e5436536SAndroid Build Coastguard Worker if (attIdx > pConcealmentInfo->pConcealParams->numFadeOutFrames) {
1742*e5436536SAndroid Build Coastguard Worker FDKmemclear(pCncl, sizeof(FIXP_DBL) * windowLen);
1743*e5436536SAndroid Build Coastguard Worker }
1744*e5436536SAndroid Build Coastguard Worker
1745*e5436536SAndroid Build Coastguard Worker /* restore frequency coefficients from buffer - attenuation is done later
1746*e5436536SAndroid Build Coastguard Worker */
1747*e5436536SAndroid Build Coastguard Worker for (i = 0; i < windowLen; i++) {
1748*e5436536SAndroid Build Coastguard Worker pOut[i] = pCncl[i];
1749*e5436536SAndroid Build Coastguard Worker }
1750*e5436536SAndroid Build Coastguard Worker
1751*e5436536SAndroid Build Coastguard Worker /* apply random change of sign for spectral coefficients */
1752*e5436536SAndroid Build Coastguard Worker CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, pOut,
1753*e5436536SAndroid Build Coastguard Worker windowLen);
1754*e5436536SAndroid Build Coastguard Worker
1755*e5436536SAndroid Build Coastguard Worker /* Increment random phase index to avoid repetition artifacts. */
1756*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->iRandomPhase =
1757*e5436536SAndroid Build Coastguard Worker (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
1758*e5436536SAndroid Build Coastguard Worker
1759*e5436536SAndroid Build Coastguard Worker /* set old scale factors */
1760*e5436536SAndroid Build Coastguard Worker pSpecScale[dstWin * winIdxStride] =
1761*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->specScale[srcWin * winIdxStride];
1762*e5436536SAndroid Build Coastguard Worker }
1763*e5436536SAndroid Build Coastguard Worker
1764*e5436536SAndroid Build Coastguard Worker srcWin += 1;
1765*e5436536SAndroid Build Coastguard Worker
1766*e5436536SAndroid Build Coastguard Worker if (srcWin >= numWindows) {
1767*e5436536SAndroid Build Coastguard Worker /* end of sequence -> rewind to first window of group */
1768*e5436536SAndroid Build Coastguard Worker srcWin = srcGrpStart;
1769*e5436536SAndroid Build Coastguard Worker numWinGrpPerFac += 1;
1770*e5436536SAndroid Build Coastguard Worker if (numWinGrpPerFac >= attIdxStride) {
1771*e5436536SAndroid Build Coastguard Worker numWinGrpPerFac = 0;
1772*e5436536SAndroid Build Coastguard Worker attIdx += 1;
1773*e5436536SAndroid Build Coastguard Worker }
1774*e5436536SAndroid Build Coastguard Worker }
1775*e5436536SAndroid Build Coastguard Worker }
1776*e5436536SAndroid Build Coastguard Worker
1777*e5436536SAndroid Build Coastguard Worker /* store current state */
1778*e5436536SAndroid Build Coastguard Worker
1779*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->winGrpOffset[mode] = srcWin - srcGrpStart;
1780*e5436536SAndroid Build Coastguard Worker FDK_ASSERT((pConcealmentInfo->winGrpOffset[mode] >= 0) &&
1781*e5436536SAndroid Build Coastguard Worker (pConcealmentInfo->winGrpOffset[mode] < 8));
1782*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->attGrpOffset[mode] = numWinGrpPerFac;
1783*e5436536SAndroid Build Coastguard Worker FDK_ASSERT((pConcealmentInfo->attGrpOffset[mode] >= 0) &&
1784*e5436536SAndroid Build Coastguard Worker (pConcealmentInfo->attGrpOffset[mode] < attIdxStride));
1785*e5436536SAndroid Build Coastguard Worker
1786*e5436536SAndroid Build Coastguard Worker if (mode == 0) {
1787*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->cntFadeFrames = attIdx;
1788*e5436536SAndroid Build Coastguard Worker }
1789*e5436536SAndroid Build Coastguard Worker
1790*e5436536SAndroid Build Coastguard Worker appliedProcessing = 1;
1791*e5436536SAndroid Build Coastguard Worker
1792*e5436536SAndroid Build Coastguard Worker return appliedProcessing;
1793*e5436536SAndroid Build Coastguard Worker }
1794*e5436536SAndroid Build Coastguard Worker
1795*e5436536SAndroid Build Coastguard Worker /*!
1796*e5436536SAndroid Build Coastguard Worker \brief Do Time domain fading (TDFading) in concealment case
1797*e5436536SAndroid Build Coastguard Worker
1798*e5436536SAndroid Build Coastguard Worker In case of concealment, this function takes care of the fading, after time
1799*e5436536SAndroid Build Coastguard Worker domain signal has been rendered by the respective signal rendering functions.
1800*e5436536SAndroid Build Coastguard Worker The fading out in case of ACELP decoding is not done by this function but by
1801*e5436536SAndroid Build Coastguard Worker the ACELP decoder for the first concealed frame if CONCEAL_CORE_IGNORANT_FADE is
1802*e5436536SAndroid Build Coastguard Worker not set.
1803*e5436536SAndroid Build Coastguard Worker
1804*e5436536SAndroid Build Coastguard Worker TimeDomain fading never creates jumps in energy / discontinuities, it always
1805*e5436536SAndroid Build Coastguard Worker does a continuous fading. To achieve this, fading is always done from a starting
1806*e5436536SAndroid Build Coastguard Worker point to a target point, while the starting point is always determined to be the
1807*e5436536SAndroid Build Coastguard Worker last target point. By varying the target point of a fading, the fading slope can
1808*e5436536SAndroid Build Coastguard Worker be controlled.
1809*e5436536SAndroid Build Coastguard Worker
1810*e5436536SAndroid Build Coastguard Worker This principle is applied to the fading within a frame and the fading from
1811*e5436536SAndroid Build Coastguard Worker frame to frame.
1812*e5436536SAndroid Build Coastguard Worker
1813*e5436536SAndroid Build Coastguard Worker One frame is divided into 8 subframes to obtain 8 parts of fading slopes
1814*e5436536SAndroid Build Coastguard Worker within a frame, each maybe with its own gradient.
1815*e5436536SAndroid Build Coastguard Worker
1816*e5436536SAndroid Build Coastguard Worker Workflow:
1817*e5436536SAndroid Build Coastguard Worker 1.) Determine Fading behavior and end-of-frame target fading level, based on
1818*e5436536SAndroid Build Coastguard Worker concealmentState (determined by CConcealment_UpdateState()) and the core mode.
1819*e5436536SAndroid Build Coastguard Worker - By _DEFAULT_,
1820*e5436536SAndroid Build Coastguard Worker The target fading level is determined by fadeOutFactor[cntFadeFrames]
1821*e5436536SAndroid Build Coastguard Worker in case of fadeOut, or fadeInFactor[cntFadeFrames] in case of fadeIn.
1822*e5436536SAndroid Build Coastguard Worker --> fading type is FADE_TIMEDOMAIN in this case. Target fading level
1823*e5436536SAndroid Build Coastguard Worker is determined by fading index cntFadeFrames.
1824*e5436536SAndroid Build Coastguard Worker
1825*e5436536SAndroid Build Coastguard Worker - If concealmentState is signalling a _MUTED SIGNAL_,
1826*e5436536SAndroid Build Coastguard Worker TDFading decays to 0 within 1/8th of a frame if numFadeOutFrames == 0.
1827*e5436536SAndroid Build Coastguard Worker --> fading type is FADE_TIMEDOMAIN_TOSPECTRALMUTE in this case.
1828*e5436536SAndroid Build Coastguard Worker
1829*e5436536SAndroid Build Coastguard Worker - If concealmentState is signalling the _END OF MUTING_,
1830*e5436536SAndroid Build Coastguard Worker TDFading fades to target fading level within 1/8th of a frame if
1831*e5436536SAndroid Build Coastguard Worker numFadeInFrames == 0.
1832*e5436536SAndroid Build Coastguard Worker --> fading type is FADE_TIMEDOMAIN_FROMSPECTRALMUTE in this case.
1833*e5436536SAndroid Build Coastguard Worker Target fading level is determined by fading index cntFadeFrames.
1834*e5436536SAndroid Build Coastguard Worker
1835*e5436536SAndroid Build Coastguard Worker #ifndef CONCEAL_CORE_IGNORANT_FADE
1836*e5436536SAndroid Build Coastguard Worker - In case of an _ACELP FADEOUT_,
1837*e5436536SAndroid Build Coastguard Worker TDFading leaves fading control to ACELP decoder for 1/2 frame.
1838*e5436536SAndroid Build Coastguard Worker --> fading type is FADE_ACELPDOMAIN in this case.
1839*e5436536SAndroid Build Coastguard Worker #endif
1840*e5436536SAndroid Build Coastguard Worker
1841*e5436536SAndroid Build Coastguard Worker 2.) Render fading levels within current frame and do the final fading:
1842*e5436536SAndroid Build Coastguard Worker Map Fading slopes to fading levels and apply to time domain signal.
1843*e5436536SAndroid Build Coastguard Worker
1844*e5436536SAndroid Build Coastguard Worker
1845*e5436536SAndroid Build Coastguard Worker */
1846*e5436536SAndroid Build Coastguard Worker
CConcealment_TDFading(int len,CAacDecoderStaticChannelInfo ** ppAacDecoderStaticChannelInfo,const INT aacOutDataHeadroom,PCM_DEC * pcmdata,PCM_DEC * pcmdata_1)1847*e5436536SAndroid Build Coastguard Worker INT CConcealment_TDFading(
1848*e5436536SAndroid Build Coastguard Worker int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo,
1849*e5436536SAndroid Build Coastguard Worker const INT aacOutDataHeadroom, PCM_DEC *pcmdata, PCM_DEC *pcmdata_1) {
1850*e5436536SAndroid Build Coastguard Worker /*
1851*e5436536SAndroid Build Coastguard Worker Do the fading in Time domain based on concealment states and core mode
1852*e5436536SAndroid Build Coastguard Worker */
1853*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadeStop, attMute = (FIXP_DBL)0;
1854*e5436536SAndroid Build Coastguard Worker int idx = 0, ii;
1855*e5436536SAndroid Build Coastguard Worker CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo =
1856*e5436536SAndroid Build Coastguard Worker *ppAacDecoderStaticChannelInfo;
1857*e5436536SAndroid Build Coastguard Worker CConcealmentInfo *pConcealmentInfo =
1858*e5436536SAndroid Build Coastguard Worker &pAacDecoderStaticChannelInfo->concealmentInfo;
1859*e5436536SAndroid Build Coastguard Worker CConcealParams *pConcealParams = pConcealmentInfo->pConcealParams;
1860*e5436536SAndroid Build Coastguard Worker const CConcealmentState concealState = pConcealmentInfo->concealState;
1861*e5436536SAndroid Build Coastguard Worker TDfadingType fadingType;
1862*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadingStations[9] = {0};
1863*e5436536SAndroid Build Coastguard Worker int fadingSteps[8] = {0};
1864*e5436536SAndroid Build Coastguard Worker const FIXP_DBL fadeStart =
1865*e5436536SAndroid Build Coastguard Worker pConcealmentInfo
1866*e5436536SAndroid Build Coastguard Worker ->fade_old; /* start fading at last end-of-frame attenuation */
1867*e5436536SAndroid Build Coastguard Worker FIXP_SGL *fadeFactor = pConcealParams->fadeOutFactor;
1868*e5436536SAndroid Build Coastguard Worker const INT cntFadeFrames = pConcealmentInfo->cntFadeFrames;
1869*e5436536SAndroid Build Coastguard Worker int TDFadeOutStopBeforeMute = 1;
1870*e5436536SAndroid Build Coastguard Worker int TDFadeInStopBeforeFullLevel = 1;
1871*e5436536SAndroid Build Coastguard Worker
1872*e5436536SAndroid Build Coastguard Worker /*
1873*e5436536SAndroid Build Coastguard Worker determine Fading behaviour (end-of-frame attenuation and fading type) (1.)
1874*e5436536SAndroid Build Coastguard Worker */
1875*e5436536SAndroid Build Coastguard Worker
1876*e5436536SAndroid Build Coastguard Worker switch (concealState) {
1877*e5436536SAndroid Build Coastguard Worker case ConcealState_Single:
1878*e5436536SAndroid Build Coastguard Worker case ConcealState_Mute:
1879*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeOut:
1880*e5436536SAndroid Build Coastguard Worker idx = (pConcealParams->method == ConcealMethodNoise) ? cntFadeFrames - 1
1881*e5436536SAndroid Build Coastguard Worker : cntFadeFrames;
1882*e5436536SAndroid Build Coastguard Worker fadingType = FADE_TIMEDOMAIN;
1883*e5436536SAndroid Build Coastguard Worker
1884*e5436536SAndroid Build Coastguard Worker if (concealState == ConcealState_Mute ||
1885*e5436536SAndroid Build Coastguard Worker (cntFadeFrames + TDFadeOutStopBeforeMute) >
1886*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->pConcealParams->numFadeOutFrames) {
1887*e5436536SAndroid Build Coastguard Worker fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE;
1888*e5436536SAndroid Build Coastguard Worker }
1889*e5436536SAndroid Build Coastguard Worker
1890*e5436536SAndroid Build Coastguard Worker break;
1891*e5436536SAndroid Build Coastguard Worker case ConcealState_FadeIn:
1892*e5436536SAndroid Build Coastguard Worker idx = cntFadeFrames;
1893*e5436536SAndroid Build Coastguard Worker idx -= TDFadeInStopBeforeFullLevel;
1894*e5436536SAndroid Build Coastguard Worker FDK_FALLTHROUGH;
1895*e5436536SAndroid Build Coastguard Worker case ConcealState_Ok:
1896*e5436536SAndroid Build Coastguard Worker fadeFactor = pConcealParams->fadeInFactor;
1897*e5436536SAndroid Build Coastguard Worker idx = (concealState == ConcealState_Ok) ? -1 : idx;
1898*e5436536SAndroid Build Coastguard Worker fadingType = (pConcealmentInfo->concealState_old == ConcealState_Mute)
1899*e5436536SAndroid Build Coastguard Worker ? FADE_TIMEDOMAIN_FROMSPECTRALMUTE
1900*e5436536SAndroid Build Coastguard Worker : FADE_TIMEDOMAIN;
1901*e5436536SAndroid Build Coastguard Worker break;
1902*e5436536SAndroid Build Coastguard Worker default:
1903*e5436536SAndroid Build Coastguard Worker FDK_ASSERT(0);
1904*e5436536SAndroid Build Coastguard Worker fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE;
1905*e5436536SAndroid Build Coastguard Worker break;
1906*e5436536SAndroid Build Coastguard Worker }
1907*e5436536SAndroid Build Coastguard Worker
1908*e5436536SAndroid Build Coastguard Worker /* determine Target end-of-frame fading level and fading slope */
1909*e5436536SAndroid Build Coastguard Worker switch (fadingType) {
1910*e5436536SAndroid Build Coastguard Worker case FADE_TIMEDOMAIN_FROMSPECTRALMUTE:
1911*e5436536SAndroid Build Coastguard Worker fadeStop =
1912*e5436536SAndroid Build Coastguard Worker (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]);
1913*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->pConcealParams->numFadeInFrames == 0) {
1914*e5436536SAndroid Build Coastguard Worker /* do step as fast as possible */
1915*e5436536SAndroid Build Coastguard Worker fadingSteps[0] = 1;
1916*e5436536SAndroid Build Coastguard Worker break;
1917*e5436536SAndroid Build Coastguard Worker }
1918*e5436536SAndroid Build Coastguard Worker CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]);
1919*e5436536SAndroid Build Coastguard Worker break;
1920*e5436536SAndroid Build Coastguard Worker case FADE_TIMEDOMAIN:
1921*e5436536SAndroid Build Coastguard Worker fadeStop =
1922*e5436536SAndroid Build Coastguard Worker (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]);
1923*e5436536SAndroid Build Coastguard Worker CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]);
1924*e5436536SAndroid Build Coastguard Worker break;
1925*e5436536SAndroid Build Coastguard Worker case FADE_TIMEDOMAIN_TOSPECTRALMUTE:
1926*e5436536SAndroid Build Coastguard Worker fadeStop = attMute;
1927*e5436536SAndroid Build Coastguard Worker if (pConcealmentInfo->pConcealParams->numFadeOutFrames == 0) {
1928*e5436536SAndroid Build Coastguard Worker /* do step as fast as possible */
1929*e5436536SAndroid Build Coastguard Worker fadingSteps[0] = 1;
1930*e5436536SAndroid Build Coastguard Worker break;
1931*e5436536SAndroid Build Coastguard Worker }
1932*e5436536SAndroid Build Coastguard Worker CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]);
1933*e5436536SAndroid Build Coastguard Worker break;
1934*e5436536SAndroid Build Coastguard Worker }
1935*e5436536SAndroid Build Coastguard Worker
1936*e5436536SAndroid Build Coastguard Worker /*
1937*e5436536SAndroid Build Coastguard Worker Render fading levels within current frame and do the final fading (2.)
1938*e5436536SAndroid Build Coastguard Worker */
1939*e5436536SAndroid Build Coastguard Worker
1940*e5436536SAndroid Build Coastguard Worker len >>= 3;
1941*e5436536SAndroid Build Coastguard Worker CConcealment_TDFadeFillFadingStations(fadingStations, fadingSteps, fadeStop,
1942*e5436536SAndroid Build Coastguard Worker fadeStart, fadingType);
1943*e5436536SAndroid Build Coastguard Worker
1944*e5436536SAndroid Build Coastguard Worker if ((fadingStations[8] != (FIXP_DBL)MAXVAL_DBL) ||
1945*e5436536SAndroid Build Coastguard Worker (fadingStations[7] != (FIXP_DBL)MAXVAL_DBL) ||
1946*e5436536SAndroid Build Coastguard Worker (fadingStations[6] != (FIXP_DBL)MAXVAL_DBL) ||
1947*e5436536SAndroid Build Coastguard Worker (fadingStations[5] != (FIXP_DBL)MAXVAL_DBL) ||
1948*e5436536SAndroid Build Coastguard Worker (fadingStations[4] != (FIXP_DBL)MAXVAL_DBL) ||
1949*e5436536SAndroid Build Coastguard Worker (fadingStations[3] != (FIXP_DBL)MAXVAL_DBL) ||
1950*e5436536SAndroid Build Coastguard Worker (fadingStations[2] != (FIXP_DBL)MAXVAL_DBL) ||
1951*e5436536SAndroid Build Coastguard Worker (fadingStations[1] != (FIXP_DBL)MAXVAL_DBL) ||
1952*e5436536SAndroid Build Coastguard Worker (fadingStations[0] !=
1953*e5436536SAndroid Build Coastguard Worker (FIXP_DBL)MAXVAL_DBL)) /* if there's something to fade */
1954*e5436536SAndroid Build Coastguard Worker {
1955*e5436536SAndroid Build Coastguard Worker int start = 0;
1956*e5436536SAndroid Build Coastguard Worker for (ii = 0; ii < 8; ii++) {
1957*e5436536SAndroid Build Coastguard Worker CConcealment_TDFadePcmAtt(start, len, fadingStations[ii],
1958*e5436536SAndroid Build Coastguard Worker fadingStations[ii + 1], pcmdata);
1959*e5436536SAndroid Build Coastguard Worker start += len;
1960*e5436536SAndroid Build Coastguard Worker }
1961*e5436536SAndroid Build Coastguard Worker }
1962*e5436536SAndroid Build Coastguard Worker CConcealment_TDNoise_Apply(pConcealmentInfo, len, aacOutDataHeadroom,
1963*e5436536SAndroid Build Coastguard Worker pcmdata);
1964*e5436536SAndroid Build Coastguard Worker
1965*e5436536SAndroid Build Coastguard Worker /* Save end-of-frame attenuation and fading type */
1966*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->lastFadingType = fadingType;
1967*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->fade_old = fadeStop;
1968*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState_old = concealState;
1969*e5436536SAndroid Build Coastguard Worker
1970*e5436536SAndroid Build Coastguard Worker return 1;
1971*e5436536SAndroid Build Coastguard Worker }
1972*e5436536SAndroid Build Coastguard Worker
1973*e5436536SAndroid Build Coastguard Worker /* attenuate pcmdata in Time Domain Fading process */
CConcealment_TDFadePcmAtt(int start,int len,FIXP_DBL fadeStart,FIXP_DBL fadeStop,PCM_DEC * pcmdata)1974*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
1975*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadeStop, PCM_DEC *pcmdata) {
1976*e5436536SAndroid Build Coastguard Worker int i;
1977*e5436536SAndroid Build Coastguard Worker FIXP_DBL dStep;
1978*e5436536SAndroid Build Coastguard Worker FIXP_DBL dGain;
1979*e5436536SAndroid Build Coastguard Worker FIXP_DBL dGain_apply;
1980*e5436536SAndroid Build Coastguard Worker
1981*e5436536SAndroid Build Coastguard Worker /* set start energy */
1982*e5436536SAndroid Build Coastguard Worker dGain = fadeStart;
1983*e5436536SAndroid Build Coastguard Worker /* determine energy steps from sample to sample */
1984*e5436536SAndroid Build Coastguard Worker dStep = (FIXP_DBL)((int)((fadeStart >> 1) - (fadeStop >> 1)) / len) << 1;
1985*e5436536SAndroid Build Coastguard Worker
1986*e5436536SAndroid Build Coastguard Worker for (i = start; i < (start + len); i++) {
1987*e5436536SAndroid Build Coastguard Worker dGain -= dStep;
1988*e5436536SAndroid Build Coastguard Worker /* prevent gain from getting negative due to possible fixpoint inaccuracies
1989*e5436536SAndroid Build Coastguard Worker */
1990*e5436536SAndroid Build Coastguard Worker dGain_apply = fMax((FIXP_DBL)0, dGain);
1991*e5436536SAndroid Build Coastguard Worker /* finally, attenuate samples */
1992*e5436536SAndroid Build Coastguard Worker pcmdata[i] = FIXP_DBL2PCM_DEC(fMult(pcmdata[i], dGain_apply));
1993*e5436536SAndroid Build Coastguard Worker }
1994*e5436536SAndroid Build Coastguard Worker }
1995*e5436536SAndroid Build Coastguard Worker
1996*e5436536SAndroid Build Coastguard Worker /*
1997*e5436536SAndroid Build Coastguard Worker \brief Fill FadingStations
1998*e5436536SAndroid Build Coastguard Worker
1999*e5436536SAndroid Build Coastguard Worker The fadingstations are the attenuation factors, being applied to its dedicated
2000*e5436536SAndroid Build Coastguard Worker portions of pcm data. They are calculated using the fadingsteps. One fadingstep
2001*e5436536SAndroid Build Coastguard Worker is the weighted contribution to the fading slope within its dedicated portion of
2002*e5436536SAndroid Build Coastguard Worker pcm data.
2003*e5436536SAndroid Build Coastguard Worker
2004*e5436536SAndroid Build Coastguard Worker *Fadingsteps : 0 0 0 1 0 1 2 0
2005*e5436536SAndroid Build Coastguard Worker
2006*e5436536SAndroid Build Coastguard Worker |<- 1 Frame pcm data ->|
2007*e5436536SAndroid Build Coastguard Worker fadeStart-->|__________ |
2008*e5436536SAndroid Build Coastguard Worker ^ ^ ^ ^ \____ |
2009*e5436536SAndroid Build Coastguard Worker Attenuation : | | | | ^ ^\__ |
2010*e5436536SAndroid Build Coastguard Worker | | | | | | ^\ |
2011*e5436536SAndroid Build Coastguard Worker | | | | | | | \___|<-- fadeStop
2012*e5436536SAndroid Build Coastguard Worker | | | | | | | ^ ^
2013*e5436536SAndroid Build Coastguard Worker | | | | | | | | |
2014*e5436536SAndroid Build Coastguard Worker Fadingstations: [0][1][2][3][4][5][6][7][8]
2015*e5436536SAndroid Build Coastguard Worker
2016*e5436536SAndroid Build Coastguard Worker (Fadingstations "[0]" is "[8] from previous frame", therefore its not meaningful
2017*e5436536SAndroid Build Coastguard Worker to be edited)
2018*e5436536SAndroid Build Coastguard Worker
2019*e5436536SAndroid Build Coastguard Worker */
CConcealment_TDFadeFillFadingStations(FIXP_DBL * fadingStations,int * fadingSteps,FIXP_DBL fadeStop,FIXP_DBL fadeStart,TDfadingType fadingType)2020*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations,
2021*e5436536SAndroid Build Coastguard Worker int *fadingSteps,
2022*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadeStop,
2023*e5436536SAndroid Build Coastguard Worker FIXP_DBL fadeStart,
2024*e5436536SAndroid Build Coastguard Worker TDfadingType fadingType) {
2025*e5436536SAndroid Build Coastguard Worker int i;
2026*e5436536SAndroid Build Coastguard Worker INT fadingSteps_sum = 0;
2027*e5436536SAndroid Build Coastguard Worker INT fadeDiff;
2028*e5436536SAndroid Build Coastguard Worker
2029*e5436536SAndroid Build Coastguard Worker fadingSteps_sum = fadingSteps[0] + fadingSteps[1] + fadingSteps[2] +
2030*e5436536SAndroid Build Coastguard Worker fadingSteps[3] + fadingSteps[4] + fadingSteps[5] +
2031*e5436536SAndroid Build Coastguard Worker fadingSteps[6] + fadingSteps[7];
2032*e5436536SAndroid Build Coastguard Worker fadeDiff = ((INT)(fadeStop - fadeStart) / fMax(fadingSteps_sum, (INT)1));
2033*e5436536SAndroid Build Coastguard Worker fadingStations[0] = fadeStart;
2034*e5436536SAndroid Build Coastguard Worker for (i = 1; i < 8; i++) {
2035*e5436536SAndroid Build Coastguard Worker fadingStations[i] =
2036*e5436536SAndroid Build Coastguard Worker fadingStations[i - 1] + (FIXP_DBL)(fadeDiff * fadingSteps[i - 1]);
2037*e5436536SAndroid Build Coastguard Worker }
2038*e5436536SAndroid Build Coastguard Worker fadingStations[8] = fadeStop;
2039*e5436536SAndroid Build Coastguard Worker }
2040*e5436536SAndroid Build Coastguard Worker
CConcealment_TDFading_doLinearFadingSteps(int * fadingSteps)2041*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps) {
2042*e5436536SAndroid Build Coastguard Worker fadingSteps[0] = fadingSteps[1] = fadingSteps[2] = fadingSteps[3] =
2043*e5436536SAndroid Build Coastguard Worker fadingSteps[4] = fadingSteps[5] = fadingSteps[6] = fadingSteps[7] = 1;
2044*e5436536SAndroid Build Coastguard Worker }
2045*e5436536SAndroid Build Coastguard Worker
2046*e5436536SAndroid Build Coastguard Worker /* end of TimeDomainFading functions */
2047*e5436536SAndroid Build Coastguard Worker
2048*e5436536SAndroid Build Coastguard Worker /* derived from int UsacRandomSign() */
CConcealment_TDNoise_Random(ULONG * seed)2049*e5436536SAndroid Build Coastguard Worker static int CConcealment_TDNoise_Random(ULONG *seed) {
2050*e5436536SAndroid Build Coastguard Worker *seed = (ULONG)(((UINT64)(*seed) * 69069) + 5);
2051*e5436536SAndroid Build Coastguard Worker return (int)(*seed);
2052*e5436536SAndroid Build Coastguard Worker }
2053*e5436536SAndroid Build Coastguard Worker
CConcealment_TDNoise_Apply(CConcealmentInfo * const pConcealmentInfo,const int len,const INT aacOutDataHeadroom,PCM_DEC * const pcmdata)2054*e5436536SAndroid Build Coastguard Worker static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
2055*e5436536SAndroid Build Coastguard Worker const int len,
2056*e5436536SAndroid Build Coastguard Worker const INT aacOutDataHeadroom,
2057*e5436536SAndroid Build Coastguard Worker PCM_DEC *const pcmdata) {
2058*e5436536SAndroid Build Coastguard Worker PCM_DEC *states = pConcealmentInfo->TDNoiseStates;
2059*e5436536SAndroid Build Coastguard Worker PCM_DEC noiseVal;
2060*e5436536SAndroid Build Coastguard Worker FIXP_DBL noiseValLong;
2061*e5436536SAndroid Build Coastguard Worker FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef;
2062*e5436536SAndroid Build Coastguard Worker FIXP_DBL TDNoiseAtt;
2063*e5436536SAndroid Build Coastguard Worker ULONG seed = pConcealmentInfo->TDNoiseSeed =
2064*e5436536SAndroid Build Coastguard Worker (ULONG)CConcealment_TDNoise_Random(&pConcealmentInfo->TDNoiseSeed) + 1;
2065*e5436536SAndroid Build Coastguard Worker
2066*e5436536SAndroid Build Coastguard Worker TDNoiseAtt = pConcealmentInfo->pConcealParams->comfortNoiseLevel;
2067*e5436536SAndroid Build Coastguard Worker
2068*e5436536SAndroid Build Coastguard Worker int ii;
2069*e5436536SAndroid Build Coastguard Worker
2070*e5436536SAndroid Build Coastguard Worker if ((pConcealmentInfo->concealState != ConcealState_Ok ||
2071*e5436536SAndroid Build Coastguard Worker pConcealmentInfo->concealState_old != ConcealState_Ok) &&
2072*e5436536SAndroid Build Coastguard Worker TDNoiseAtt != (FIXP_DBL)0) {
2073*e5436536SAndroid Build Coastguard Worker for (ii = 0; ii < (len << 3); ii++) {
2074*e5436536SAndroid Build Coastguard Worker /* create filtered noise */
2075*e5436536SAndroid Build Coastguard Worker states[2] = states[1];
2076*e5436536SAndroid Build Coastguard Worker states[1] = states[0];
2077*e5436536SAndroid Build Coastguard Worker states[0] =
2078*e5436536SAndroid Build Coastguard Worker FIXP_DBL2PCM_DEC((FIXP_DBL)CConcealment_TDNoise_Random(&seed));
2079*e5436536SAndroid Build Coastguard Worker noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) +
2080*e5436536SAndroid Build Coastguard Worker fMult(states[2], coef[2]);
2081*e5436536SAndroid Build Coastguard Worker noiseVal = FIXP_DBL2PCM_DEC(fMult(noiseValLong, TDNoiseAtt) >>
2082*e5436536SAndroid Build Coastguard Worker aacOutDataHeadroom);
2083*e5436536SAndroid Build Coastguard Worker
2084*e5436536SAndroid Build Coastguard Worker /* add filtered noise - check for clipping, before */
2085*e5436536SAndroid Build Coastguard Worker if (noiseVal > (PCM_DEC)0 &&
2086*e5436536SAndroid Build Coastguard Worker pcmdata[ii] > (PCM_DEC)MAXVAL_PCM_DEC - noiseVal) {
2087*e5436536SAndroid Build Coastguard Worker noiseVal = noiseVal * (PCM_DEC)-1;
2088*e5436536SAndroid Build Coastguard Worker } else if (noiseVal < (PCM_DEC)0 &&
2089*e5436536SAndroid Build Coastguard Worker pcmdata[ii] < (PCM_DEC)MINVAL_PCM_DEC - noiseVal) {
2090*e5436536SAndroid Build Coastguard Worker noiseVal = noiseVal * (PCM_DEC)-1;
2091*e5436536SAndroid Build Coastguard Worker }
2092*e5436536SAndroid Build Coastguard Worker
2093*e5436536SAndroid Build Coastguard Worker pcmdata[ii] += noiseVal;
2094*e5436536SAndroid Build Coastguard Worker }
2095*e5436536SAndroid Build Coastguard Worker }
2096*e5436536SAndroid Build Coastguard Worker }
2097