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