blob: cc6de75a2f70fa6e468e2d77089cd8e870df44c5 [file] [log] [blame]
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001/* -----------------------------------------------------------------------------
The Android Open Source Project2228e362012-07-11 10:15:24 -07002Software License for The Fraunhofer FDK AAC Codec Library for Android
3
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01004© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5Forschung e.V. All rights reserved.
The Android Open Source Project2228e362012-07-11 10:15:24 -07006
7 1. INTRODUCTION
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01008The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10scheme for digital audio. This FDK AAC Codec software is intended to be used on
11a wide variety of Android devices.
The Android Open Source Project2228e362012-07-11 10:15:24 -070012
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010013AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14general perceptual audio codecs. AAC-ELD is considered the best-performing
15full-bandwidth communications codec by independent studies and is widely
16deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17specifications.
The Android Open Source Project2228e362012-07-11 10:15:24 -070018
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010019Patent licenses for necessary patent claims for the FDK AAC Codec (including
20those of Fraunhofer) may be obtained through Via Licensing
21(www.vialicensing.com) or through the respective patent owners individually for
22the purpose of encoding or decoding bit streams in products that are compliant
23with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24Android devices already license these patent claims through Via Licensing or
25directly from the patent owners, and therefore FDK AAC Codec software may
26already be covered under those patent licenses when it is used for those
27licensed purposes only.
The Android Open Source Project2228e362012-07-11 10:15:24 -070028
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010029Commercially-licensed AAC software libraries, including floating-point versions
30with enhanced sound quality, are also available from Fraunhofer. Users are
31encouraged to check the Fraunhofer website for additional applications
32information and documentation.
The Android Open Source Project2228e362012-07-11 10:15:24 -070033
342. COPYRIGHT LICENSE
35
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010036Redistribution and use in source and binary forms, with or without modification,
37are permitted without payment of copyright license fees provided that you
38satisfy the following conditions:
The Android Open Source Project2228e362012-07-11 10:15:24 -070039
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010040You must retain the complete text of this software license in redistributions of
41the FDK AAC Codec or your modifications thereto in source code form.
The Android Open Source Project2228e362012-07-11 10:15:24 -070042
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010043You must retain the complete text of this software license in the documentation
44and/or other materials provided with redistributions of the FDK AAC Codec or
45your modifications thereto in binary form. You must make available free of
46charge copies of the complete source code of the FDK AAC Codec and your
The Android Open Source Project2228e362012-07-11 10:15:24 -070047modifications thereto to recipients of copies in binary form.
48
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010049The name of Fraunhofer may not be used to endorse or promote products derived
50from this library without prior written permission.
The Android Open Source Project2228e362012-07-11 10:15:24 -070051
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010052You may not charge copyright license fees for anyone to use, copy or distribute
53the FDK AAC Codec software or your modifications thereto.
The Android Open Source Project2228e362012-07-11 10:15:24 -070054
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010055Your modified versions of the FDK AAC Codec must carry prominent notices stating
56that you changed the software and the date of any change. For modified versions
57of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59AAC Codec Library for Android."
The Android Open Source Project2228e362012-07-11 10:15:24 -070060
613. NO PATENT LICENSE
62
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010063NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65Fraunhofer provides no warranty of patent non-infringement with respect to this
66software.
The Android Open Source Project2228e362012-07-11 10:15:24 -070067
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010068You may use this FDK AAC Codec software or modifications thereto only for
69purposes that are authorized by appropriate patent licenses.
The Android Open Source Project2228e362012-07-11 10:15:24 -070070
714. DISCLAIMER
72
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010073This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75including but not limited to the implied warranties of merchantability and
76fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78or consequential damages, including but not limited to procurement of substitute
79goods or services; loss of use, data, or profits, or business interruption,
80however caused and on any theory of liability, whether in contract, strict
81liability, or tort (including negligence), arising in any way out of the use of
82this software, even if advised of the possibility of such damage.
The Android Open Source Project2228e362012-07-11 10:15:24 -070083
845. CONTACT INFORMATION
85
86Fraunhofer Institute for Integrated Circuits IIS
87Attention: Audio and Multimedia Departments - FDK AAC LL
88Am Wolfsmantel 33
8991058 Erlangen, Germany
90
91www.iis.fraunhofer.de/amm
92amm-info@iis.fraunhofer.de
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010093----------------------------------------------------------------------------- */
The Android Open Source Project2228e362012-07-11 10:15:24 -070094
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010095/**************************** AAC decoder library ******************************
The Android Open Source Project2228e362012-07-11 10:15:24 -070096
97 Author(s): Josef Hoepfl
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +010098
The Android Open Source Project2228e362012-07-11 10:15:24 -070099 Description: independent channel concealment
100
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100101*******************************************************************************/
The Android Open Source Project2228e362012-07-11 10:15:24 -0700102
103/*!
104 \page concealment AAC core concealment
105
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100106 This AAC core implementation includes a concealment function, which can be
107 enabled using the several defines during compilation.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700108
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100109 There are various tests inside the core, starting with simple CRC tests and
110 ending in a variety of plausibility checks. If such a check indicates an
111 invalid bitstream, then concealment is applied.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700112
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100113 Concealment is also applied when the calling main program indicates a
114 distorted or missing data frame using the frameOK flag. This is used for error
115 detection on the transport layer. (See below)
The Android Open Source Project2228e362012-07-11 10:15:24 -0700116
117 There are three concealment-modes:
118
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100119 1) Muting: The spectral data is simply set to zero in case of an detected
120 error.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700121
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100122 2) Noise substitution: In case of an detected error, concealment copies the
123 last frame and adds attenuates the spectral data. For this mode you have to
124 set the #CONCEAL_NOISE define. Noise substitution adds no additional delay.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700125
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100126 3) Interpolation: The interpolation routine swaps the spectral data from the
127 previous and the current frame just before the final frequency to time
128 conversion. In case a single frame is corrupted, concealmant interpolates
129 between the last good and the first good frame to create the spectral data for
130 the missing frame. If multiple frames are corrupted, concealment implements
131 first a fade out based on slightly modified spectral values from the last good
132 frame. As soon as good frames are available, concealmant fades in the new
133 spectral data. For this mode you have to set the #CONCEAL_INTER define. Note
134 that in this case, you also need to set #SBR_BS_DELAY_ENABLE, which basically
135 adds approriate delay in the SBR decoder. Note that the
136 Interpolating-Concealment increases the delay of your decoder by one frame and
137 that it does require additional resources such as memory and computational
138 complexity.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700139
140 <h2>How concealment can be used with errors on the transport layer</h2>
141
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100142 Many errors can or have to be detected on the transport layer. For example in
143 IP based systems packet loss can occur. The transport protocol used should
144 indicate such packet loss by inserting an empty frame with frameOK=0.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700145*/
146
147#include "conceal.h"
148
149#include "aac_rom.h"
150#include "genericStds.h"
151
The Android Open Source Project2228e362012-07-11 10:15:24 -0700152/* PNS (of block) */
153#include "aacdec_pns.h"
154#include "block.h"
155
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100156#define CONCEAL_DFLT_COMF_NOISE_LEVEL (0x100000)
The Android Open Source Project2228e362012-07-11 10:15:24 -0700157
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100158#define CONCEAL_NOT_DEFINED ((UCHAR)-1)
The Android Open Source Project2228e362012-07-11 10:15:24 -0700159
160/* default settings */
Fraunhofer IIS FDKa4d1f0a2018-05-23 18:26:27 +0200161#define CONCEAL_DFLT_FADEOUT_FRAMES (6)
162#define CONCEAL_DFLT_FADEIN_FRAMES (5)
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100163#define CONCEAL_DFLT_MUTE_RELEASE_FRAMES (0)
The Android Open Source Project2228e362012-07-11 10:15:24 -0700164
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100165#define CONCEAL_DFLT_FADE_FACTOR (0.707106781186548f) /* 1/sqrt(2) */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700166
167/* some often used constants: */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100168#define FIXP_ZERO FL2FXCONST_DBL(0.0f)
169#define FIXP_ONE FL2FXCONST_DBL(1.0f)
170#define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f)
The Android Open Source Project2228e362012-07-11 10:15:24 -0700171
172/* For parameter conversion */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100173#define CONCEAL_PARAMETER_BITS (8)
174#define CONCEAL_MAX_QUANT_FACTOR ((1 << CONCEAL_PARAMETER_BITS) - 1)
175/*#define CONCEAL_MIN_ATTENUATION_FACTOR_025 ( FL2FXCONST_DBL(0.971627951577106174) )*/ /* -0.25 dB */
176#define CONCEAL_MIN_ATTENUATION_FACTOR_025_LD \
177 FL2FXCONST_DBL(-0.041524101186092029596853445212299)
178/*#define CONCEAL_MIN_ATTENUATION_FACTOR_050 ( FL2FXCONST_DBL(0.944060876285923380) )*/ /* -0.50 dB */
179#define CONCEAL_MIN_ATTENUATION_FACTOR_050_LD \
180 FL2FXCONST_DBL(-0.083048202372184059253597008145293)
The Android Open Source Project2228e362012-07-11 10:15:24 -0700181
182typedef enum {
183 CConcealment_NoExpand,
184 CConcealment_Expand,
185 CConcealment_Compress
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100186} CConcealmentExpandType;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700187
188static const FIXP_SGL facMod4Table[4] = {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100189 FL2FXCONST_SGL(0.500000000f), /* FIXP_SGL(0x4000), 2^-(1-0,00) */
190 FL2FXCONST_SGL(0.594603558f), /* FIXP_SGL(0x4c1b), 2^-(1-0,25) */
191 FL2FXCONST_SGL(0.707106781f), /* FIXP_SGL(0x5a82), 2^-(1-0,50) */
192 FL2FXCONST_SGL(0.840896415f) /* FIXP_SGL(0x6ba2) 2^-(1-0,75) */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700193};
194
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100195static void CConcealment_CalcBandEnergy(
196 FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo,
197 const int blockType, CConcealmentExpandType ex, int *sfbEnergy);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700198
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100199static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum,
200 SHORT *pSpecScalePrev,
201 SHORT *pSpecScaleAct,
202 SHORT *pSpecScaleOut, int *enPrv,
203 int *enAct, int sfbCnt,
204 const SHORT *pSfbOffset);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700205
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100206static int CConcealment_ApplyInter(
207 CConcealmentInfo *pConcealmentInfo,
The Android Open Source Project2228e362012-07-11 10:15:24 -0700208 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100209 const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
210 const int improveTonal, const int frameOk, const int mute_release_active);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700211
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100212static int CConcealment_ApplyNoise(
The Android Open Source Project2228e362012-07-11 10:15:24 -0700213 CConcealmentInfo *pConcealmentInfo,
214 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
215 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100216 const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
217 const UINT flags);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700218
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100219static void CConcealment_UpdateState(
220 CConcealmentInfo *pConcealmentInfo, int frameOk,
221 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
222 const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700223
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100224static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec,
225 int samplesPerFrame);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700226
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100227/* TimeDomainFading */
228static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
229 FIXP_DBL fadeStop, FIXP_PCM *pcmdata);
230static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations,
231 int *fadingSteps,
232 FIXP_DBL fadeStop,
233 FIXP_DBL fadeStart,
234 TDfadingType fadingType);
235static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700236
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100237/* Streamline the state machine */
238static int CConcealment_ApplyFadeOut(
239 int mode, CConcealmentInfo *pConcealmentInfo,
240 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
241 const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo);
242
243static int CConcealment_TDNoise_Random(ULONG *seed);
244static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
245 const int len, FIXP_PCM *const pcmdata);
246
247static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) {
248 BLOCK_TYPE newWinSeq = BLOCK_LONG;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700249
250 /* Try to have only long blocks */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100251 if (prevWinSeq == BLOCK_START || prevWinSeq == BLOCK_SHORT) {
252 newWinSeq = BLOCK_STOP;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700253 }
254
255 return (newWinSeq);
256}
257
The Android Open Source Project2228e362012-07-11 10:15:24 -0700258/*!
259 \brief Init common concealment information data
260
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100261 \param pConcealCommonData Pointer to the concealment common data structure.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700262*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100263void CConcealment_InitCommonData(CConcealParams *pConcealCommonData) {
264 if (pConcealCommonData != NULL) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700265 int i;
266
267 /* Set default error concealment technique */
268 pConcealCommonData->method = ConcealMethodInter;
269
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100270 pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES;
271 pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700272 pConcealCommonData->numMuteReleaseFrames = CONCEAL_DFLT_MUTE_RELEASE_FRAMES;
273
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100274 pConcealCommonData->comfortNoiseLevel =
275 (FIXP_DBL)CONCEAL_DFLT_COMF_NOISE_LEVEL;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700276
277 /* Init fade factors (symetric) */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100278 pConcealCommonData->fadeOutFactor[0] =
279 FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR);
280 pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0];
The Android Open Source Project2228e362012-07-11 10:15:24 -0700281
282 for (i = 1; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100283 pConcealCommonData->fadeOutFactor[i] =
284 FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i - 1],
285 FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR)));
286 pConcealCommonData->fadeInFactor[i] =
287 pConcealCommonData->fadeOutFactor[i];
The Android Open Source Project2228e362012-07-11 10:15:24 -0700288 }
289 }
290}
291
The Android Open Source Project2228e362012-07-11 10:15:24 -0700292/*!
293 \brief Get current concealment method.
294
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100295 \param pConcealCommonData Pointer to common concealment data (for all
296 channels)
The Android Open Source Project2228e362012-07-11 10:15:24 -0700297*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100298CConcealmentMethod CConcealment_GetMethod(CConcealParams *pConcealCommonData) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700299 CConcealmentMethod method = ConcealMethodNone;
300
301 if (pConcealCommonData != NULL) {
302 method = pConcealCommonData->method;
303 }
304
305 return (method);
306}
307
The Android Open Source Project2228e362012-07-11 10:15:24 -0700308/*!
309 \brief Init concealment information for each channel
310
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100311 \param pConcealChannelInfo Pointer to the channel related concealment info
312 structure to be initialized. \param pConcealCommonData Pointer to common
313 concealment data (for all channels) \param initRenderMode Initial render
314 mode to be set for the current channel. \param samplesPerFrame The number
315 of samples per frame.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700316*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100317void CConcealment_InitChannelData(CConcealmentInfo *pConcealChannelInfo,
318 CConcealParams *pConcealCommonData,
319 AACDEC_RENDER_MODE initRenderMode,
320 int samplesPerFrame) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700321 int i;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100322 pConcealChannelInfo->TDNoiseSeed = 0;
323 FDKmemclear(pConcealChannelInfo->TDNoiseStates,
324 sizeof(pConcealChannelInfo->TDNoiseStates));
325 pConcealChannelInfo->TDNoiseCoef[0] = FL2FXCONST_SGL(0.05f);
326 pConcealChannelInfo->TDNoiseCoef[1] = FL2FXCONST_SGL(0.5f);
327 pConcealChannelInfo->TDNoiseCoef[2] = FL2FXCONST_SGL(0.45f);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700328
329 pConcealChannelInfo->pConcealParams = pConcealCommonData;
330
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100331 pConcealChannelInfo->lastRenderMode = initRenderMode;
332
333 pConcealChannelInfo->windowShape = CONCEAL_NOT_DEFINED;
334 pConcealChannelInfo->windowSequence = BLOCK_LONG; /* default type */
335 pConcealChannelInfo->lastWinGrpLen = 1;
336
337 pConcealChannelInfo->concealState = ConcealState_Ok;
338
339 FDKmemclear(pConcealChannelInfo->spectralCoefficient,
340 1024 * sizeof(FIXP_CNCL));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700341
342 for (i = 0; i < 8; i++) {
343 pConcealChannelInfo->specScale[i] = 0;
344 }
345
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100346 pConcealChannelInfo->iRandomPhase = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700347
348 pConcealChannelInfo->prevFrameOk[0] = 1;
349 pConcealChannelInfo->prevFrameOk[1] = 1;
350
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100351 pConcealChannelInfo->cntFadeFrames = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700352 pConcealChannelInfo->cntValidFrames = 0;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100353 pConcealChannelInfo->fade_old = (FIXP_DBL)MAXVAL_DBL;
354 pConcealChannelInfo->winGrpOffset[0] = 0;
355 pConcealChannelInfo->winGrpOffset[1] = 0;
356 pConcealChannelInfo->attGrpOffset[0] = 0;
357 pConcealChannelInfo->attGrpOffset[1] = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700358}
359
The Android Open Source Project2228e362012-07-11 10:15:24 -0700360/*!
361 \brief Set error concealment parameters
362
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100363 \param concealParams
364 \param method
365 \param fadeOutSlope
366 \param fadeInSlope
367 \param muteRelease
368 \param comfNoiseLevel
The Android Open Source Project2228e362012-07-11 10:15:24 -0700369*/
370AAC_DECODER_ERROR
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100371CConcealment_SetParams(CConcealParams *concealParams, int method,
372 int fadeOutSlope, int fadeInSlope, int muteRelease,
373 FIXP_DBL comfNoiseLevel) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700374 /* set concealment technique */
375 if (method != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100376 switch ((CConcealmentMethod)method) {
377 case ConcealMethodMute:
378 case ConcealMethodNoise:
379 case ConcealMethodInter:
380 /* Be sure to enable delay adjustment of SBR decoder! */
381 if (concealParams == NULL) {
382 return AAC_DEC_INVALID_HANDLE;
383 } else {
384 /* set param */
385 concealParams->method = (CConcealmentMethod)method;
386 }
387 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700388
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100389 default:
390 return AAC_DEC_SET_PARAM_FAIL;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700391 }
392 }
393
394 /* set number of frames for fade-out slope */
395 if (fadeOutSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100396 if ((fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeOutSlope >= 0)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700397 if (concealParams == NULL) {
398 return AAC_DEC_INVALID_HANDLE;
399 } else {
400 /* set param */
401 concealParams->numFadeOutFrames = fadeOutSlope;
402 }
403 } else {
404 return AAC_DEC_SET_PARAM_FAIL;
405 }
406 }
407
408 /* set number of frames for fade-in slope */
409 if (fadeInSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100410 if ((fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeInSlope >= 0)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700411 if (concealParams == NULL) {
412 return AAC_DEC_INVALID_HANDLE;
413 } else {
414 /* set param */
415 concealParams->numFadeInFrames = fadeInSlope;
416 }
417 } else {
418 return AAC_DEC_SET_PARAM_FAIL;
419 }
420 }
421
422 /* set number of error-free frames after which the muting will be released */
423 if (muteRelease != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100424 if ((muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS << 1)) &&
425 (muteRelease >= 0)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700426 if (concealParams == NULL) {
427 return AAC_DEC_INVALID_HANDLE;
428 } else {
429 /* set param */
430 concealParams->numMuteReleaseFrames = muteRelease;
431 }
432 } else {
433 return AAC_DEC_SET_PARAM_FAIL;
434 }
435 }
436
437 /* set confort noise level which will be inserted while in state 'muting' */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100438 if (comfNoiseLevel != (FIXP_DBL)AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) {
439 if ((comfNoiseLevel < (FIXP_DBL)0) ||
440 (comfNoiseLevel > (FIXP_DBL)MAXVAL_DBL)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700441 return AAC_DEC_SET_PARAM_FAIL;
442 }
443 if (concealParams == NULL) {
444 return AAC_DEC_INVALID_HANDLE;
445 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100446 concealParams->comfortNoiseLevel = (FIXP_DBL)comfNoiseLevel;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700447 }
448 }
449
450 return (AAC_DEC_OK);
451}
452
The Android Open Source Project2228e362012-07-11 10:15:24 -0700453/*!
454 \brief Set fade-out/in attenuation factor vectors
455
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100456 \param concealParams
457 \param fadeOutAttenuationVector
458 \param fadeInAttenuationVector
The Android Open Source Project2228e362012-07-11 10:15:24 -0700459
460 \return 0 if OK all other values indicate errors
461*/
462AAC_DECODER_ERROR
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100463CConcealment_SetAttenuation(CConcealParams *concealParams,
464 const SHORT *fadeOutAttenuationVector,
465 const SHORT *fadeInAttenuationVector) {
466 if ((fadeOutAttenuationVector == NULL) && (fadeInAttenuationVector == NULL)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700467 return AAC_DEC_SET_PARAM_FAIL;
468 }
469
470 /* Fade-out factors */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100471 if (fadeOutAttenuationVector != NULL) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700472 int i;
473
474 /* check quantized factors first */
475 for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100476 if ((fadeOutAttenuationVector[i] < 0) ||
477 (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700478 return AAC_DEC_SET_PARAM_FAIL;
479 }
480 }
481 if (concealParams == NULL) {
482 return AAC_DEC_INVALID_HANDLE;
483 }
484
485 /* now dequantize factors */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100486 for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700487 concealParams->fadeOutFactor[i] =
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100488 FX_DBL2FX_SGL(fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0,
489 (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0 / 2.0) >>
490 (CONCEAL_PARAMETER_BITS - 1)) *
491 (INT)fadeOutAttenuationVector[i]),
492 CONCEAL_PARAMETER_BITS));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700493 }
494 }
495
496 /* Fade-in factors */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100497 if (fadeInAttenuationVector != NULL) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700498 int i;
499
500 /* check quantized factors first */
501 for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100502 if ((fadeInAttenuationVector[i] < 0) ||
503 (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700504 return AAC_DEC_SET_PARAM_FAIL;
505 }
506 }
507 if (concealParams == NULL) {
508 return AAC_DEC_INVALID_HANDLE;
509 }
510
511 /* now dequantize factors */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100512 for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
513 concealParams->fadeInFactor[i] = FX_DBL2FX_SGL(
514 fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0,
515 (FIXP_DBL)((INT)(FIXP_ONE >> CONCEAL_PARAMETER_BITS) *
516 (INT)fadeInAttenuationVector[i]),
517 CONCEAL_PARAMETER_BITS));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700518 }
519 }
520
521 return (AAC_DEC_OK);
522}
523
The Android Open Source Project2228e362012-07-11 10:15:24 -0700524/*!
525 \brief Get state of concealment module.
526
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100527 \param pConcealChannelInfo
The Android Open Source Project2228e362012-07-11 10:15:24 -0700528
529 \return Concealment state.
530*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100531CConcealmentState CConcealment_GetState(CConcealmentInfo *pConcealChannelInfo) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700532 CConcealmentState state = ConcealState_Ok;
533
534 if (pConcealChannelInfo != NULL) {
535 state = pConcealChannelInfo->concealState;
536 }
537
538 return (state);
539}
540
The Android Open Source Project2228e362012-07-11 10:15:24 -0700541/*!
542 \brief Store data for concealment techniques applied later
543
544 Interface function to store data for different concealment strategies
The Android Open Source Project2228e362012-07-11 10:15:24 -0700545 */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100546void CConcealment_Store(
The Android Open Source Project2228e362012-07-11 10:15:24 -0700547 CConcealmentInfo *hConcealmentInfo,
548 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100549 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) {
550 UCHAR nbDiv = NB_DIV;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700551
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100552 if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD &&
553 pAacDecoderChannelInfo->data.usac.mod[nbDiv - 1] == 0))
554
555 {
556 FIXP_DBL *pSpectralCoefficient =
557 SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
558 SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
559 CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
560
561 SHORT tSpecScale[8];
562 UCHAR tWindowShape;
563 BLOCK_TYPE tWindowSequence;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700564
565 /* store old window infos for swapping */
566 tWindowSequence = hConcealmentInfo->windowSequence;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100567 tWindowShape = hConcealmentInfo->windowShape;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700568
569 /* store old scale factors for swapping */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100570 FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700571
572 /* store new window infos */
573 hConcealmentInfo->windowSequence = GetWindowSequence(pIcsInfo);
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100574 hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo);
575 hConcealmentInfo->lastWinGrpLen =
576 *(GetWindowGroupLengthTable(pIcsInfo) + GetWindowGroups(pIcsInfo) - 1);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700577
578 /* store new scale factors */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100579 FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8 * sizeof(SHORT));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700580
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100581 if (hConcealmentInfo->pConcealParams->method < ConcealMethodInter) {
582 /* store new spectral bins */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700583#if (CNCL_FRACT_BITS == DFRACT_BITS)
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100584 FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient,
585 1024 * sizeof(FIXP_CNCL));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700586#else
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100587 FIXP_CNCL *RESTRICT pCncl =
588 &hConcealmentInfo->spectralCoefficient[1024 - 1];
589 FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1];
The Android Open Source Project2228e362012-07-11 10:15:24 -0700590 int i;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700591 for (i = 1024; i != 0; i--) {
592 *pCncl-- = FX_DBL2FX_CNCL(*pSpec--);
593 }
594#endif
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100595 } else {
596 /* swap spectral data */
597#if (FIXP_CNCL == FIXP_DBL)
598 C_ALLOC_SCRATCH_START(pSpecTmp, FIXP_DBL, 1024);
599 FDKmemcpy(pSpecTmp, pSpectralCoefficient, 1024 * sizeof(FIXP_DBL));
600 FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient,
601 1024 * sizeof(FIXP_DBL));
602 FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpecTmp,
603 1024 * sizeof(FIXP_DBL));
604 C_ALLOC_SCRATCH_END(pSpecTmp, FIXP_DBL, 1024);
605#else
606 FIXP_CNCL *RESTRICT pCncl =
607 &hConcealmentInfo->spectralCoefficient[1024 - 1];
608 FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1];
609 FIXP_DBL tSpec;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700610
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100611 for (int i = 1024; i != 0; i--) {
612 tSpec = *pSpec;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700613 *pSpec-- = FX_CNCL2FX_DBL(*pCncl);
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100614 *pCncl-- = FX_DBL2FX_CNCL(tSpec);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700615 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100616#endif
The Android Open Source Project2228e362012-07-11 10:15:24 -0700617
618 /* complete swapping of window infos */
619 pIcsInfo->WindowSequence = tWindowSequence;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100620 pIcsInfo->WindowShape = tWindowShape;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700621
622 /* complete swapping of scale factors */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100623 FDKmemcpy(pSpecScale, tSpecScale, 8 * sizeof(SHORT));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700624 }
625 }
The Android Open Source Project2228e362012-07-11 10:15:24 -0700626
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100627 if (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD) {
628 /* Store LSF4 */
629 FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf,
630 sizeof(hConcealmentInfo->lsf4));
631 /* Store TCX gain */
632 hConcealmentInfo->last_tcx_gain =
633 pAacDecoderStaticChannelInfo->last_tcx_gain;
634 hConcealmentInfo->last_tcx_gain_e =
635 pAacDecoderStaticChannelInfo->last_tcx_gain_e;
636 }
637}
The Android Open Source Project2228e362012-07-11 10:15:24 -0700638
639/*!
640 \brief Apply concealment
641
642 Interface function to different concealment strategies
The Android Open Source Project2228e362012-07-11 10:15:24 -0700643 */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100644int CConcealment_Apply(
The Android Open Source Project2228e362012-07-11 10:15:24 -0700645 CConcealmentInfo *hConcealmentInfo,
646 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
647 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100648 const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
649 const UCHAR lastLpdMode, const int frameOk, const UINT flags) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700650 int appliedProcessing = 0;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100651 const int mute_release_active =
652 frameOk && (hConcealmentInfo->concealState >= ConcealState_Mute) &&
653 (hConcealmentInfo->cntValidFrames + 1 <=
654 hConcealmentInfo->pConcealParams->numMuteReleaseFrames);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700655
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100656 if (hConcealmentInfo->windowShape == CONCEAL_NOT_DEFINED) {
657 /* Initialize window_shape with same value as in the current (parsed) frame.
658 Because section 4.6.11.3.2 (Windowing and block switching) of ISO/IEC
659 14496-3:2009 says: For the first raw_data_block() to be decoded the
660 window_shape of the left and right half of the window are identical. */
661 hConcealmentInfo->windowShape = pAacDecoderChannelInfo->icsInfo.WindowShape;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700662 }
663
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100664 if (frameOk && !mute_release_active) {
665 /* Update render mode if frameOk except for ongoing mute release state. */
666 hConcealmentInfo->lastRenderMode =
667 (SCHAR)pAacDecoderChannelInfo->renderMode;
668
The Android Open Source Project2228e362012-07-11 10:15:24 -0700669 /* Rescue current data for concealment in future frames */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100670 CConcealment_Store(hConcealmentInfo, pAacDecoderChannelInfo,
671 pAacDecoderStaticChannelInfo);
672 /* Reset index to random sign vector to make sign calculation frame agnostic
The Android Open Source Project2228e362012-07-11 10:15:24 -0700673 (only depends on number of subsequently concealed spectral blocks) */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100674 hConcealmentInfo->iRandomPhase = 0;
675 } else {
676 if (hConcealmentInfo->lastRenderMode == AACDEC_RENDER_INVALID) {
677 hConcealmentInfo->lastRenderMode = AACDEC_RENDER_IMDCT;
678 }
679 pAacDecoderChannelInfo->renderMode =
680 (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700681 }
682
683 /* hand current frame status to the state machine */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100684 CConcealment_UpdateState(hConcealmentInfo, frameOk,
685 pAacDecoderStaticChannelInfo, samplesPerFrame,
686 pAacDecoderChannelInfo);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700687
The Android Open Source Project2228e362012-07-11 10:15:24 -0700688 {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100689 if (!frameOk && pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_IMDCT) {
690 /* LPC extrapolation */
691 CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff,
692 pAacDecoderStaticChannelInfo->lpc4_lsf,
693 pAacDecoderStaticChannelInfo->lsf_adaptive_mean,
694 hConcealmentInfo->lastRenderMode == AACDEC_RENDER_IMDCT);
695 FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf,
696 sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf));
697 }
The Android Open Source Project2228e362012-07-11 10:15:24 -0700698
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100699 /* Create data for signal rendering according to the selected concealment
700 * method and decoder operating mode. */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700701
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100702 if ((!frameOk || mute_release_active) &&
703 (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD)) {
704 /* Restore old LSF4 */
705 FDKmemcpy(pAacDecoderStaticChannelInfo->lpc4_lsf, hConcealmentInfo->lsf4,
706 sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf));
707 /* Restore old TCX gain */
708 pAacDecoderStaticChannelInfo->last_tcx_gain =
709 hConcealmentInfo->last_tcx_gain;
710 pAacDecoderStaticChannelInfo->last_tcx_gain_e =
711 hConcealmentInfo->last_tcx_gain_e;
712 }
713
714 if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD &&
715 pAacDecoderStaticChannelInfo->last_lpd_mode == 0)) {
716 switch (hConcealmentInfo->pConcealParams->method) {
717 default:
718 case ConcealMethodMute:
719 if (!frameOk) {
720 /* Mute spectral data in case of errors */
721 FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient,
722 samplesPerFrame * sizeof(FIXP_DBL));
723 /* Set last window shape */
724 pAacDecoderChannelInfo->icsInfo.WindowShape =
725 hConcealmentInfo->windowShape;
726 appliedProcessing = 1;
727 }
728 break;
729
730 case ConcealMethodNoise:
731 /* Noise substitution error concealment technique */
732 appliedProcessing = CConcealment_ApplyNoise(
733 hConcealmentInfo, pAacDecoderChannelInfo,
734 pAacDecoderStaticChannelInfo, pSamplingRateInfo, samplesPerFrame,
735 flags);
736 break;
737
738 case ConcealMethodInter:
739 /* Energy interpolation concealment based on 3GPP */
740 appliedProcessing = CConcealment_ApplyInter(
741 hConcealmentInfo, pAacDecoderChannelInfo, pSamplingRateInfo,
742 samplesPerFrame, 0, /* don't use tonal improvement */
743 frameOk, mute_release_active);
744 break;
745 }
746 } else if (!frameOk || mute_release_active) {
747 /* simply restore the buffer */
748 FIXP_DBL *pSpectralCoefficient =
749 SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
750 SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
751 CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
752#if (CNCL_FRACT_BITS != DFRACT_BITS)
753 FIXP_CNCL *RESTRICT pCncl =
754 &hConcealmentInfo->spectralCoefficient[1024 - 1];
755 FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1];
756 int i;
757#endif
758
759 /* restore window infos (gri) do we need that? */
760 pIcsInfo->WindowSequence = hConcealmentInfo->windowSequence;
761 pIcsInfo->WindowShape = hConcealmentInfo->windowShape;
762
763 if (hConcealmentInfo->concealState != ConcealState_Mute) {
764 /* restore scale factors */
765 FDKmemcpy(pSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT));
766
767 /* restore spectral bins */
768#if (CNCL_FRACT_BITS == DFRACT_BITS)
769 FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient,
770 1024 * sizeof(FIXP_DBL));
771#else
772 for (i = 1024; i != 0; i--) {
773 *pSpec-- = FX_CNCL2FX_DBL(*pCncl--);
Jean-Michel Trivi47c680c2013-12-27 16:13:22 -0800774 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100775#endif
776 } else {
777 /* clear scale factors */
778 FDKmemclear(pSpecScale, 8 * sizeof(SHORT));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700779
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100780 /* clear buffer */
781 FDKmemclear(pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700782 }
783 }
784 }
785 /* update history */
786 hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1];
787 hConcealmentInfo->prevFrameOk[1] = frameOk;
788
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100789 return mute_release_active ? -1 : appliedProcessing;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700790}
791
792/*!
793\brief Apply concealment noise substitution
794
795 In case of frame lost this function produces a noisy frame with respect to the
796 energies values of past frame.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700797 */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100798static int CConcealment_ApplyNoise(
799 CConcealmentInfo *pConcealmentInfo,
800 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
801 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
802 const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
803 const UINT flags) {
804 FIXP_DBL *pSpectralCoefficient =
805 SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
806 CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700807
808 int appliedProcessing = 0;
809
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100810 FDK_ASSERT(pConcealmentInfo != NULL);
811 FDK_ASSERT((samplesPerFrame >= 120) && (samplesPerFrame <= 1024));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700812
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100813 switch (pConcealmentInfo->concealState) {
814 case ConcealState_Ok:
815 /* Nothing to do here! */
816 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700817
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100818 case ConcealState_Single:
819 case ConcealState_FadeOut:
820 appliedProcessing = CConcealment_ApplyFadeOut(
821 /*mode =*/1, pConcealmentInfo, pAacDecoderStaticChannelInfo,
822 samplesPerFrame, pAacDecoderChannelInfo);
823 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700824
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100825 case ConcealState_Mute: {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700826 /* set dummy window parameters */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100827 pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
828 pIcsInfo->WindowShape =
829 pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape
830 (required for F/T transform) */
831 pIcsInfo->WindowSequence =
832 CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
833 pConcealmentInfo->windowSequence =
834 pIcsInfo->WindowSequence; /* Store for next frame
835 (spectrum in concealment
836 buffer can't be used at
837 all) */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700838
839 /* mute spectral data */
840 FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100841 FDKmemclear(pConcealmentInfo->spectralCoefficient,
842 samplesPerFrame * sizeof(FIXP_DBL));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700843
The Android Open Source Project2228e362012-07-11 10:15:24 -0700844 appliedProcessing = 1;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100845 } break;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700846
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100847 case ConcealState_FadeIn: {
848 /* TimeDomainFading: */
849 /* Attenuation of signal is done in CConcealment_TDFading() */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700850
The Android Open Source Project2228e362012-07-11 10:15:24 -0700851 appliedProcessing = 1;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100852 } break;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700853
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100854 default:
855 /* we shouldn't come here anyway */
856 FDK_ASSERT(0);
857 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700858 }
859
860 return appliedProcessing;
861}
862
The Android Open Source Project2228e362012-07-11 10:15:24 -0700863/*!
864 \brief Apply concealment interpolation
865
866 The function swaps the data from the current and the previous frame. If an
867 error has occured, frame interpolation is performed to restore the missing
868 frame. In case of multiple faulty frames, fade-in and fade-out is applied.
The Android Open Source Project2228e362012-07-11 10:15:24 -0700869*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100870static int CConcealment_ApplyInter(
871 CConcealmentInfo *pConcealmentInfo,
The Android Open Source Project2228e362012-07-11 10:15:24 -0700872 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100873 const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame,
874 const int improveTonal, const int frameOk, const int mute_release_active) {
875#if defined(FDK_ASSERT_ENABLE)
876 CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
877#endif
The Android Open Source Project2228e362012-07-11 10:15:24 -0700878
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100879 FIXP_DBL *pSpectralCoefficient =
880 SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
881 CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
882 SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700883
884 int sfbEnergyPrev[64];
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100885 int sfbEnergyAct[64];
The Android Open Source Project2228e362012-07-11 10:15:24 -0700886
887 int i, appliedProcessing = 0;
888
889 /* clear/init */
890 FDKmemclear(sfbEnergyPrev, 64 * sizeof(int));
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100891 FDKmemclear(sfbEnergyAct, 64 * sizeof(int));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700892
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100893 if (!frameOk || mute_release_active) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700894 /* Restore last frame from concealment buffer */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100895 pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700896 pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
897
898 /* Restore spectral data */
899 for (i = 0; i < samplesPerFrame; i++) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100900 pSpectralCoefficient[i] =
901 FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700902 }
903
904 /* Restore scale factors */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100905 FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8 * sizeof(SHORT));
The Android Open Source Project2228e362012-07-11 10:15:24 -0700906 }
907
908 /* if previous frame was not ok */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100909 if (!pConcealmentInfo->prevFrameOk[1] || mute_release_active) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700910 /* if current frame (f_n) is ok and the last but one frame (f_(n-2))
911 was ok, too, then interpolate both frames in order to generate
912 the current output frame (f_(n-1)). Otherwise, use the last stored
913 frame (f_(n-2) or f_(n-3) or ...). */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100914 if (frameOk && pConcealmentInfo->prevFrameOk[0] && !mute_release_active) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700915 appliedProcessing = 1;
916
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100917 /* Interpolate both frames in order to generate the current output frame
918 * (f_(n-1)). */
919 if (pIcsInfo->WindowSequence == BLOCK_SHORT) {
920 /* f_(n-2) == BLOCK_SHORT */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700921 /* short--??????--short, short--??????--long interpolation */
922 /* short--short---short, short---long---long interpolation */
923
924 int wnd;
925
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100926 if (pConcealmentInfo->windowSequence ==
927 BLOCK_SHORT) { /* f_n == BLOCK_SHORT */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700928 /* short--short---short interpolation */
929
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100930 int scaleFactorBandsTotal =
931 pSamplingRateInfo->NumberOfScaleFactorBands_Short;
932 const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
933 pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1;
934 pIcsInfo->WindowSequence = BLOCK_SHORT;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700935
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100936 for (wnd = 0; wnd < 8; wnd++) {
The Android Open Source Project2228e362012-07-11 10:15:24 -0700937 CConcealment_CalcBandEnergy(
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100938 &pSpectralCoefficient[wnd *
939 (samplesPerFrame / 8)], /* spec_(n-2) */
940 pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand,
941 sfbEnergyPrev);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700942
943 CConcealment_CalcBandEnergy(
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100944 &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame /
945 8)], /* spec_n */
946 pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand,
947 sfbEnergyAct);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700948
949 CConcealment_InterpolateBuffer(
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100950 &pSpectralCoefficient[wnd *
951 (samplesPerFrame / 8)], /* spec_(n-1) */
952 &pSpecScale[wnd], &pConcealmentInfo->specScale[wnd],
953 &pSpecScale[wnd], sfbEnergyPrev, sfbEnergyAct,
954 scaleFactorBandsTotal, pSfbOffset);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700955 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100956 } else { /* f_n != BLOCK_SHORT */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700957 /* short---long---long interpolation */
958
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100959 int scaleFactorBandsTotal =
960 pSamplingRateInfo->NumberOfScaleFactorBands_Long;
961 const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700962 SHORT specScaleOut;
963
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100964 CConcealment_CalcBandEnergy(
965 &pSpectralCoefficient[samplesPerFrame -
966 (samplesPerFrame /
967 8)], /* [wnd] spec_(n-2) */
968 pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand,
969 sfbEnergyAct);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700970
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100971 CConcealment_CalcBandEnergy(
972 pConcealmentInfo->spectralCoefficient, /* spec_n */
973 pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand,
974 sfbEnergyPrev);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700975
976 pIcsInfo->WindowShape = 0;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100977 pIcsInfo->WindowSequence = BLOCK_STOP;
The Android Open Source Project2228e362012-07-11 10:15:24 -0700978
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100979 for (i = 0; i < samplesPerFrame; i++) {
980 pSpectralCoefficient[i] =
981 pConcealmentInfo->spectralCoefficient[i]; /* spec_n */
The Android Open Source Project2228e362012-07-11 10:15:24 -0700982 }
983
984 for (i = 0; i < 8; i++) { /* search for max(specScale) */
985 if (pSpecScale[i] > pSpecScale[0]) {
986 pSpecScale[0] = pSpecScale[i];
987 }
988 }
989
990 CConcealment_InterpolateBuffer(
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +0100991 pSpectralCoefficient, /* spec_(n-1) */
992 &pConcealmentInfo->specScale[0], &pSpecScale[0], &specScaleOut,
993 sfbEnergyPrev, sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset);
The Android Open Source Project2228e362012-07-11 10:15:24 -0700994
995 pSpecScale[0] = specScaleOut;
996 }
997 } else {
998 /* long--??????--short, long--??????--long interpolation */
999 /* long---long---short, long---long---long interpolation */
1000
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001001 int scaleFactorBandsTotal =
1002 pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1003 const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1004 SHORT specScaleAct = pConcealmentInfo->specScale[0];
The Android Open Source Project2228e362012-07-11 10:15:24 -07001005
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001006 CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */
1007 pSamplingRateInfo, BLOCK_LONG,
1008 CConcealment_NoExpand, sfbEnergyPrev);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001009
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001010 if (pConcealmentInfo->windowSequence ==
1011 BLOCK_SHORT) { /* f_n == BLOCK_SHORT */
The Android Open Source Project2228e362012-07-11 10:15:24 -07001012 /* long---long---short interpolation */
1013
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001014 pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1;
1015 pIcsInfo->WindowSequence = BLOCK_START;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001016
1017 for (i = 1; i < 8; i++) { /* search for max(specScale) */
1018 if (pConcealmentInfo->specScale[i] > specScaleAct) {
1019 specScaleAct = pConcealmentInfo->specScale[i];
1020 }
1021 }
1022
1023 /* Expand first short spectrum */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001024 CConcealment_CalcBandEnergy(
1025 pConcealmentInfo->spectralCoefficient, /* spec_n */
1026 pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, /* !!! */
1027 sfbEnergyAct);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001028 } else {
1029 /* long---long---long interpolation */
1030
1031 pIcsInfo->WindowShape = 0;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001032 pIcsInfo->WindowSequence = BLOCK_LONG;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001033
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001034 CConcealment_CalcBandEnergy(
1035 pConcealmentInfo->spectralCoefficient, /* spec_n */
1036 pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand,
1037 sfbEnergyAct);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001038 }
1039
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001040 CConcealment_InterpolateBuffer(
1041 pSpectralCoefficient, /* spec_(n-1) */
1042 &pSpecScale[0], &specScaleAct, &pSpecScale[0], sfbEnergyPrev,
1043 sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001044 }
1045 }
1046
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001047 /* Noise substitution of sign of the output spectral coefficients */
1048 CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase,
1049 pSpectralCoefficient, samplesPerFrame);
1050 /* Increment random phase index to avoid repetition artifacts. */
1051 pConcealmentInfo->iRandomPhase =
1052 (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001053 }
1054
1055 /* scale spectrum according to concealment state */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001056 switch (pConcealmentInfo->concealState) {
1057 case ConcealState_Single:
The Android Open Source Project2228e362012-07-11 10:15:24 -07001058 appliedProcessing = 1;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001059 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001060
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001061 case ConcealState_FadeOut: {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001062 FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001063 FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1064 CONCEAL_MAX_NUM_FADE_FACTORS);
1065 FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1066 pConcealCommonData->numFadeOutFrames);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001067
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001068 /* TimeDomainFading: */
1069 /* Attenuation of signal is done in CConcealment_TDFading() */
The Android Open Source Project2228e362012-07-11 10:15:24 -07001070
The Android Open Source Project2228e362012-07-11 10:15:24 -07001071 appliedProcessing = 1;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001072 } break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001073
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001074 case ConcealState_FadeIn: {
1075 FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
1076 FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1077 CONCEAL_MAX_NUM_FADE_FACTORS);
1078 FDK_ASSERT(pConcealmentInfo->cntFadeFrames <
1079 pConcealCommonData->numFadeInFrames);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001080
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001081 /* TimeDomainFading: */
1082 /* Attenuation of signal is done in CConcealment_TDFading() */
1083
1084 appliedProcessing = 1;
1085 } break;
1086
1087 case ConcealState_Mute: {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001088 /* set dummy window parameters */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001089 pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
1090 pIcsInfo->WindowShape =
1091 pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape
1092 (required for F/T transform) */
1093 pIcsInfo->WindowSequence =
1094 CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
1095 pConcealmentInfo->windowSequence =
1096 pIcsInfo->WindowSequence; /* Store for next frame
1097 (spectrum in concealment
1098 buffer can't be used at
1099 all) */
The Android Open Source Project2228e362012-07-11 10:15:24 -07001100
1101 /* mute spectral data */
1102 FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
1103
The Android Open Source Project2228e362012-07-11 10:15:24 -07001104 appliedProcessing = 1;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001105 } break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001106
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001107 default:
1108 /* nothing to do here */
1109 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001110 }
1111
1112 return appliedProcessing;
1113}
1114
The Android Open Source Project2228e362012-07-11 10:15:24 -07001115/*!
1116 \brief Calculate the spectral energy
1117
1118 The function calculates band-wise the spectral energy. This is used for
1119 frame interpolation.
The Android Open Source Project2228e362012-07-11 10:15:24 -07001120*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001121static void CConcealment_CalcBandEnergy(
1122 FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo,
1123 const int blockType, CConcealmentExpandType expandType, int *sfbEnergy) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001124 const SHORT *pSfbOffset;
1125 int line, sfb, scaleFactorBandsTotal = 0;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001126
1127 /* In the following calculations, enAccu is initialized with LSB-value in
1128 * order to avoid zero energy-level */
The Android Open Source Project2228e362012-07-11 10:15:24 -07001129
1130 line = 0;
1131
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001132 switch (blockType) {
1133 case BLOCK_LONG:
1134 case BLOCK_START:
1135 case BLOCK_STOP:
The Android Open Source Project2228e362012-07-11 10:15:24 -07001136
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001137 if (expandType == CConcealment_NoExpand) {
1138 /* standard long calculation */
1139 scaleFactorBandsTotal =
1140 pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1141 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001142
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001143 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1144 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1145 int sfbScale =
1146 (sizeof(LONG) << 3) -
1147 CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1148 /* scaling depends on sfb width. */
1149 for (; line < pSfbOffset[sfb + 1]; line++) {
1150 enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
1151 }
1152 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001153 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001154 } else {
1155 /* compress long to short */
1156 scaleFactorBandsTotal =
1157 pSamplingRateInfo->NumberOfScaleFactorBands_Short;
1158 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001159
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001160 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1161 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1162 int sfbScale =
1163 (sizeof(LONG) << 3) -
1164 CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1165 /* scaling depends on sfb width. */
1166 for (; line < pSfbOffset[sfb + 1] << 3; line++) {
1167 enAccu +=
1168 (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3;
1169 }
1170 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001171 }
The Android Open Source Project2228e362012-07-11 10:15:24 -07001172 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001173 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001174
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001175 case BLOCK_SHORT:
The Android Open Source Project2228e362012-07-11 10:15:24 -07001176
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001177 if (expandType == CConcealment_NoExpand) {
1178 /* standard short calculation */
1179 scaleFactorBandsTotal =
1180 pSamplingRateInfo->NumberOfScaleFactorBands_Short;
1181 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001182
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001183 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1184 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1185 int sfbScale =
1186 (sizeof(LONG) << 3) -
1187 CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1188 /* scaling depends on sfb width. */
1189 for (; line < pSfbOffset[sfb + 1]; line++) {
1190 enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
1191 }
1192 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001193 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001194 } else {
1195 /* expand short to long spectrum */
1196 scaleFactorBandsTotal =
1197 pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1198 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001199
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001200 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1201 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1202 int sfbScale =
1203 (sizeof(LONG) << 3) -
1204 CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1;
1205 /* scaling depends on sfb width. */
1206 for (; line < pSfbOffset[sfb + 1]; line++) {
1207 enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale;
1208 }
1209 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001210 }
The Android Open Source Project2228e362012-07-11 10:15:24 -07001211 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001212 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001213 }
1214}
1215
The Android Open Source Project2228e362012-07-11 10:15:24 -07001216/*!
1217 \brief Interpolate buffer
1218
1219 The function creates the interpolated spectral data according to the
1220 energy of the last good frame and the current (good) frame.
The Android Open Source Project2228e362012-07-11 10:15:24 -07001221*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001222static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum,
1223 SHORT *pSpecScalePrv,
1224 SHORT *pSpecScaleAct,
1225 SHORT *pSpecScaleOut, int *enPrv,
1226 int *enAct, int sfbCnt,
1227 const SHORT *pSfbOffset) {
1228 int sfb, line = 0;
1229 int fac_shift;
1230 int fac_mod;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001231 FIXP_DBL accu;
1232
1233 for (sfb = 0; sfb < sfbCnt; sfb++) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001234 fac_shift =
1235 enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1);
1236 fac_mod = fac_shift & 3;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001237 fac_shift = (fac_shift >> 2) + 1;
1238 fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct);
1239
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001240 for (; line < pSfbOffset[sfb + 1]; line++) {
1241 accu = fMult(*(spectrum + line), facMod4Table[fac_mod]);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001242 if (fac_shift < 0) {
1243 accu >>= -fac_shift;
1244 } else {
1245 accu <<= fac_shift;
1246 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001247 *(spectrum + line) = accu;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001248 }
1249 }
1250 *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct);
1251}
1252
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001253/*!
1254 \brief Find next fading frame in case of changing fading direction
The Android Open Source Project2228e362012-07-11 10:15:24 -07001255
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001256 \param pConcealCommonData Pointer to the concealment common data structure.
1257 \param actFadeIndex Last index used for fading
1258 \param direction Direction of change: 0 : change from FADE-OUT to FADE-IN, 1
1259 : change from FADE-IN to FADE-OUT
The Android Open Source Project2228e362012-07-11 10:15:24 -07001260
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001261 This function determines the next fading index to be used for the fading
1262 direction to be changed to.
1263*/
The Android Open Source Project2228e362012-07-11 10:15:24 -07001264
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001265static INT findEquiFadeFrame(CConcealParams *pConcealCommonData,
1266 INT actFadeIndex, int direction) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001267 FIXP_SGL *pFactor;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001268 FIXP_SGL referenceVal;
1269 FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001270
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001271 INT nextFadeIndex = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001272
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001273 int i;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001274
1275 /* init depending on direction */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001276 if (direction == 0) { /* FADE-OUT => FADE-IN */
1277 if (actFadeIndex < 0) {
1278 referenceVal = (FIXP_SGL)MAXVAL_SGL;
1279 } else {
1280 referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1;
1281 }
The Android Open Source Project2228e362012-07-11 10:15:24 -07001282 pFactor = pConcealCommonData->fadeInFactor;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001283 } else { /* FADE-IN => FADE-OUT */
1284 if (actFadeIndex < 0) {
1285 referenceVal = (FIXP_SGL)MAXVAL_SGL;
1286 } else {
1287 referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1;
1288 }
The Android Open Source Project2228e362012-07-11 10:15:24 -07001289 pFactor = pConcealCommonData->fadeOutFactor;
1290 }
1291
1292 /* search for minimum difference */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001293 for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) {
1294 FIXP_SGL diff = fixp_abs((pFactor[i] >> 1) - referenceVal);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001295 if (diff < minDiff) {
1296 minDiff = diff;
1297 nextFadeIndex = i;
1298 }
1299 }
1300
1301 /* check and adjust depending on direction */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001302 if (direction == 0) { /* FADE-OUT => FADE-IN */
1303 if (nextFadeIndex > pConcealCommonData->numFadeInFrames) {
1304 nextFadeIndex = fMax(pConcealCommonData->numFadeInFrames - 1, 0);
1305 }
1306 if (((pFactor[nextFadeIndex] >> 1) <= referenceVal) &&
1307 (nextFadeIndex > 0)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001308 nextFadeIndex -= 1;
1309 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001310 } else { /* FADE-IN => FADE-OUT */
1311 if (((pFactor[nextFadeIndex] >> 1) >= referenceVal) &&
1312 (nextFadeIndex < CONCEAL_MAX_NUM_FADE_FACTORS - 1)) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001313 nextFadeIndex += 1;
1314 }
1315 }
1316
1317 return (nextFadeIndex);
1318}
1319
The Android Open Source Project2228e362012-07-11 10:15:24 -07001320/*!
1321 \brief Update the concealment state
1322
1323 The function updates the state of the concealment state-machine. The
1324 states are: mute, fade-in, fade-out, interpolate and frame-ok.
The Android Open Source Project2228e362012-07-11 10:15:24 -07001325*/
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001326static void CConcealment_UpdateState(
1327 CConcealmentInfo *pConcealmentInfo, int frameOk,
1328 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
1329 const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001330 CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
1331
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001332 switch (pConcealCommonData->method) {
1333 case ConcealMethodNoise: {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001334 if (pConcealmentInfo->concealState != ConcealState_Ok) {
1335 /* count the valid frames during concealment process */
1336 if (frameOk) {
1337 pConcealmentInfo->cntValidFrames += 1;
1338 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001339 pConcealmentInfo->cntValidFrames = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001340 }
1341 }
1342
1343 /* -- STATE MACHINE for Noise Substitution -- */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001344 switch (pConcealmentInfo->concealState) {
1345 case ConcealState_Ok:
1346 if (!frameOk) {
1347 pConcealmentInfo->cntFadeFrames = 0;
1348 pConcealmentInfo->cntValidFrames = 0;
1349 pConcealmentInfo->attGrpOffset[0] = 0;
1350 pConcealmentInfo->attGrpOffset[1] = 0;
1351 pConcealmentInfo->winGrpOffset[0] = 0;
1352 pConcealmentInfo->winGrpOffset[1] = 0;
1353 if (pConcealCommonData->numFadeOutFrames > 0) {
1354 /* change to state SINGLE-FRAME-LOSS */
1355 pConcealmentInfo->concealState = ConcealState_Single;
1356 /* mode 0 just updates the Fading counter */
1357 CConcealment_ApplyFadeOut(
1358 /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1359 samplesPerFrame, pAacDecoderChannelInfo);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001360
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001361 } else {
1362 /* change to state MUTE */
1363 pConcealmentInfo->concealState = ConcealState_Mute;
1364 }
1365 }
1366 break;
1367
1368 case ConcealState_Single: /* Just a pre-stage before fade-out begins.
1369 Stay here only one frame! */
1370 if (frameOk) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001371 /* change to state OK */
1372 pConcealmentInfo->concealState = ConcealState_Ok;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001373 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001374 if (pConcealmentInfo->cntFadeFrames >=
1375 pConcealCommonData->numFadeOutFrames) {
1376 /* change to state MUTE */
1377 pConcealmentInfo->concealState = ConcealState_Mute;
1378 } else {
1379 /* change to state FADE-OUT */
1380 pConcealmentInfo->concealState = ConcealState_FadeOut;
1381 /* mode 0 just updates the Fading counter */
1382 CConcealment_ApplyFadeOut(
1383 /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1384 samplesPerFrame, pAacDecoderChannelInfo);
1385 }
The Android Open Source Project2228e362012-07-11 10:15:24 -07001386 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001387 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001388
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001389 case ConcealState_FadeOut:
1390 if (pConcealmentInfo->cntValidFrames >
1391 pConcealCommonData->numMuteReleaseFrames) {
1392 if (pConcealCommonData->numFadeInFrames > 0) {
1393 /* change to state FADE-IN */
1394 pConcealmentInfo->concealState = ConcealState_FadeIn;
1395 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1396 pConcealCommonData, pConcealmentInfo->cntFadeFrames,
1397 0 /* FadeOut -> FadeIn */);
1398 } else {
1399 /* change to state OK */
1400 pConcealmentInfo->concealState = ConcealState_Ok;
1401 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001402 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001403 if (frameOk) {
1404 /* we have good frame information but stay fully in concealment -
1405 * reset winGrpOffset/attGrpOffset */
1406 pConcealmentInfo->winGrpOffset[0] = 0;
1407 pConcealmentInfo->winGrpOffset[1] = 0;
1408 pConcealmentInfo->attGrpOffset[0] = 0;
1409 pConcealmentInfo->attGrpOffset[1] = 0;
1410 }
1411 if (pConcealmentInfo->cntFadeFrames >=
1412 pConcealCommonData->numFadeOutFrames) {
1413 /* change to state MUTE */
1414 pConcealmentInfo->concealState = ConcealState_Mute;
1415 } else /* Stay in FADE-OUT */
1416 {
1417 /* mode 0 just updates the Fading counter */
1418 CConcealment_ApplyFadeOut(
1419 /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1420 samplesPerFrame, pAacDecoderChannelInfo);
1421 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001422 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001423 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001424
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001425 case ConcealState_Mute:
1426 if (pConcealmentInfo->cntValidFrames >
1427 pConcealCommonData->numMuteReleaseFrames) {
1428 if (pConcealCommonData->numFadeInFrames > 0) {
1429 /* change to state FADE-IN */
1430 pConcealmentInfo->concealState = ConcealState_FadeIn;
1431 pConcealmentInfo->cntFadeFrames =
1432 pConcealCommonData->numFadeInFrames - 1;
1433 } else {
1434 /* change to state OK */
1435 pConcealmentInfo->concealState = ConcealState_Ok;
1436 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001437 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001438 if (frameOk) {
1439 /* we have good frame information but stay fully in concealment -
1440 * reset winGrpOffset/attGrpOffset */
1441 pConcealmentInfo->winGrpOffset[0] = 0;
1442 pConcealmentInfo->winGrpOffset[1] = 0;
1443 pConcealmentInfo->attGrpOffset[0] = 0;
1444 pConcealmentInfo->attGrpOffset[1] = 0;
1445 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001446 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001447 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001448
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001449 case ConcealState_FadeIn:
1450 pConcealmentInfo->cntFadeFrames -= 1;
1451 if (frameOk) {
1452 if (pConcealmentInfo->cntFadeFrames < 0) {
1453 /* change to state OK */
1454 pConcealmentInfo->concealState = ConcealState_Ok;
1455 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001456 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001457 if (pConcealCommonData->numFadeOutFrames > 0) {
1458 /* change to state FADE-OUT */
1459 pConcealmentInfo->concealState = ConcealState_FadeOut;
1460 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1461 pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1,
1462 1 /* FadeIn -> FadeOut */);
1463 pConcealmentInfo->winGrpOffset[0] = 0;
1464 pConcealmentInfo->winGrpOffset[1] = 0;
1465 pConcealmentInfo->attGrpOffset[0] = 0;
1466 pConcealmentInfo->attGrpOffset[1] = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001467
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001468 pConcealmentInfo
1469 ->cntFadeFrames--; /* decrease because
1470 CConcealment_ApplyFadeOut() will
1471 increase, accordingly */
1472 /* mode 0 just updates the Fading counter */
1473 CConcealment_ApplyFadeOut(
1474 /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo,
1475 samplesPerFrame, pAacDecoderChannelInfo);
1476 } else {
1477 /* change to state MUTE */
1478 pConcealmentInfo->concealState = ConcealState_Mute;
1479 }
1480 }
1481 break;
1482
1483 default:
1484 FDK_ASSERT(0);
1485 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001486 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001487 } break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001488
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001489 case ConcealMethodInter:
1490 case ConcealMethodTonal: {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001491 if (pConcealmentInfo->concealState != ConcealState_Ok) {
1492 /* count the valid frames during concealment process */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001493 if (pConcealmentInfo->prevFrameOk[1] ||
1494 (pConcealmentInfo->prevFrameOk[0] &&
1495 !pConcealmentInfo->prevFrameOk[1] && frameOk)) {
1496 /* The frame is OK even if it can be estimated by the energy
1497 * interpolation algorithm */
The Android Open Source Project2228e362012-07-11 10:15:24 -07001498 pConcealmentInfo->cntValidFrames += 1;
1499 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001500 pConcealmentInfo->cntValidFrames = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001501 }
1502 }
1503
1504 /* -- STATE MACHINE for energy interpolation -- */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001505 switch (pConcealmentInfo->concealState) {
1506 case ConcealState_Ok:
1507 if (!(pConcealmentInfo->prevFrameOk[1] ||
1508 (pConcealmentInfo->prevFrameOk[0] &&
1509 !pConcealmentInfo->prevFrameOk[1] && frameOk))) {
1510 if (pConcealCommonData->numFadeOutFrames > 0) {
1511 /* Fade out only if the energy interpolation algorithm can not be
1512 * applied! */
1513 pConcealmentInfo->concealState = ConcealState_FadeOut;
1514 } else {
1515 /* change to state MUTE */
1516 pConcealmentInfo->concealState = ConcealState_Mute;
1517 }
1518 pConcealmentInfo->cntFadeFrames = 0;
1519 pConcealmentInfo->cntValidFrames = 0;
1520 }
1521 break;
1522
1523 case ConcealState_Single:
1524 pConcealmentInfo->concealState = ConcealState_Ok;
1525 break;
1526
1527 case ConcealState_FadeOut:
1528 pConcealmentInfo->cntFadeFrames += 1;
1529
1530 if (pConcealmentInfo->cntValidFrames >
1531 pConcealCommonData->numMuteReleaseFrames) {
1532 if (pConcealCommonData->numFadeInFrames > 0) {
1533 /* change to state FADE-IN */
1534 pConcealmentInfo->concealState = ConcealState_FadeIn;
1535 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1536 pConcealCommonData, pConcealmentInfo->cntFadeFrames - 1,
1537 0 /* FadeOut -> FadeIn */);
1538 } else {
1539 /* change to state OK */
1540 pConcealmentInfo->concealState = ConcealState_Ok;
1541 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001542 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001543 if (pConcealmentInfo->cntFadeFrames >=
1544 pConcealCommonData->numFadeOutFrames) {
1545 /* change to state MUTE */
1546 pConcealmentInfo->concealState = ConcealState_Mute;
1547 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001548 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001549 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001550
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001551 case ConcealState_Mute:
1552 if (pConcealmentInfo->cntValidFrames >
1553 pConcealCommonData->numMuteReleaseFrames) {
1554 if (pConcealCommonData->numFadeInFrames > 0) {
1555 /* change to state FADE-IN */
1556 pConcealmentInfo->concealState = ConcealState_FadeIn;
1557 pConcealmentInfo->cntFadeFrames =
1558 pConcealCommonData->numFadeInFrames - 1;
1559 } else {
1560 /* change to state OK */
1561 pConcealmentInfo->concealState = ConcealState_Ok;
1562 }
1563 }
1564 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001565
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001566 case ConcealState_FadeIn:
1567 pConcealmentInfo->cntFadeFrames -=
1568 1; /* used to address the fade-in factors */
The Android Open Source Project2228e362012-07-11 10:15:24 -07001569
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001570 if (frameOk || pConcealmentInfo->prevFrameOk[1]) {
1571 if (pConcealmentInfo->cntFadeFrames < 0) {
1572 /* change to state OK */
1573 pConcealmentInfo->concealState = ConcealState_Ok;
1574 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001575 } else {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001576 if (pConcealCommonData->numFadeOutFrames > 0) {
1577 /* change to state FADE-OUT */
1578 pConcealmentInfo->concealState = ConcealState_FadeOut;
1579 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame(
1580 pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1,
1581 1 /* FadeIn -> FadeOut */);
1582 } else {
1583 /* change to state MUTE */
1584 pConcealmentInfo->concealState = ConcealState_Mute;
1585 }
Jean-Michel Trivi5016eb72013-08-27 16:28:09 -07001586 }
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001587 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001588 } /* End switch(pConcealmentInfo->concealState) */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001589 } break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001590
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001591 default:
1592 /* Don't need a state machine for other concealment methods. */
1593 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001594 }
The Android Open Source Project2228e362012-07-11 10:15:24 -07001595}
1596
The Android Open Source Project2228e362012-07-11 10:15:24 -07001597/*!
1598\brief Randomizes the sign of the spectral data
1599
1600 The function toggles the sign of the spectral data randomly. This is
1601 useful to ensure the quality of the concealed frames.
The Android Open Source Project2228e362012-07-11 10:15:24 -07001602 */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001603static void CConcealment_ApplyRandomSign(int randomPhase, FIXP_DBL *spec,
1604 int samplesPerFrame) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001605 int i;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001606 USHORT packedSign = 0;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001607
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001608 /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit
1609 */
The Android Open Source Project2228e362012-07-11 10:15:24 -07001610
1611 /* read current packed sign word */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001612 packedSign = AacDec_randomSign[randomPhase >> 4];
1613 packedSign >>= (randomPhase & 0xf);
The Android Open Source Project2228e362012-07-11 10:15:24 -07001614
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001615 for (i = 0; i < samplesPerFrame; i++) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001616 if ((randomPhase & 0xf) == 0) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001617 packedSign = AacDec_randomSign[randomPhase >> 4];
The Android Open Source Project2228e362012-07-11 10:15:24 -07001618 }
1619
1620 if (packedSign & 0x1) {
1621 spec[i] = -spec[i];
1622 }
1623 packedSign >>= 1;
1624
1625 randomPhase = (randomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
1626 }
1627}
1628
The Android Open Source Project2228e362012-07-11 10:15:24 -07001629/*!
1630 \brief Get fadeing factor for current concealment state.
1631
1632 The function returns the state (ok or not) of the previous frame.
1633 If called before the function CConcealment_Apply() set the fBeforeApply
1634 flag to get the correct value.
1635
1636 \return Frame OK flag of previous frame.
1637 */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001638int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo,
1639 const int fBeforeApply) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001640 int prevFrameOk = 1;
1641
1642 if (hConcealmentInfo != NULL) {
1643 prevFrameOk = hConcealmentInfo->prevFrameOk[fBeforeApply & 0x1];
1644 }
1645
1646 return prevFrameOk;
1647}
1648
1649/*!
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001650 \brief Get the number of delay frames introduced by concealment technique.
The Android Open Source Project2228e362012-07-11 10:15:24 -07001651
1652 \return Number of delay frames.
1653 */
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001654UINT CConcealment_GetDelay(CConcealParams *pConcealCommonData) {
The Android Open Source Project2228e362012-07-11 10:15:24 -07001655 UINT frameDelay = 0;
1656
1657 if (pConcealCommonData != NULL) {
1658 switch (pConcealCommonData->method) {
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001659 case ConcealMethodTonal:
1660 case ConcealMethodInter:
1661 frameDelay = 1;
1662 break;
1663 default:
1664 break;
The Android Open Source Project2228e362012-07-11 10:15:24 -07001665 }
1666 }
1667
1668 return frameDelay;
1669}
1670
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001671static int CConcealment_ApplyFadeOut(
1672 int mode, CConcealmentInfo *pConcealmentInfo,
1673 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
1674 const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) {
1675 /* mode 1 = apply RandomSign and mute spectral coefficients if necessary, *
1676 * mode 0 = Update cntFadeFrames */
1677
1678 /* restore frequency coefficients from buffer with a specific muting */
1679 int srcWin, dstWin, numWindows = 1;
1680 int windowLen = samplesPerFrame;
1681 int srcGrpStart = 0;
1682 int winIdxStride = 1;
1683 int numWinGrpPerFac, attIdx, attIdxStride;
1684 int i;
1685 int appliedProcessing = 0;
1686
1687 CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
1688 FIXP_DBL *pSpectralCoefficient =
1689 SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
1690 SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
1691
1692 /* set old window parameters */
1693 if (pConcealmentInfo->lastRenderMode == AACDEC_RENDER_LPD) {
1694 switch (pAacDecoderStaticChannelInfo->last_lpd_mode) {
1695 case 1:
1696 numWindows = 4;
1697 srcGrpStart = 3;
1698 windowLen = samplesPerFrame >> 2;
1699 break;
1700 case 2:
1701 numWindows = 2;
1702 srcGrpStart = 1;
1703 windowLen = samplesPerFrame >> 1;
1704 winIdxStride = 2;
1705 break;
1706 case 3:
1707 numWindows = 1;
1708 srcGrpStart = 0;
1709 windowLen = samplesPerFrame;
1710 winIdxStride = 4;
1711 break;
1712 }
1713 pConcealmentInfo->lastWinGrpLen = 1;
1714 } else {
1715 pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
1716 pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
1717
1718 if (pConcealmentInfo->windowSequence == BLOCK_SHORT) {
1719 /* short block handling */
1720 numWindows = 8;
1721 windowLen = samplesPerFrame >> 3;
1722 srcGrpStart = numWindows - pConcealmentInfo->lastWinGrpLen;
1723 }
1724 }
1725
1726 attIdxStride =
1727 fMax(1, (int)(numWindows / (pConcealmentInfo->lastWinGrpLen + 1)));
1728
1729 /* load last state */
1730 attIdx = pConcealmentInfo->cntFadeFrames;
1731 numWinGrpPerFac = pConcealmentInfo->attGrpOffset[mode];
1732 srcWin = srcGrpStart + pConcealmentInfo->winGrpOffset[mode];
1733
1734 FDK_ASSERT((srcGrpStart * windowLen + windowLen) <= samplesPerFrame);
1735 FDK_ASSERT((srcWin * windowLen + windowLen) <= 1024);
1736
1737 for (dstWin = 0; dstWin < numWindows; dstWin += 1) {
1738 FIXP_CNCL *pCncl =
1739 pConcealmentInfo->spectralCoefficient + (srcWin * windowLen);
1740 FIXP_DBL *pOut = pSpectralCoefficient + (dstWin * windowLen);
1741
1742 if (mode == 1) {
1743 /* mute if attIdx gets large enaugh */
1744 if (attIdx > pConcealmentInfo->pConcealParams->numFadeOutFrames) {
1745 FDKmemclear(pCncl, sizeof(FIXP_DBL) * windowLen);
1746 }
1747
1748 /* restore frequency coefficients from buffer - attenuation is done later
1749 */
1750 for (i = 0; i < windowLen; i++) {
1751 pOut[i] = pCncl[i];
1752 }
1753
1754 /* apply random change of sign for spectral coefficients */
1755 CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, pOut,
1756 windowLen);
1757
1758 /* Increment random phase index to avoid repetition artifacts. */
1759 pConcealmentInfo->iRandomPhase =
1760 (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
1761
1762 /* set old scale factors */
1763 pSpecScale[dstWin * winIdxStride] =
1764 pConcealmentInfo->specScale[srcWin * winIdxStride];
1765 }
1766
1767 srcWin += 1;
1768
1769 if (srcWin >= numWindows) {
1770 /* end of sequence -> rewind to first window of group */
1771 srcWin = srcGrpStart;
1772 numWinGrpPerFac += 1;
1773 if (numWinGrpPerFac >= attIdxStride) {
1774 numWinGrpPerFac = 0;
1775 attIdx += 1;
1776 }
1777 }
1778 }
1779
1780 /* store current state */
1781
1782 pConcealmentInfo->winGrpOffset[mode] = srcWin - srcGrpStart;
1783 FDK_ASSERT((pConcealmentInfo->winGrpOffset[mode] >= 0) &&
1784 (pConcealmentInfo->winGrpOffset[mode] < 8));
1785 pConcealmentInfo->attGrpOffset[mode] = numWinGrpPerFac;
1786 FDK_ASSERT((pConcealmentInfo->attGrpOffset[mode] >= 0) &&
1787 (pConcealmentInfo->attGrpOffset[mode] < attIdxStride));
1788
1789 if (mode == 0) {
1790 pConcealmentInfo->cntFadeFrames = attIdx;
1791 }
1792
1793 appliedProcessing = 1;
1794
1795 return appliedProcessing;
1796}
1797
1798/*!
1799 \brief Do Time domain fading (TDFading) in concealment case
1800
1801 In case of concealment, this function takes care of the fading, after time
1802domain signal has been rendered by the respective signal rendering functions.
1803 The fading out in case of ACELP decoding is not done by this function but by
1804the ACELP decoder for the first concealed frame if CONCEAL_CORE_IGNORANT_FADE is
1805not set.
1806
1807 TimeDomain fading never creates jumps in energy / discontinuities, it always
1808does a continuous fading. To achieve this, fading is always done from a starting
1809point to a target point, while the starting point is always determined to be the
1810last target point. By varying the target point of a fading, the fading slope can
1811be controlled.
1812
1813 This principle is applied to the fading within a frame and the fading from
1814frame to frame.
1815
1816 One frame is divided into 8 subframes to obtain 8 parts of fading slopes
1817within a frame, each maybe with its own gradient.
1818
1819 Workflow:
1820 1.) Determine Fading behavior and end-of-frame target fading level, based on
1821concealmentState (determined by CConcealment_UpdateState()) and the core mode.
1822 - By _DEFAULT_,
1823 The target fading level is determined by fadeOutFactor[cntFadeFrames]
1824in case of fadeOut, or fadeInFactor[cntFadeFrames] in case of fadeIn.
1825 --> fading type is FADE_TIMEDOMAIN in this case. Target fading level
1826is determined by fading index cntFadeFrames.
1827
1828 - If concealmentState is signalling a _MUTED SIGNAL_,
1829 TDFading decays to 0 within 1/8th of a frame if numFadeOutFrames == 0.
1830 --> fading type is FADE_TIMEDOMAIN_TOSPECTRALMUTE in this case.
1831
1832 - If concealmentState is signalling the _END OF MUTING_,
1833 TDFading fades to target fading level within 1/8th of a frame if
1834numFadeInFrames == 0.
1835 --> fading type is FADE_TIMEDOMAIN_FROMSPECTRALMUTE in this case.
1836Target fading level is determined by fading index cntFadeFrames.
1837
1838#ifndef CONCEAL_CORE_IGNORANT_FADE
1839 - In case of an _ACELP FADEOUT_,
1840 TDFading leaves fading control to ACELP decoder for 1/2 frame.
1841 --> fading type is FADE_ACELPDOMAIN in this case.
1842#endif
1843
1844 2.) Render fading levels within current frame and do the final fading:
1845 Map Fading slopes to fading levels and apply to time domain signal.
1846
1847
1848*/
1849
1850INT CConcealment_TDFading(
1851 int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo,
1852 FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1) {
1853 /*
1854 Do the fading in Time domain based on concealment states and core mode
1855 */
1856 FIXP_DBL fadeStop, attMute = (FIXP_DBL)0;
1857 int idx = 0, ii;
1858 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo =
1859 *ppAacDecoderStaticChannelInfo;
1860 CConcealmentInfo *pConcealmentInfo =
1861 &pAacDecoderStaticChannelInfo->concealmentInfo;
1862 CConcealParams *pConcealParams = pConcealmentInfo->pConcealParams;
1863 const CConcealmentState concealState = pConcealmentInfo->concealState;
1864 TDfadingType fadingType;
1865 FIXP_DBL fadingStations[9] = {0};
1866 int fadingSteps[8] = {0};
1867 const FIXP_DBL fadeStart =
1868 pConcealmentInfo
1869 ->fade_old; /* start fading at last end-of-frame attenuation */
1870 FIXP_SGL *fadeFactor = pConcealParams->fadeOutFactor;
1871 const INT cntFadeFrames = pConcealmentInfo->cntFadeFrames;
1872 int TDFadeOutStopBeforeMute = 1;
1873 int TDFadeInStopBeforeFullLevel = 1;
1874
1875 /*
1876 determine Fading behaviour (end-of-frame attenuation and fading type) (1.)
1877 */
1878
1879 switch (concealState) {
1880 case ConcealState_Single:
1881 case ConcealState_Mute:
1882 case ConcealState_FadeOut:
1883 idx = (pConcealParams->method == ConcealMethodNoise) ? cntFadeFrames - 1
1884 : cntFadeFrames;
1885 fadingType = FADE_TIMEDOMAIN;
1886
1887 if (concealState == ConcealState_Mute ||
1888 (cntFadeFrames + TDFadeOutStopBeforeMute) >
1889 pConcealmentInfo->pConcealParams->numFadeOutFrames) {
1890 fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE;
1891 }
1892
1893 break;
1894 case ConcealState_FadeIn:
1895 idx = cntFadeFrames;
1896 idx -= TDFadeInStopBeforeFullLevel;
Fraunhofer IIS FDK64134e62018-10-19 16:37:31 +02001897 FDK_FALLTHROUGH;
Fraunhofer IIS FDK6cfabd32018-02-26 20:17:00 +01001898 case ConcealState_Ok:
1899 fadeFactor = pConcealParams->fadeInFactor;
1900 idx = (concealState == ConcealState_Ok) ? -1 : idx;
1901 fadingType = (pConcealmentInfo->concealState_old == ConcealState_Mute)
1902 ? FADE_TIMEDOMAIN_FROMSPECTRALMUTE
1903 : FADE_TIMEDOMAIN;
1904 break;
1905 default:
1906 FDK_ASSERT(0);
1907 fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE;
1908 break;
1909 }
1910
1911 /* determine Target end-of-frame fading level and fading slope */
1912 switch (fadingType) {
1913 case FADE_TIMEDOMAIN_FROMSPECTRALMUTE:
1914 fadeStop =
1915 (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]);
1916 if (pConcealmentInfo->pConcealParams->numFadeInFrames == 0) {
1917 /* do step as fast as possible */
1918 fadingSteps[0] = 1;
1919 break;
1920 }
1921 CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]);
1922 break;
1923 case FADE_TIMEDOMAIN:
1924 fadeStop =
1925 (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]);
1926 CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]);
1927 break;
1928 case FADE_TIMEDOMAIN_TOSPECTRALMUTE:
1929 fadeStop = attMute;
1930 if (pConcealmentInfo->pConcealParams->numFadeOutFrames == 0) {
1931 /* do step as fast as possible */
1932 fadingSteps[0] = 1;
1933 break;
1934 }
1935 CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]);
1936 break;
1937 }
1938
1939 /*
1940 Render fading levels within current frame and do the final fading (2.)
1941 */
1942
1943 len >>= 3;
1944 CConcealment_TDFadeFillFadingStations(fadingStations, fadingSteps, fadeStop,
1945 fadeStart, fadingType);
1946
1947 if ((fadingStations[8] != (FIXP_DBL)MAXVAL_DBL) ||
1948 (fadingStations[7] != (FIXP_DBL)MAXVAL_DBL) ||
1949 (fadingStations[6] != (FIXP_DBL)MAXVAL_DBL) ||
1950 (fadingStations[5] != (FIXP_DBL)MAXVAL_DBL) ||
1951 (fadingStations[4] != (FIXP_DBL)MAXVAL_DBL) ||
1952 (fadingStations[3] != (FIXP_DBL)MAXVAL_DBL) ||
1953 (fadingStations[2] != (FIXP_DBL)MAXVAL_DBL) ||
1954 (fadingStations[1] != (FIXP_DBL)MAXVAL_DBL) ||
1955 (fadingStations[0] !=
1956 (FIXP_DBL)MAXVAL_DBL)) /* if there's something to fade */
1957 {
1958 int start = 0;
1959 for (ii = 0; ii < 8; ii++) {
1960 CConcealment_TDFadePcmAtt(start, len, fadingStations[ii],
1961 fadingStations[ii + 1], pcmdata);
1962 start += len;
1963 }
1964 }
1965 CConcealment_TDNoise_Apply(pConcealmentInfo, len, pcmdata);
1966
1967 /* Save end-of-frame attenuation and fading type */
1968 pConcealmentInfo->lastFadingType = fadingType;
1969 pConcealmentInfo->fade_old = fadeStop;
1970 pConcealmentInfo->concealState_old = concealState;
1971
1972 return 1;
1973}
1974
1975/* attenuate pcmdata in Time Domain Fading process */
1976static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart,
1977 FIXP_DBL fadeStop, FIXP_PCM *pcmdata) {
1978 int i;
1979 FIXP_DBL dStep;
1980 FIXP_DBL dGain;
1981 FIXP_DBL dGain_apply;
1982 int bitshift = (DFRACT_BITS - SAMPLE_BITS);
1983
1984 /* set start energy */
1985 dGain = fadeStart;
1986 /* determine energy steps from sample to sample */
1987 dStep = (FIXP_DBL)((int)((fadeStart >> 1) - (fadeStop >> 1)) / len) << 1;
1988
1989 for (i = start; i < (start + len); i++) {
1990 dGain -= dStep;
1991 /* prevent gain from getting negative due to possible fixpoint inaccuracies
1992 */
1993 dGain_apply = fMax((FIXP_DBL)0, dGain);
1994 /* finally, attenuate samples */
1995 pcmdata[i] = (FIXP_PCM)((fMult(pcmdata[i], (dGain_apply))) >> bitshift);
1996 }
1997}
1998
1999/*
2000\brief Fill FadingStations
2001
2002The fadingstations are the attenuation factors, being applied to its dedicated
2003portions of pcm data. They are calculated using the fadingsteps. One fadingstep
2004is the weighted contribution to the fading slope within its dedicated portion of
2005pcm data.
2006
2007*Fadingsteps : 0 0 0 1 0 1 2 0
2008
2009 |<- 1 Frame pcm data ->|
2010 fadeStart-->|__________ |
2011 ^ ^ ^ ^ \____ |
2012 Attenuation : | | | | ^ ^\__ |
2013 | | | | | | ^\ |
2014 | | | | | | | \___|<-- fadeStop
2015 | | | | | | | ^ ^
2016 | | | | | | | | |
2017Fadingstations: [0][1][2][3][4][5][6][7][8]
2018
2019(Fadingstations "[0]" is "[8] from previous frame", therefore its not meaningful
2020to be edited)
2021
2022*/
2023static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations,
2024 int *fadingSteps,
2025 FIXP_DBL fadeStop,
2026 FIXP_DBL fadeStart,
2027 TDfadingType fadingType) {
2028 int i;
2029 INT fadingSteps_sum = 0;
2030 INT fadeDiff;
2031
2032 fadingSteps_sum = fadingSteps[0] + fadingSteps[1] + fadingSteps[2] +
2033 fadingSteps[3] + fadingSteps[4] + fadingSteps[5] +
2034 fadingSteps[6] + fadingSteps[7];
2035 fadeDiff = ((INT)(fadeStop - fadeStart) / fMax(fadingSteps_sum, (INT)1));
2036 fadingStations[0] = fadeStart;
2037 for (i = 1; i < 8; i++) {
2038 fadingStations[i] =
2039 fadingStations[i - 1] + (FIXP_DBL)(fadeDiff * fadingSteps[i - 1]);
2040 }
2041 fadingStations[8] = fadeStop;
2042}
2043
2044static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps) {
2045 fadingSteps[0] = fadingSteps[1] = fadingSteps[2] = fadingSteps[3] =
2046 fadingSteps[4] = fadingSteps[5] = fadingSteps[6] = fadingSteps[7] = 1;
2047}
2048
2049/* end of TimeDomainFading functions */
2050
2051/* derived from int UsacRandomSign() */
2052static int CConcealment_TDNoise_Random(ULONG *seed) {
2053 *seed = (ULONG)(((UINT64)(*seed) * 69069) + 5);
2054 return (int)(*seed);
2055}
2056
2057static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo,
2058 const int len, FIXP_PCM *const pcmdata) {
2059 FIXP_PCM *states = pConcealmentInfo->TDNoiseStates;
2060 FIXP_PCM noiseVal;
2061 FIXP_DBL noiseValLong;
2062 FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef;
2063 FIXP_DBL TDNoiseAtt;
2064 ULONG seed = pConcealmentInfo->TDNoiseSeed =
2065 (ULONG)CConcealment_TDNoise_Random(&pConcealmentInfo->TDNoiseSeed) + 1;
2066
2067 TDNoiseAtt = pConcealmentInfo->pConcealParams->comfortNoiseLevel;
2068
2069 int ii;
2070
2071 if ((pConcealmentInfo->concealState != ConcealState_Ok ||
2072 pConcealmentInfo->concealState_old != ConcealState_Ok) &&
2073 TDNoiseAtt != (FIXP_DBL)0) {
2074 for (ii = 0; ii < (len << 3); ii++) {
2075 /* create filtered noise */
2076 states[2] = states[1];
2077 states[1] = states[0];
2078 states[0] = ((FIXP_PCM)CConcealment_TDNoise_Random(&seed));
2079 noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) +
2080 fMult(states[2], coef[2]);
2081 noiseVal = FX_DBL2FX_PCM(fMult(noiseValLong, TDNoiseAtt));
2082
2083 /* add filtered noise - check for clipping, before */
2084 if (pcmdata[ii] > (FIXP_PCM)MAXVAL_FIXP_PCM - noiseVal &&
2085 noiseVal > (FIXP_PCM)0) {
2086 noiseVal = noiseVal * (FIXP_PCM)-1;
2087 } else if (pcmdata[ii] < (FIXP_PCM)MINVAL_FIXP_PCM - noiseVal &&
2088 noiseVal < (FIXP_PCM)0) {
2089 noiseVal = noiseVal * (FIXP_PCM)-1;
2090 }
2091
2092 pcmdata[ii] += noiseVal;
2093 }
2094 }
2095}