Imported Debian version 0.1.3.1
[deb_fdk-aac.git] / libAACdec / src / conceal.cpp
1
2 /* -----------------------------------------------------------------------------------------------------------
3 Software 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
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
17
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
28
29 2. COPYRIGHT LICENSE
30
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
33
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
36
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
41
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
47
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and 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
53 3. NO PATENT LICENSE
54
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
58
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61
62 4. DISCLAIMER
63
64 This 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
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
72
73 5. CONTACT INFORMATION
74
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79
80 www.iis.fraunhofer.de/amm
81 amm-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
166 typedef enum {
167 CConcealment_NoExpand,
168 CConcealment_Expand,
169 CConcealment_Compress
170 }
171 CConcealmentExpandType;
172
173 static 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
183 static void
184 CConcealment_CalcBandEnergy (
185 FIXP_DBL *spectrum,
186 const SamplingRateInfo *pSamplingRateInfo,
187 const int blockType,
188 CConcealmentExpandType ex,
189 int *sfbEnergy
190 );
191
192 static 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
204 static 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
216 static 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
226 static void
227 CConcealment_UpdateState (
228 CConcealmentInfo *pConcealmentInfo,
229 int frameOk
230 );
231
232 static void
233 CConcealment_ApplyRandomSign (
234 int iRandomPhase,
235 FIXP_DBL *spec,
236 int samplesPerFrame
237 );
238
239
240 static 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 */
262 void
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 */
298 CConcealmentMethod
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 */
320 void
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 */
364 AAC_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 */
468 AAC_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 */
546 CConcealmentState
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
561 static 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 */
650 void
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 */
728 int
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 if ( !frameOk )
766 {
767 /* Create data for signal rendering according to the selected concealment method and decoder operating mode. */
768
769
770 if ( !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD
771 )
772 )
773 {
774 switch (hConcealmentInfo->pConcealParams->method)
775 {
776 default:
777 case ConcealMethodMute:
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 break;
784
785 case ConcealMethodNoise:
786 /* Noise substitution error concealment technique */
787 appliedProcessing =
788 CConcealment_ApplyNoise (hConcealmentInfo,
789 pAacDecoderChannelInfo,
790 pAacDecoderStaticChannelInfo,
791 pSamplingRateInfo,
792 samplesPerFrame,
793 flags);
794 break;
795
796 case ConcealMethodInter:
797 /* Energy interpolation concealment based on 3GPP */
798 appliedProcessing =
799 CConcealment_ApplyInter (hConcealmentInfo,
800 pAacDecoderChannelInfo,
801 pSamplingRateInfo,
802 samplesPerFrame,
803 0, /* don't use tonal improvement */
804 0);
805 break;
806
807 }
808 }
809 }
810 /* update history */
811 hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1];
812 hConcealmentInfo->prevFrameOk[1] = frameOk;
813
814 return appliedProcessing;
815 }
816
817 /*!
818 \brief Apply concealment noise substitution
819
820 In case of frame lost this function produces a noisy frame with respect to the
821 energies values of past frame.
822
823 \return none
824 */
825 static int
826 CConcealment_ApplyNoise (CConcealmentInfo *pConcealmentInfo,
827 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
828 CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
829 const SamplingRateInfo *pSamplingRateInfo,
830 const int samplesPerFrame,
831 const UINT flags)
832 {
833 CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
834
835 FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
836 SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
837 CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
838
839 int appliedProcessing = 0;
840
841 FDK_ASSERT((samplesPerFrame>=480) && (samplesPerFrame<=1024));
842 FDK_ASSERT((samplesPerFrame&0x1F) == 0);
843
844 switch (pConcealmentInfo->concealState)
845 {
846 case ConcealState_Ok:
847 /* Nothing to do here! */
848 break;
849
850 case ConcealState_Single:
851 case ConcealState_FadeOut:
852 {
853 /* restore frequency coefficients from buffer with a specific muting */
854 FIXP_SGL fac;
855 int win, numWindows = 1;
856 int windowLen = samplesPerFrame;
857 int tFadeFrames, lastWindow = 0;
858 int win_idx_stride = 1;
859
860 FDK_ASSERT(pConcealmentInfo != NULL);
861 FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
862 FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
863 FDK_ASSERT(pConcealmentInfo->cntFadeFrames <= pConcealCommonData->numFadeOutFrames);
864
865 /* get attenuation factor */
866 tFadeFrames = pConcealmentInfo->cntFadeFrames;
867 fac = pConcealCommonData->fadeOutFactor[tFadeFrames];
868
869 /* set old window parameters */
870 {
871 pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
872 pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
873
874 if (pConcealmentInfo->windowSequence == 2) {
875 /* short block handling */
876 numWindows = 8;
877 windowLen = samplesPerFrame >> 3;
878 lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen;
879 }
880 }
881
882 for (win = 0; win < numWindows; win++) {
883 FIXP_CNCL *pCncl = pConcealmentInfo->spectralCoefficient + (lastWindow * windowLen);
884 FIXP_DBL *pOut = pSpectralCoefficient + (win * windowLen);
885 int i;
886
887 FDK_ASSERT((lastWindow * windowLen + windowLen) <= samplesPerFrame);
888
889 /* restore frequency coefficients from buffer with a specific attenuation */
890 for (i = 0; i < windowLen; i++) {
891 pOut[i] = fMult(pCncl[i], fac);
892 }
893
894 /* apply random change of sign for spectral coefficients */
895 CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase,
896 pOut,
897 windowLen );
898
899 /* Increment random phase index to avoid repetition artifacts. */
900 pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
901
902 /* set old scale factors */
903 pSpecScale[win*win_idx_stride] = pConcealmentInfo->specScale[win_idx_stride*lastWindow++];
904
905 if ( (lastWindow >= numWindows)
906 && (numWindows > 1) )
907 {
908 /* end of sequence -> rewind */
909 lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen;
910 /* update the attenuation factor to get a faster fade-out */
911 tFadeFrames += 1;
912 if (tFadeFrames < pConcealCommonData->numFadeOutFrames) {
913 fac = pConcealCommonData->fadeOutFactor[tFadeFrames];
914 } else {
915 fac = (FIXP_SGL)0;
916 }
917 }
918 }
919
920 /* store temp vars */
921 pConcealmentInfo->cntFadeFrames = tFadeFrames;
922 appliedProcessing = 1;
923 }
924 break;
925
926 case ConcealState_Mute:
927 {
928 /* set dummy window parameters */
929 pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
930 pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */
931 pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
932 pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */
933
934 /* mute spectral data */
935 FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
936
937 if ( !(flags & (AC_USAC|AC_RSVD50))
938 && pConcealCommonData->comfortNoiseLevel >= 0
939 && pConcealCommonData->comfortNoiseLevel <= 61 /* -90dB */)
940 {
941 /* insert comfort noise using PNS */
942 CConcealment_fakePnsData (
943 &pAacDecoderChannelInfo->data.aac.PnsData,
944 pIcsInfo,
945 pSamplingRateInfo,
946 pAacDecoderChannelInfo->pDynData->aSfbScale,
947 pAacDecoderChannelInfo->pDynData->aScaleFactor,
948 pConcealCommonData->comfortNoiseLevel
949 );
950
951 CPns_Apply (
952 &pAacDecoderChannelInfo->data.aac.PnsData,
953 pIcsInfo,
954 pAacDecoderChannelInfo->pSpectralCoefficient,
955 pAacDecoderChannelInfo->specScale,
956 pAacDecoderChannelInfo->pDynData->aScaleFactor,
957 pSamplingRateInfo,
958 pAacDecoderChannelInfo->granuleLength,
959 0 /* always apply to first channel */
960 );
961 }
962 appliedProcessing = 1;
963 }
964 break;
965
966 case ConcealState_FadeIn:
967 {
968 FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
969 FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
970 FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames);
971
972 /* attenuate signal to get a smooth fade-in */
973 FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1];
974 FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames];
975 int i;
976
977 for (i = samplesPerFrame; i != 0; i--) {
978 *pOut = fMult(*pOut, fac);
979 pOut--;
980 }
981 appliedProcessing = 1;
982 }
983 break;
984
985 default:
986 /* we shouldn't come here anyway */
987 FDK_ASSERT(0);
988 break;
989 }
990
991 return appliedProcessing;
992 }
993
994
995 /*!
996 \brief Apply concealment interpolation
997
998 The function swaps the data from the current and the previous frame. If an
999 error has occured, frame interpolation is performed to restore the missing
1000 frame. In case of multiple faulty frames, fade-in and fade-out is applied.
1001
1002 \return none
1003 */
1004 static int
1005 CConcealment_ApplyInter (
1006 CConcealmentInfo *pConcealmentInfo,
1007 CAacDecoderChannelInfo *pAacDecoderChannelInfo,
1008 const SamplingRateInfo *pSamplingRateInfo,
1009 const int samplesPerFrame,
1010 const int improveTonal,
1011 const int frameOk )
1012 {
1013 CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
1014
1015 FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
1016 CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
1017 SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
1018
1019
1020 int sfbEnergyPrev[64];
1021 int sfbEnergyAct [64];
1022
1023 int i, appliedProcessing = 0;
1024
1025 /* clear/init */
1026 FDKmemclear(sfbEnergyPrev, 64 * sizeof(int));
1027 FDKmemclear(sfbEnergyAct, 64 * sizeof(int));
1028
1029
1030 if (!frameOk)
1031 {
1032 /* Restore last frame from concealment buffer */
1033 pIcsInfo->WindowShape = pConcealmentInfo->windowShape;
1034 pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence;
1035
1036 /* Restore spectral data */
1037 for (i = 0; i < samplesPerFrame; i++) {
1038 pSpectralCoefficient[i] = FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]);
1039 }
1040
1041 /* Restore scale factors */
1042 FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8*sizeof(SHORT));
1043 }
1044
1045 /* if previous frame was not ok */
1046 if (!pConcealmentInfo->prevFrameOk[1]) {
1047
1048 /* if current frame (f_n) is ok and the last but one frame (f_(n-2))
1049 was ok, too, then interpolate both frames in order to generate
1050 the current output frame (f_(n-1)). Otherwise, use the last stored
1051 frame (f_(n-2) or f_(n-3) or ...). */
1052 if (frameOk && pConcealmentInfo->prevFrameOk[0])
1053 {
1054 appliedProcessing = 1;
1055
1056
1057 /* Interpolate both frames in order to generate the current output frame (f_(n-1)). */
1058 if (pIcsInfo->WindowSequence == EightShortSequence) {
1059 /* f_(n-2) == EightShortSequence */
1060 /* short--??????--short, short--??????--long interpolation */
1061 /* short--short---short, short---long---long interpolation */
1062
1063 int wnd;
1064
1065 if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */
1066 /* short--short---short interpolation */
1067
1068 int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
1069 const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
1070 pIcsInfo->WindowShape = 1;
1071 pIcsInfo->WindowSequence = EightShortSequence;
1072
1073 for (wnd = 0; wnd < 8; wnd++)
1074 {
1075 CConcealment_CalcBandEnergy(
1076 &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-2) */
1077 pSamplingRateInfo,
1078 EightShortSequence,
1079 CConcealment_NoExpand,
1080 sfbEnergyPrev);
1081
1082 CConcealment_CalcBandEnergy(
1083 &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_n */
1084 pSamplingRateInfo,
1085 EightShortSequence,
1086 CConcealment_NoExpand,
1087 sfbEnergyAct);
1088
1089 CConcealment_InterpolateBuffer(
1090 &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-1) */
1091 &pSpecScale[wnd],
1092 &pConcealmentInfo->specScale[wnd],
1093 &pSpecScale[wnd],
1094 sfbEnergyPrev,
1095 sfbEnergyAct,
1096 scaleFactorBandsTotal,
1097 pSfbOffset);
1098
1099 }
1100 } else { /* f_n != EightShortSequence */
1101 /* short---long---long interpolation */
1102
1103 int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1104 const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1105 SHORT specScaleOut;
1106
1107 CConcealment_CalcBandEnergy(&pSpectralCoefficient[samplesPerFrame - (samplesPerFrame / 8)], /* [wnd] spec_(n-2) */
1108 pSamplingRateInfo,
1109 EightShortSequence,
1110 CConcealment_Expand,
1111 sfbEnergyAct);
1112
1113 CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */
1114 pSamplingRateInfo,
1115 OnlyLongSequence,
1116 CConcealment_NoExpand,
1117 sfbEnergyPrev);
1118
1119 pIcsInfo->WindowShape = 0;
1120 pIcsInfo->WindowSequence = LongStopSequence;
1121
1122 for (i = 0; i < samplesPerFrame ; i++) {
1123 pSpectralCoefficient[i] = pConcealmentInfo->spectralCoefficient[i]; /* spec_n */
1124 }
1125
1126 for (i = 0; i < 8; i++) { /* search for max(specScale) */
1127 if (pSpecScale[i] > pSpecScale[0]) {
1128 pSpecScale[0] = pSpecScale[i];
1129 }
1130 }
1131
1132 CConcealment_InterpolateBuffer(
1133 pSpectralCoefficient, /* spec_(n-1) */
1134 &pConcealmentInfo->specScale[0],
1135 &pSpecScale[0],
1136 &specScaleOut,
1137 sfbEnergyPrev,
1138 sfbEnergyAct,
1139 scaleFactorBandsTotal,
1140 pSfbOffset);
1141
1142 pSpecScale[0] = specScaleOut;
1143 }
1144 } else {
1145 /* long--??????--short, long--??????--long interpolation */
1146 /* long---long---short, long---long---long interpolation */
1147
1148 int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1149 const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1150 SHORT specScaleAct = pConcealmentInfo->specScale[0];
1151
1152 CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */
1153 pSamplingRateInfo,
1154 OnlyLongSequence,
1155 CConcealment_NoExpand,
1156 sfbEnergyPrev);
1157
1158 if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */
1159 /* long---long---short interpolation */
1160
1161 pIcsInfo->WindowShape = 1;
1162 pIcsInfo->WindowSequence = LongStartSequence;
1163
1164 for (i = 1; i < 8; i++) { /* search for max(specScale) */
1165 if (pConcealmentInfo->specScale[i] > specScaleAct) {
1166 specScaleAct = pConcealmentInfo->specScale[i];
1167 }
1168 }
1169
1170 /* Expand first short spectrum */
1171 CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */
1172 pSamplingRateInfo,
1173 EightShortSequence,
1174 CConcealment_Expand, /* !!! */
1175 sfbEnergyAct);
1176 } else {
1177 /* long---long---long interpolation */
1178
1179 pIcsInfo->WindowShape = 0;
1180 pIcsInfo->WindowSequence = OnlyLongSequence;
1181
1182 CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */
1183 pSamplingRateInfo,
1184 OnlyLongSequence,
1185 CConcealment_NoExpand,
1186 sfbEnergyAct);
1187 }
1188
1189 CConcealment_InterpolateBuffer(
1190 pSpectralCoefficient, /* spec_(n-1) */
1191 &pSpecScale[0],
1192 &specScaleAct,
1193 &pSpecScale[0],
1194 sfbEnergyPrev,
1195 sfbEnergyAct,
1196 scaleFactorBandsTotal,
1197 pSfbOffset);
1198
1199 }
1200 }
1201
1202 /* Noise substitution of sign of the output spectral coefficients */
1203 CConcealment_ApplyRandomSign (pConcealmentInfo->iRandomPhase,
1204 pSpectralCoefficient,
1205 samplesPerFrame);
1206 /* Increment random phase index to avoid repetition artifacts. */
1207 pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
1208 }
1209
1210 /* scale spectrum according to concealment state */
1211 switch (pConcealmentInfo->concealState)
1212 {
1213 case ConcealState_Single:
1214 appliedProcessing = 1;
1215 break;
1216
1217 case ConcealState_FadeOut:
1218 {
1219 FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
1220 FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
1221 FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeOutFrames);
1222
1223 /* restore frequency coefficients from buffer with a specific muting */
1224 FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1];
1225 FIXP_SGL fac = pConcealCommonData->fadeOutFactor[pConcealmentInfo->cntFadeFrames];
1226
1227 for (i = samplesPerFrame; i != 0; i--) {
1228 *pOut = fMult(*pOut, fac);
1229 pOut--;
1230 }
1231 appliedProcessing = 1;
1232 }
1233 break;
1234
1235 case ConcealState_FadeIn:
1236 {
1237 FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0);
1238 FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS);
1239 FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames);
1240
1241 /* attenuate signal to get a smooth fade-in */
1242 FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1];
1243 FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames];
1244
1245 for (i = samplesPerFrame; i != 0; i--) {
1246 *pOut = fMult(*pOut, fac);
1247 pOut--;
1248 }
1249 appliedProcessing = 1;
1250 }
1251 break;
1252
1253 case ConcealState_Mute:
1254 {
1255 int fac = pConcealCommonData->comfortNoiseLevel;
1256
1257 /* set dummy window parameters */
1258 pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */
1259 pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */
1260 pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence);
1261 pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */
1262
1263 /* mute spectral data */
1264 FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
1265
1266 if (fac >= 0 && fac <= 61) {
1267 /* insert comfort noise using PNS */
1268 CConcealment_fakePnsData (
1269 &pAacDecoderChannelInfo->data.aac.PnsData,
1270 pIcsInfo,
1271 pSamplingRateInfo,
1272 pAacDecoderChannelInfo->specScale,
1273 pAacDecoderChannelInfo->pDynData->aScaleFactor,
1274 fac
1275 );
1276
1277 CPns_Apply (
1278 &pAacDecoderChannelInfo->data.aac.PnsData,
1279 pIcsInfo,
1280 pAacDecoderChannelInfo->pSpectralCoefficient,
1281 pAacDecoderChannelInfo->specScale,
1282 pAacDecoderChannelInfo->pDynData->aScaleFactor,
1283 pSamplingRateInfo,
1284 pAacDecoderChannelInfo->granuleLength,
1285 0 /* always apply to first channel */
1286 );
1287 }
1288 appliedProcessing = 1;
1289 }
1290 break;
1291
1292 default:
1293 /* nothing to do here */
1294 break;
1295 }
1296
1297 return appliedProcessing;
1298 }
1299
1300
1301 /*!
1302 \brief Calculate the spectral energy
1303
1304 The function calculates band-wise the spectral energy. This is used for
1305 frame interpolation.
1306
1307 \return none
1308 */
1309 static void
1310 CConcealment_CalcBandEnergy (
1311 FIXP_DBL *spectrum,
1312 const SamplingRateInfo *pSamplingRateInfo,
1313 const int blockType,
1314 CConcealmentExpandType expandType,
1315 int *sfbEnergy )
1316 {
1317 const SHORT *pSfbOffset;
1318 int line, sfb, scaleFactorBandsTotal = 0;
1319
1320 /* In the following calculations, enAccu is initialized with LSB-value in order to avoid zero energy-level */
1321
1322 line = 0;
1323
1324 switch(blockType) {
1325
1326 case OnlyLongSequence:
1327 case LongStartSequence:
1328 case LongStopSequence:
1329
1330 if (expandType == CConcealment_NoExpand) {
1331 /* standard long calculation */
1332 scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1333 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1334
1335 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1336 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1337 int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
1338 /* scaling depends on sfb width. */
1339 for ( ; line < pSfbOffset[sfb+1]; line++) {
1340 enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
1341 }
1342 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1343 }
1344 }
1345 else {
1346 /* compress long to short */
1347 scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
1348 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
1349
1350 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1351 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1352 int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
1353 /* scaling depends on sfb width. */
1354 for (; line < pSfbOffset[sfb+1] << 3; line++) {
1355 enAccu += (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3;
1356 }
1357 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1358 }
1359 }
1360 break;
1361
1362 case EightShortSequence:
1363
1364 if (expandType == CConcealment_NoExpand) {
1365 /* standard short calculation */
1366 scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
1367 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short;
1368
1369 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1370 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1371 int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
1372 /* scaling depends on sfb width. */
1373 for ( ; line < pSfbOffset[sfb+1]; line++) {
1374 enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale;
1375 }
1376 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1377 }
1378 }
1379 else {
1380 /* expand short to long spectrum */
1381 scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
1382 pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long;
1383
1384 for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) {
1385 FIXP_DBL enAccu = (FIXP_DBL)(LONG)1;
1386 int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1;
1387 /* scaling depends on sfb width. */
1388 for ( ; line < pSfbOffset[sfb+1]; line++) {
1389 enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale;
1390 }
1391 *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1;
1392 }
1393 }
1394 break;
1395 }
1396 }
1397
1398
1399 /*!
1400 \brief Interpolate buffer
1401
1402 The function creates the interpolated spectral data according to the
1403 energy of the last good frame and the current (good) frame.
1404
1405 \return none
1406 */
1407 static void
1408 CConcealment_InterpolateBuffer (
1409 FIXP_DBL *spectrum,
1410 SHORT *pSpecScalePrv,
1411 SHORT *pSpecScaleAct,
1412 SHORT *pSpecScaleOut,
1413 int *enPrv,
1414 int *enAct,
1415 int sfbCnt,
1416 const SHORT *pSfbOffset )
1417 {
1418 int sfb, line = 0;
1419 int fac_shift;
1420 int fac_mod;
1421 FIXP_DBL accu;
1422
1423 for (sfb = 0; sfb < sfbCnt; sfb++) {
1424
1425 fac_shift = enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1);
1426 fac_mod = fac_shift & 3;
1427 fac_shift = (fac_shift >> 2) + 1;
1428 fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct);
1429
1430 for (; line < pSfbOffset[sfb+1]; line++) {
1431 accu = fMult(*(spectrum+line), facMod4Table[fac_mod]);
1432 if (fac_shift < 0) {
1433 accu >>= -fac_shift;
1434 } else {
1435 accu <<= fac_shift;
1436 }
1437 *(spectrum+line) = accu;
1438 }
1439 }
1440 *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct);
1441 }
1442
1443
1444
1445
1446 static INT findEquiFadeFrame (
1447 CConcealParams *pConcealCommonData,
1448 INT actFadeIndex,
1449 int direction )
1450 {
1451 FIXP_SGL *pFactor;
1452 FIXP_SGL referenceVal;
1453 FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL;
1454
1455 INT numFrames = 0;
1456 INT nextFadeIndex = 0;
1457
1458 int i;
1459
1460 /* init depending on direction */
1461 if (direction == 0) { /* FADE-OUT => FADE-IN */
1462 numFrames = pConcealCommonData->numFadeInFrames;
1463 referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1;
1464 pFactor = pConcealCommonData->fadeInFactor;
1465 }
1466 else { /* FADE-IN => FADE-OUT */
1467 numFrames = pConcealCommonData->numFadeOutFrames;
1468 referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1;
1469 pFactor = pConcealCommonData->fadeOutFactor;
1470 }
1471
1472 /* search for minimum difference */
1473 for (i = 0; i < numFrames; i++) {
1474 FIXP_SGL diff = fixp_abs((pFactor[i]>>1) - referenceVal);
1475 if (diff < minDiff) {
1476 minDiff = diff;
1477 nextFadeIndex = i;
1478 }
1479 }
1480
1481 /* check and adjust depending on direction */
1482 if (direction == 0) { /* FADE-OUT => FADE-IN */
1483 if (((pFactor[nextFadeIndex]>>1) <= referenceVal) && (nextFadeIndex > 0)) {
1484 nextFadeIndex -= 1;
1485 }
1486 }
1487 else { /* FADE-IN => FADE-OUT */
1488 if (((pFactor[nextFadeIndex]>>1) >= referenceVal) && (nextFadeIndex < numFrames-1)) {
1489 nextFadeIndex += 1;
1490 }
1491 }
1492
1493 return (nextFadeIndex);
1494 }
1495
1496
1497 /*!
1498 \brief Update the concealment state
1499
1500 The function updates the state of the concealment state-machine. The
1501 states are: mute, fade-in, fade-out, interpolate and frame-ok.
1502
1503 \return none
1504 */
1505 static void
1506 CConcealment_UpdateState (
1507 CConcealmentInfo *pConcealmentInfo,
1508 int frameOk )
1509 {
1510 CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams;
1511
1512 switch (pConcealCommonData->method)
1513 {
1514 case ConcealMethodNoise:
1515 {
1516 if (pConcealmentInfo->concealState != ConcealState_Ok) {
1517 /* count the valid frames during concealment process */
1518 if (frameOk) {
1519 pConcealmentInfo->cntValidFrames += 1;
1520 } else {
1521 pConcealmentInfo->cntValidFrames = 0;
1522 }
1523 }
1524
1525 /* -- STATE MACHINE for Noise Substitution -- */
1526 switch (pConcealmentInfo->concealState)
1527 {
1528 case ConcealState_Ok:
1529 if (!frameOk) {
1530 if (pConcealCommonData->numFadeOutFrames > 0) {
1531 /* change to state SINGLE-FRAME-LOSS */
1532 pConcealmentInfo->concealState = ConcealState_Single;
1533 } else {
1534 /* change to state MUTE */
1535 pConcealmentInfo->concealState = ConcealState_Mute;
1536 }
1537 pConcealmentInfo->cntFadeFrames = 0;
1538 pConcealmentInfo->cntValidFrames = 0;
1539 }
1540 break;
1541
1542 case ConcealState_Single: /* Just a pre-stage before fade-out begins. Stay here only one frame! */
1543 pConcealmentInfo->cntFadeFrames += 1;
1544 if (frameOk) {
1545 if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
1546 /* change to state FADE-IN */
1547 pConcealmentInfo->concealState = ConcealState_FadeIn;
1548 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
1549 pConcealmentInfo->cntFadeFrames-1,
1550 0 /* FadeOut -> FadeIn */);
1551 } else {
1552 /* change to state OK */
1553 pConcealmentInfo->concealState = ConcealState_Ok;
1554 }
1555 } else {
1556 if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
1557 /* change to state MUTE */
1558 pConcealmentInfo->concealState = ConcealState_Mute;
1559 } else {
1560 /* change to state FADE-OUT */
1561 pConcealmentInfo->concealState = ConcealState_FadeOut;
1562 }
1563 }
1564 break;
1565
1566 case ConcealState_FadeOut:
1567 pConcealmentInfo->cntFadeFrames += 1; /* used to address the fade-out factors */
1568 if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
1569 if (pConcealCommonData->numFadeInFrames > 0) {
1570 /* change to state FADE-IN */
1571 pConcealmentInfo->concealState = ConcealState_FadeIn;
1572 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
1573 pConcealmentInfo->cntFadeFrames-1,
1574 0 /* FadeOut -> FadeIn */);
1575 } else {
1576 /* change to state OK */
1577 pConcealmentInfo->concealState = ConcealState_Ok;
1578 }
1579 } else {
1580 if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
1581 /* change to state MUTE */
1582 pConcealmentInfo->concealState = ConcealState_Mute;
1583 }
1584 }
1585 break;
1586
1587 case ConcealState_Mute:
1588 if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
1589 if (pConcealCommonData->numFadeInFrames > 0) {
1590 /* change to state FADE-IN */
1591 pConcealmentInfo->concealState = ConcealState_FadeIn;
1592 pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
1593 } else {
1594 /* change to state OK */
1595 pConcealmentInfo->concealState = ConcealState_Ok;
1596 }
1597 }
1598 break;
1599
1600 case ConcealState_FadeIn:
1601 pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */
1602 if (frameOk) {
1603 if (pConcealmentInfo->cntFadeFrames < 0) {
1604 /* change to state OK */
1605 pConcealmentInfo->concealState = ConcealState_Ok;
1606 }
1607 } else {
1608 if (pConcealCommonData->numFadeOutFrames > 0) {
1609 /* change to state FADE-OUT */
1610 pConcealmentInfo->concealState = ConcealState_FadeOut;
1611 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
1612 pConcealmentInfo->cntFadeFrames+1,
1613 1 /* FadeIn -> FadeOut */);
1614 } else {
1615 /* change to state MUTE */
1616 pConcealmentInfo->concealState = ConcealState_Mute;
1617 }
1618 }
1619 break;
1620
1621 default:
1622 FDK_ASSERT(0);
1623 break;
1624 }
1625 }
1626 break;
1627
1628 case ConcealMethodInter:
1629 case ConcealMethodTonal:
1630 {
1631 if (pConcealmentInfo->concealState != ConcealState_Ok) {
1632 /* count the valid frames during concealment process */
1633 if ( pConcealmentInfo->prevFrameOk[1] ||
1634 (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk) ) {
1635 /* The frame is OK even if it can be estimated by the energy interpolation algorithm */
1636 pConcealmentInfo->cntValidFrames += 1;
1637 } else {
1638 pConcealmentInfo->cntValidFrames = 0;
1639 }
1640 }
1641
1642 /* -- STATE MACHINE for energy interpolation -- */
1643 switch (pConcealmentInfo->concealState)
1644 {
1645 case ConcealState_Ok:
1646 if (!(pConcealmentInfo->prevFrameOk[1] ||
1647 (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk))) {
1648 if (pConcealCommonData->numFadeOutFrames > 0) {
1649 /* Fade out only if the energy interpolation algorithm can not be applied! */
1650 pConcealmentInfo->concealState = ConcealState_FadeOut;
1651 } else {
1652 /* change to state MUTE */
1653 pConcealmentInfo->concealState = ConcealState_Mute;
1654 }
1655 pConcealmentInfo->cntFadeFrames = 0;
1656 pConcealmentInfo->cntValidFrames = 0;
1657 }
1658 break;
1659
1660 case ConcealState_Single:
1661 pConcealmentInfo->concealState = ConcealState_Ok;
1662 break;
1663
1664 case ConcealState_FadeOut:
1665 pConcealmentInfo->cntFadeFrames += 1;
1666
1667 if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
1668 if (pConcealCommonData->numFadeInFrames > 0) {
1669 /* change to state FADE-IN */
1670 pConcealmentInfo->concealState = ConcealState_FadeIn;
1671 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
1672 pConcealmentInfo->cntFadeFrames-1,
1673 0 /* FadeOut -> FadeIn */);
1674 } else {
1675 /* change to state OK */
1676 pConcealmentInfo->concealState = ConcealState_Ok;
1677 }
1678 } else {
1679 if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) {
1680 /* change to state MUTE */
1681 pConcealmentInfo->concealState = ConcealState_Mute;
1682 }
1683 }
1684 break;
1685
1686 case ConcealState_Mute:
1687 if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) {
1688 if (pConcealCommonData->numFadeInFrames > 0) {
1689 /* change to state FADE-IN */
1690 pConcealmentInfo->concealState = ConcealState_FadeIn;
1691 pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1;
1692 } else {
1693 /* change to state OK */
1694 pConcealmentInfo->concealState = ConcealState_Ok;
1695 }
1696 }
1697 break;
1698
1699 case ConcealState_FadeIn:
1700 pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */
1701
1702 if (frameOk || pConcealmentInfo->prevFrameOk[1]) {
1703 if (pConcealmentInfo->cntFadeFrames < 0) {
1704 /* change to state OK */
1705 pConcealmentInfo->concealState = ConcealState_Ok;
1706 }
1707 } else {
1708 if (pConcealCommonData->numFadeOutFrames > 0) {
1709 /* change to state FADE-OUT */
1710 pConcealmentInfo->concealState = ConcealState_FadeOut;
1711 pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData,
1712 pConcealmentInfo->cntFadeFrames+1,
1713 1 /* FadeIn -> FadeOut */);
1714 } else {
1715 /* change to state MUTE */
1716 pConcealmentInfo->concealState = ConcealState_Mute;
1717 }
1718 }
1719 break;
1720 } /* End switch(pConcealmentInfo->concealState) */
1721 }
1722 break;
1723
1724 default:
1725 /* Don't need a state machine for other concealment methods. */
1726 break;
1727 }
1728
1729 }
1730
1731
1732 /*!
1733 \brief Randomizes the sign of the spectral data
1734
1735 The function toggles the sign of the spectral data randomly. This is
1736 useful to ensure the quality of the concealed frames.
1737
1738 \return none
1739 */
1740 static
1741 void CConcealment_ApplyRandomSign (int randomPhase,
1742 FIXP_DBL *spec,
1743 int samplesPerFrame
1744 )
1745 {
1746 int i;
1747 USHORT packedSign=0;
1748
1749 /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit */
1750
1751 /* read current packed sign word */
1752 packedSign = randomSign[randomPhase>>4];
1753 packedSign >>= (randomPhase&0xf);
1754
1755 for (i = 0; i < samplesPerFrame ; i++) {
1756 if ((randomPhase & 0xf) == 0) {
1757 packedSign = randomSign[randomPhase>>4];
1758 }
1759
1760 if (packedSign & 0x1) {
1761 spec[i] = -spec[i];
1762 }
1763 packedSign >>= 1;
1764
1765 randomPhase = (randomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1);
1766 }
1767 }
1768
1769
1770 /*!
1771 \brief Get fadeing factor for current concealment state.
1772
1773 The function returns the factor used for fading that belongs to the current internal state.
1774
1775 \return Fade factor
1776 */
1777 FIXP_DBL
1778 CConcealment_GetFadeFactor (
1779 CConcealmentInfo *hConcealmentInfo,
1780 const int fPreviousFactor
1781 )
1782 {
1783 FIXP_DBL fac = (FIXP_DBL)0;
1784
1785 CConcealParams *pConcealCommonData = hConcealmentInfo->pConcealParams;
1786
1787 if (hConcealmentInfo->pConcealParams->method > ConcealMethodMute) {
1788 switch (hConcealmentInfo->concealState) {
1789 default:
1790 case ConcealState_Mute:
1791 /* Nothing to do here */
1792 break;
1793 case ConcealState_Ok:
1794 fac = (FIXP_DBL)MAXVAL_DBL;
1795 break;
1796 case ConcealState_Single:
1797 case ConcealState_FadeOut:
1798 {
1799 int idx = hConcealmentInfo->cntFadeFrames - ((fPreviousFactor != 0) ? 1 : 0);
1800 fac = (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(pConcealCommonData->fadeOutFactor[idx]);
1801 }
1802 break;
1803 case ConcealState_FadeIn:
1804 {
1805 int idx = hConcealmentInfo->cntFadeFrames + ((fPreviousFactor != 0) ? 1 : 0);
1806 fac = (idx >= hConcealmentInfo->pConcealParams->numFadeInFrames) ? (FIXP_DBL)0 : FX_SGL2FX_DBL(pConcealCommonData->fadeInFactor[idx]);
1807 }
1808 break;
1809 }
1810 }
1811
1812 return (fac);
1813 }
1814
1815
1816 /*!
1817 \brief Get fadeing factor for current concealment state.
1818
1819 The function returns the state (ok or not) of the previous frame.
1820 If called before the function CConcealment_Apply() set the fBeforeApply
1821 flag to get the correct value.
1822
1823 \return Frame OK flag of previous frame.
1824 */
1825 int
1826 CConcealment_GetLastFrameOk (
1827 CConcealmentInfo *hConcealmentInfo,
1828 const int fBeforeApply
1829 )
1830 {
1831 int prevFrameOk = 1;
1832
1833 if (hConcealmentInfo != NULL) {
1834 prevFrameOk = hConcealmentInfo->prevFrameOk[fBeforeApply & 0x1];
1835 }
1836
1837 return prevFrameOk;
1838 }
1839
1840 /*!
1841 \brief Get the number of delay frames introduced by concealment technique.
1842
1843 \return Number of delay frames.
1844 */
1845 UINT
1846 CConcealment_GetDelay (
1847 CConcealParams *pConcealCommonData
1848 )
1849 {
1850 UINT frameDelay = 0;
1851
1852 if (pConcealCommonData != NULL) {
1853 switch (pConcealCommonData->method) {
1854 case ConcealMethodTonal:
1855 case ConcealMethodInter:
1856 frameDelay = 1;
1857 break;
1858 default:
1859 break;
1860 }
1861 }
1862
1863 return frameDelay;
1864 }
1865