LCOV - code coverage report
Current view: top level - lib_dec - tonalMDCTconcealment.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 435 447 97.3 %
Date: 2025-05-23 08:37:30 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #define _USE_MATH_DEFINES
      38             : 
      39             : #include <assert.h>
      40             : #include <stdint.h>
      41             : #include "options.h"
      42             : #ifdef DEBUGGING
      43             : #include "debug.h"
      44             : #endif
      45             : #include <math.h>
      46             : #include "prot.h"
      47             : #include "ivas_prot.h"
      48             : #include "wmc_auto.h"
      49             : 
      50             : 
      51             : /*******************************************************/
      52             : /*-------------- public functions -------------------- */
      53             : /*******************************************************/
      54             : 
      55       47526 : ivas_error TonalMDCTConceal_Init(
      56             :     TonalMDCTConcealPtr hTonalMDCTConc,
      57             :     const uint16_t nSamples,
      58             :     const uint16_t nSamplesCore,
      59             :     const uint16_t nScaleFactors,
      60             :     TCX_CONFIG_HANDLE hTcxCfg )
      61             : {
      62       47526 :     if ( nSamples > L_FRAME_MAX || nScaleFactors > FDNS_NPTS )
      63             :     {
      64           0 :         assert( nSamples <= L_FRAME_MAX );
      65           0 :         assert( nScaleFactors <= FDNS_NPTS );
      66           0 :         return ( IVAS_ERROR( IVAS_ERR_INTERNAL, "TonalMDCT FEC: Number of samples larger than max. block size\n" ) );
      67             :     }
      68       47526 :     assert( ( hTonalMDCTConc->nScaleFactors == nScaleFactors ) || ( hTonalMDCTConc->nSamples != nSamples ) ); /* If nSamples doesn't change then also nScaleFactors must stay the same */
      69             : 
      70       47526 :     hTonalMDCTConc->tcx_cfg = hTcxCfg;
      71       47526 :     hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
      72       47526 :     hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
      73       47526 :     hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
      74       47526 :     hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
      75       47526 :     hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
      76       47526 :     hTonalMDCTConc->lastBlockData.blockIsValid = 0;
      77       47526 :     hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
      78       47526 :     hTonalMDCTConc->nSamples = 0;
      79       47526 :     hTonalMDCTConc->nScaleFactors = 0;
      80             : 
      81       47526 :     hTonalMDCTConc->lastBlockData.blockIsConcealed = 0;
      82       47526 :     hTonalMDCTConc->secondLastBlockData.blockIsConcealed = 0;
      83       47526 :     hTonalMDCTConc->pTCI = (TonalComponentsInfo *) hTonalMDCTConc->timeDataBuffer;
      84             : 
      85       47526 :     hTonalMDCTConc->lastPitchLag = 0;
      86             : 
      87       47526 :     if ( hTonalMDCTConc->nSamples != nSamples )
      88             :     {
      89       47526 :         hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
      90       47526 :         hTonalMDCTConc->lastBlockData.blockIsValid = 0;
      91             :     }
      92       47526 :     hTonalMDCTConc->nSamples = nSamples;
      93       47526 :     hTonalMDCTConc->nSamplesCore = nSamplesCore;
      94       47526 :     hTonalMDCTConc->nScaleFactors = nScaleFactors;
      95             : 
      96       47526 :     set_zero( hTonalMDCTConc->scaleFactorsBackground, FDNS_NPTS );
      97       47526 :     hTonalMDCTConc->scf_fadeout = 1.0f;
      98       47526 :     PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k, 64, 1, 1, &hTonalMDCTConc->psychParamsTCX20 );
      99       47526 :     PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k / 2, 64, 0, 1, &hTonalMDCTConc->psychParamsTCX10 );
     100       47526 :     hTonalMDCTConc->psychParams = NULL;
     101             : 
     102       47526 :     hTonalMDCTConc->last_block_nrg = 0.0f;
     103       47526 :     hTonalMDCTConc->curr_noise_nrg = 0.0f;
     104       47526 :     hTonalMDCTConc->faded_signal_nrg = 0.0f;
     105             : 
     106             :     /* Offset the pointer to the end of buffer, so that pTCI is not destroyed when
     107             :        new time samples are stored in lastPcmOut */
     108             :     /* just the second half of the second last pcm output is needed */
     109       47526 :     hTonalMDCTConc->secondLastPcmOut = &hTonalMDCTConc->timeDataBuffer[( 3 * L_FRAME_MAX ) / 2 - ( 3 * min( L_FRAME_MAX, nSamples ) ) / 2];
     110       47526 :     hTonalMDCTConc->lastPcmOut = &hTonalMDCTConc->timeDataBuffer[( 3 * L_FRAME_MAX ) / 2 - min( L_FRAME_MAX, nSamples )];
     111             : 
     112             :     /* If the second last frame was lost and concealed with tonal PLC, we
     113             :        reuse saved TonalComponentsInfo and don't update pcm buffers */
     114       47526 :     assert( sizeof( *hTonalMDCTConc->pTCI ) <= ( hTonalMDCTConc->lastPcmOut - hTonalMDCTConc->timeDataBuffer ) * sizeof( hTonalMDCTConc->timeDataBuffer[0] ) );
     115             : 
     116       47526 :     return IVAS_ERR_OK;
     117             : }
     118             : 
     119             : 
     120     2564757 : void TonalMDCTConceal_SaveFreqSignal(
     121             :     TonalMDCTConcealPtr hTonalMDCTConc,
     122             :     const float *mdctSpectrum,
     123             :     const uint16_t nNewSamples,
     124             :     const uint16_t nNewSamplesCore,
     125             :     const float *scaleFactors,
     126             :     const int16_t infoIGFStartLine )
     127             : {
     128             :     float *temp;
     129             :     uint16_t nOldSamples;
     130             : 
     131     2564757 :     assert( nNewSamples > 0 && nNewSamples <= 2 * L_FRAME_MAX );
     132             : 
     133             :     /* Avoid overwriting hTonalMDCTConc->secondLastPowerSpectrum stored in spectralData,
     134             :        because it is needed if the second last and the current frame are lost
     135             :        and concealed using the Tonal MDCT PLC */
     136     2564757 :     if ( !hTonalMDCTConc->lastBlockData.tonalConcealmentActive || ( hTonalMDCTConc->lastBlockData.nSamples != nNewSamples ) )
     137             :     {
     138     2563455 :         if ( nNewSamples <= L_FRAME_MAX )
     139             :         {
     140             :             /* Shift the buffers */
     141     2542968 :             temp = hTonalMDCTConc->secondLastBlockData.spectralData; /* Save the pointer */
     142     2542968 :             hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->lastBlockData.spectralData;
     143     2542968 :             hTonalMDCTConc->lastBlockData.spectralData = temp;
     144     2542968 :             temp = hTonalMDCTConc->secondLastBlockData.scaleFactors;
     145     2542968 :             hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->lastBlockData.scaleFactors;
     146     2542968 :             hTonalMDCTConc->lastBlockData.scaleFactors = temp;
     147             :         }
     148             :         else
     149             :         {
     150             :             /* Order the buffers so that even transition frame can fit in if written into the first buffer */
     151       20487 :             hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
     152       20487 :             hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
     153       20487 :             hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
     154       20487 :             hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
     155             :         }
     156     2563455 :         nOldSamples = hTonalMDCTConc->lastBlockData.nSamples;
     157     2563455 :         hTonalMDCTConc->lastBlockData.nSamples = nNewSamples;
     158     2563455 :         hTonalMDCTConc->secondLastBlockData.nSamples = nOldSamples;
     159     2563455 :         nOldSamples = hTonalMDCTConc->lastBlockData.nSamplesCore;
     160     2563455 :         hTonalMDCTConc->lastBlockData.nSamplesCore = nNewSamplesCore;
     161     2563455 :         hTonalMDCTConc->secondLastBlockData.nSamplesCore = nOldSamples;
     162             :     }
     163             : 
     164     2564757 :     if ( ( nNewSamples > 0 ) && ( nNewSamples <= 2 * L_FRAME_MAX ) )
     165             :     {
     166             :         /* Store new data */
     167             :         int16_t i;
     168             : 
     169     2564757 :         hTonalMDCTConc->last_block_nrg = 0.0f;
     170  1227338133 :         for ( i = 0; i < infoIGFStartLine; i++ )
     171             :         {
     172  1224773376 :             hTonalMDCTConc->lastBlockData.spectralData[i] = mdctSpectrum[i];
     173  1224773376 :             hTonalMDCTConc->last_block_nrg += mdctSpectrum[i] * mdctSpectrum[i];
     174             :         }
     175   923810901 :         for ( ; i < nNewSamples; i++ )
     176             :         {
     177   921246144 :             hTonalMDCTConc->lastBlockData.spectralData[i] = mdctSpectrum[i];
     178             :         }
     179             : 
     180     2564757 :         mvr2r( scaleFactors, hTonalMDCTConc->lastBlockData.scaleFactors, hTonalMDCTConc->nScaleFactors );
     181             :     }
     182             : 
     183     2564757 :     return;
     184             : }
     185             : 
     186             : 
     187     2842746 : void TonalMDCTConceal_UpdateState(
     188             :     TonalMDCTConcealPtr hTonalMDCTConc,
     189             :     const int16_t nNewSamples,
     190             :     const float pitchLag,
     191             :     const int16_t badBlock,
     192             :     const int16_t tonalConcealmentActive )
     193             : {
     194             :     int16_t newBlockIsValid;
     195             : 
     196     2842746 :     assert( !( !badBlock && tonalConcealmentActive ) );
     197             : 
     198     2842746 :     if ( badBlock )
     199             :     {
     200       49758 :         newBlockIsValid = hTonalMDCTConc->lastBlockData.blockIsValid;
     201             :     }
     202             :     else
     203             :     {
     204     2792988 :         newBlockIsValid = ( nNewSamples <= 2 * L_FRAME_MAX ) && ( nNewSamples > 0 );
     205             :     }
     206             : 
     207             :     /* Shift old state */
     208     2842746 :     hTonalMDCTConc->secondLastBlockData.blockIsConcealed = hTonalMDCTConc->lastBlockData.blockIsConcealed;
     209     2842746 :     hTonalMDCTConc->secondLastBlockData.blockIsValid = hTonalMDCTConc->lastBlockData.blockIsValid;
     210     2842746 :     hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive = hTonalMDCTConc->lastBlockData.tonalConcealmentActive;
     211             : 
     212             :     /* Store new state */
     213     2842746 :     hTonalMDCTConc->lastBlockData.blockIsConcealed = badBlock;
     214     2842746 :     hTonalMDCTConc->lastBlockData.blockIsValid = newBlockIsValid;
     215     2842746 :     hTonalMDCTConc->lastBlockData.tonalConcealmentActive = tonalConcealmentActive;
     216     2842746 :     hTonalMDCTConc->lastPitchLag = pitchLag;
     217             : 
     218     2842746 :     return;
     219             : }
     220             : 
     221             : 
     222        5931 : static void FindPhases(
     223             :     const TonalMDCTConcealPtr hTonalMDCTConc,
     224             :     const float secondLastMDCT[],
     225             :     const float secondLastMDST[] )
     226             : {
     227             :     int16_t i;
     228             :     int16_t l;
     229             :     float *pCurrentPhase;
     230             : 
     231        5931 :     pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
     232             :     /* for each index/index group */
     233       17874 :     for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     234             :     {
     235       95430 :         for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     236             :         {
     237       83487 :             *pCurrentPhase++ = (float) atan2( secondLastMDST[l], secondLastMDCT[l] );
     238             :         }
     239             :     }
     240             : 
     241        5931 :     return;
     242             : }
     243             : 
     244             : #define CNST_bandwidth 7.0f
     245             : #define CNST_m         (float) cos( EVS_PI / CNST_bandwidth )
     246             : #define CNST_s         (float) cos( ( 3 * EVS_PI ) / CNST_bandwidth )
     247             : #define CNST_n         (float) sin( EVS_PI / CNST_bandwidth )
     248             : #define CNST_j         (float) sin( ( 3 * EVS_PI ) / CNST_bandwidth )
     249             : #define CNST_G         (float) ( 1.0 / ( 2 * 1.36 ) )
     250             : #define CNST_maxRatio  44.8f /* Maximum ratio |ODFT[k-1]|/|ODFT[k+1]| is 16.5 dB, that is maximum ratio (for fractional = 0) is (cos(EVS_PI/bandwidth)/cos(3PI/bandwidth))^1.36 */
     251             : 
     252             : 
     253        5931 : static void FindPhaseDifferences(
     254             :     TonalMDCTConcealPtr const hTonalMDCTConc,
     255             :     float powerSpectrum[] )
     256             : {
     257             :     int16_t i, k;
     258             :     float odft_left, odft_right;
     259             :     float *phaseDiff;
     260             :     float fractional;
     261             :     float Q, a;
     262             : 
     263        5931 :     phaseDiff = hTonalMDCTConc->pTCI->phaseDiff;
     264       17874 :     for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     265             :     {
     266       11943 :         k = hTonalMDCTConc->pTCI->indexOfTonalPeak[i];
     267       11943 :         odft_left = powerSpectrum[k - 1];
     268       11943 :         odft_right = powerSpectrum[k + 1];
     269       11943 :         if ( odft_left >= CNST_maxRatio * odft_right )
     270             :         {
     271          72 :             a = (float) tan( 0.0f * EVS_PI / CNST_bandwidth );
     272             :         }
     273             :         else
     274             :         {
     275       11871 :             if ( odft_right >= CNST_maxRatio * odft_left )
     276             :             {
     277         123 :                 a = (float) tan( 2.0f * EVS_PI / CNST_bandwidth );
     278             :             }
     279             :             else
     280             :             {
     281       11748 :                 Q = (float) pow( odft_left / odft_right, CNST_G );
     282       11748 :                 a = ( CNST_m - Q * CNST_s ) / ( CNST_n + Q * CNST_j );
     283             :             }
     284             :         }
     285       11943 :         fractional = (float) atan( a ) * ( CNST_bandwidth / 2.0f );
     286       11943 :         assert( ( fractional >= 0 ) && ( fractional <= EVS_PI + 1.192092896e-07F ) );
     287       11943 :         phaseDiff[i] = fractional + EVS_PI * ( k % 4 );
     288             :     }
     289             : 
     290        5931 :     return;
     291             : }
     292             : 
     293        5931 : static void CalcPowerSpec(
     294             :     const float *mdctSpec,
     295             :     const float *mdstSpec,
     296             :     const int16_t nSamples,
     297             :     float floorPowerSpectrum,
     298             :     float *powerSpec )
     299             : {
     300             :     int16_t k;
     301             :     float x;
     302             : 
     303     2944770 :     for ( k = 1; k <= nSamples - 2; k++ )
     304             :     {
     305     2938839 :         x = mdctSpec[k] * mdctSpec[k] + mdstSpec[k] * mdstSpec[k];
     306     2938839 :         powerSpec[k] = max( floorPowerSpectrum, x );
     307             :     }
     308        5931 :     powerSpec[0] = 0.5f * powerSpec[1];
     309        5931 :     powerSpec[nSamples - 1] = 0.5f * powerSpec[nSamples - 2];
     310             : 
     311        5931 :     return;
     312             : }
     313             : 
     314        5931 : static void CalcPowerSpecAndDetectTonalComponents(
     315             :     const TonalMDCTConcealPtr hTonalMDCTConc,
     316             :     float secondLastMDST[],
     317             :     float secondLastMDCT[],
     318             :     const float pitchLag,
     319             :     const PsychoacousticParameters *psychParamsCurrent )
     320             : {
     321             :     int16_t i, nSamples;
     322             :     float floorPowerSpectrum;         /* Minimum significant value of a spectral line in the power spectrum */
     323             :     float powerSpectrum[L_FRAME_MAX]; /* 32 bits are required */
     324             :     float invScaleFactors[FDNS_NPTS];
     325             :     int16_t nBands;
     326             : 
     327        5931 :     nSamples = hTonalMDCTConc->nNonZeroSamples;
     328             : 
     329             :     /* It is taken into account that the MDCT is not normalized. */
     330        5931 :     floorPowerSpectrum = hTonalMDCTConc->nSamples * hTonalMDCTConc->nSamples / 400.0f;
     331        5931 :     CalcPowerSpec( secondLastMDCT, secondLastMDST, nSamples, floorPowerSpectrum, powerSpectrum );
     332             : 
     333             :     /* This setting to minimal level is required because the power spectrum is used in the threshold adaptation using the pitch up to hTonalMDCTConc->nSamples. */
     334        5931 :     set_f( powerSpectrum + nSamples, floorPowerSpectrum, hTonalMDCTConc->nSamples - nSamples );
     335             :     /* this setting to zero is needed since the FDNS needs to be called
     336             :        with hTonalMDCTConc->nSamplesCore; it relevant only for nb; it has no effect
     337             :        to the output, but memory checker may complain otherwise due to the
     338             :        usage of uninitialized values */
     339             : 
     340        5931 :     if ( hTonalMDCTConc->nSamplesCore > hTonalMDCTConc->nSamples )
     341             :     {
     342         174 :         set_zero( powerSpectrum + hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamplesCore - hTonalMDCTConc->nSamples );
     343             :     }
     344             : 
     345        5931 :     DetectTonalComponents( hTonalMDCTConc->pTCI->indexOfTonalPeak, hTonalMDCTConc->pTCI->lowerIndex, hTonalMDCTConc->pTCI->upperIndex, &hTonalMDCTConc->pTCI->numIndexes, hTonalMDCTConc->lastPitchLag, pitchLag,
     346        5931 :                            hTonalMDCTConc->lastBlockData.spectralData, hTonalMDCTConc->lastBlockData.scaleFactors, powerSpectrum, nSamples, hTonalMDCTConc->nSamplesCore, floorPowerSpectrum, psychParamsCurrent );
     347             : 
     348        5931 :     FindPhases( hTonalMDCTConc, secondLastMDCT, secondLastMDST );
     349             : 
     350        5931 :     FindPhaseDifferences( hTonalMDCTConc, powerSpectrum );
     351             : 
     352        5931 :     if ( hTonalMDCTConc->pTCI->numIndexes > 0 )
     353             :     {
     354        2166 :         hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
     355             : 
     356     1143459 :         for ( i = 0; i < nSamples; i++ )
     357             :         {
     358     1141293 :             powerSpectrum[i] = (float) sqrt( powerSpectrum[i] );
     359             :         }
     360             : 
     361      140790 :         for ( i = 0; i < hTonalMDCTConc->nScaleFactors; i++ )
     362             :         {
     363      138624 :             invScaleFactors[i] = 1.0f / hTonalMDCTConc->secondLastBlockData.scaleFactors[i];
     364             :         }
     365             : 
     366        2166 :         if ( psychParamsCurrent == NULL )
     367             :         {
     368         906 :             nBands = FDNS_NPTS;
     369         906 :             mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, invScaleFactors, nBands );
     370             :         }
     371             :         else
     372             :         {
     373        1260 :             sns_shape_spectrum( powerSpectrum, psychParamsCurrent, invScaleFactors, hTonalMDCTConc->nSamplesCore );
     374        1260 :             nBands = psychParamsCurrent->nBands;
     375             :         }
     376             : 
     377        2166 :         v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, invScaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples - hTonalMDCTConc->nSamplesCore );
     378        2166 :         mvr2r( powerSpectrum, hTonalMDCTConc->secondLastPowerSpectrum, hTonalMDCTConc->nSamples ); /* 16 bits are now enough for storing the power spectrum */
     379             :     }
     380             : 
     381        5931 :     return;
     382             : }
     383             : 
     384             : 
     385       11862 : static void CalcMDXT(
     386             :     const TonalMDCTConcealPtr hTonalMDCTConc,
     387             :     const char type,
     388             :     const float *timeSignal,
     389             :     float *mdxtOutput )
     390             : {
     391             :     float windowedTimeSignal[L_FRAME_PLUS + 2 * L_MDCT_OVLP_MAX];
     392             :     int16_t left_overlap, right_overlap;
     393             :     int16_t L_frame;
     394             : 
     395       11862 :     L_frame = hTonalMDCTConc->nSamples;
     396       11862 :     WindowSignal( hTonalMDCTConc->tcx_cfg, hTonalMDCTConc->tcx_cfg->tcx_offsetFB, FULL_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, timeSignal, &L_frame, windowedTimeSignal, 1, 1 );
     397             : 
     398       11862 :     if ( type == 'S' )
     399             :     {
     400        5931 :         TCX_MDST( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - ( left_overlap + right_overlap ) / 2, right_overlap, EVS_MONO );
     401             :     }
     402             :     else
     403             :     {
     404        5931 :         TCX_MDCT( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - ( left_overlap + right_overlap ) / 2, right_overlap, EVS_MONO );
     405             :     }
     406             : 
     407       11862 :     return;
     408             : }
     409             : 
     410             : 
     411        7215 : void TonalMDCTConceal_Detect(
     412             :     const TonalMDCTConcealPtr hTonalMDCTConc,
     413             :     const float pitchLag,
     414             :     int16_t *numIndices,
     415             :     const PsychoacousticParameters *psychParamsCurrent )
     416             : {
     417             :     float secondLastMDST[L_FRAME_MAX]; /* 32 bits are required */
     418             :     float secondLastMDCT[L_FRAME_MAX]; /* 32 bits are required */
     419        7215 :     float *powerSpectrum = secondLastMDST;
     420             :     int16_t i, nSamples;
     421             :     int16_t nBands;
     422             : 
     423        7215 :     nSamples = hTonalMDCTConc->nSamples;
     424        7215 :     if ( hTonalMDCTConc->lastBlockData.blockIsValid && hTonalMDCTConc->secondLastBlockData.blockIsValid && ( hTonalMDCTConc->lastBlockData.nSamples == nSamples ) && ( hTonalMDCTConc->secondLastBlockData.nSamples == nSamples ) && ( !hTonalMDCTConc->secondLastBlockData.blockIsConcealed || hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive || ( pitchLag != 0 ) ) )
     425             :     {
     426             :         /* Safety if the second last frame was concealed and tonal concealment was inactive */
     427             : 
     428        6066 :         if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
     429             :         {
     430        6066 :             if ( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
     431             :             {
     432        5931 :                 CalcMDXT( hTonalMDCTConc, 'S', hTonalMDCTConc->secondLastPcmOut, secondLastMDST );
     433        5931 :                 CalcMDXT( hTonalMDCTConc, 'C', hTonalMDCTConc->secondLastPcmOut, secondLastMDCT );
     434        5931 :                 hTonalMDCTConc->nNonZeroSamples = 0;
     435     4600491 :                 for ( i = 0; i < hTonalMDCTConc->nSamples; i++ )
     436             :                 {
     437     4594560 :                     if ( hTonalMDCTConc->secondLastBlockData.spectralData[i] != 0 )
     438             :                     {
     439     2656377 :                         hTonalMDCTConc->nNonZeroSamples = i;
     440             :                     }
     441             :                 }
     442             :                 /* 23 is the maximum length of the MA filter in getEnvelope */
     443        5931 :                 hTonalMDCTConc->nNonZeroSamples = min( hTonalMDCTConc->nSamples, hTonalMDCTConc->nNonZeroSamples + 23 );
     444        5931 :                 CalcPowerSpecAndDetectTonalComponents( hTonalMDCTConc, secondLastMDST, secondLastMDCT, pitchLag, psychParamsCurrent );
     445             :             }
     446             :             else
     447             :             {
     448             :                 /* If the second last frame was also lost, it is expected that pastTimeSignal could hold a bit different signal (e.g. including fade-out) from the one stored in TonalMDCTConceal_SaveTimeSignal. */
     449             :                 /* That is why we reuse the already stored information about the concealed spectrum in the second last frame */
     450         135 :                 nSamples = hTonalMDCTConc->nNonZeroSamples;
     451         135 :                 mvr2r( hTonalMDCTConc->secondLastPowerSpectrum, powerSpectrum, nSamples ); /* Convert from 16 bits to 32 bits */
     452         135 :                 if ( psychParamsCurrent == NULL )
     453             :                 {
     454          48 :                     nBands = FDNS_NPTS;
     455          48 :                     mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors, nBands );
     456             :                 }
     457             :                 else
     458             :                 {
     459          87 :                     sns_shape_spectrum( powerSpectrum, psychParamsCurrent, hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->nSamplesCore );
     460          87 :                     nBands = psychParamsCurrent->nBands;
     461             :                 }
     462             : 
     463         135 :                 v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, nSamples - hTonalMDCTConc->nSamplesCore );
     464         135 :                 v_mult( powerSpectrum, powerSpectrum, powerSpectrum, nSamples );
     465             : 
     466         135 :                 RefineTonalComponents( hTonalMDCTConc->pTCI->indexOfTonalPeak, hTonalMDCTConc->pTCI->lowerIndex, hTonalMDCTConc->pTCI->upperIndex, hTonalMDCTConc->pTCI->phaseDiff,
     467         135 :                                        hTonalMDCTConc->pTCI->phase_currentFramePredicted, &hTonalMDCTConc->pTCI->numIndexes, hTonalMDCTConc->lastPitchLag, pitchLag,
     468         135 :                                        hTonalMDCTConc->lastBlockData.spectralData, hTonalMDCTConc->lastBlockData.scaleFactors, powerSpectrum,
     469         135 :                                        nSamples, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples * hTonalMDCTConc->nSamples / 400.0f /* floorPowerSpectrum */, psychParamsCurrent );
     470             :             }
     471             :         }
     472             :     }
     473             :     else
     474             :     {
     475        1149 :         hTonalMDCTConc->pTCI->numIndexes = 0;
     476             :     }
     477             : 
     478        7215 :     *numIndices = hTonalMDCTConc->pTCI->numIndexes;
     479             : 
     480        7215 :     return;
     481             : }
     482             : 
     483             : 
     484       34524 : void TonalMDCTConceal_InsertNoise(
     485             :     const TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
     486             :     float *mdctSpectrum,                      /*OUT*/
     487             :     const int16_t tonalConcealmentActive,
     488             :     int16_t *pSeed,
     489             :     const float tiltCompFactor,
     490             :     const float crossfadeGain,
     491             :     const float concealment_noise[L_FRAME48k],
     492             :     const float cngLevelBackgroundTrace_bfi,
     493             :     const int16_t crossOverFreq )
     494             : {
     495             :     int16_t i, l;
     496             :     float x, y;
     497             :     Word16 rnd;
     498             :     float g, nrgNoiseInLastFrame, nrgWhiteNoise, tiltFactor, tilt;
     499             :     float last_block_nrg_correct;
     500             : 
     501       34524 :     push_wmops( "InsertNoise" );
     502             : 
     503       34524 :     g = 1.0f - crossfadeGain;
     504       34524 :     if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
     505             :     {
     506       20784 :         rnd = 1977;
     507             :     }
     508             :     else
     509             :     {
     510       13740 :         rnd = *pSeed;
     511             :     }
     512             : 
     513             :     /* based on what is done in tcx_noise_filling() */
     514             :     /* always initialize these to avoid compiler warnings */
     515       34524 :     tiltFactor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / hTonalMDCTConc->lastBlockData.nSamples );
     516       34524 :     tilt = 1.0f;
     517       34524 :     nrgNoiseInLastFrame = 0.0f;
     518       34524 :     nrgWhiteNoise = 0.0f;
     519       34524 :     hTonalMDCTConc->faded_signal_nrg = 0.0f;
     520       34524 :     last_block_nrg_correct = 0.0f;
     521             : 
     522       34524 :     if ( !hTonalMDCTConc->lastBlockData.blockIsValid )
     523             :     {
     524             :         /* may just become active if the very first frame is lost */
     525           0 :         set_f( mdctSpectrum, 0.0f, hTonalMDCTConc->nSamples );
     526             :     }
     527       34524 :     else if ( concealment_noise != NULL )
     528             :     {
     529       11073 :         if ( !tonalConcealmentActive )
     530             :         {
     531             :             /* if fadeout has not started yet, only apply sign scrambling */
     532       10662 :             if ( crossfadeGain == 1.0f )
     533             :             {
     534     2224293 :                 for ( i = 0; i < crossOverFreq; i++ )
     535             :                 {
     536     2218464 :                     if ( concealment_noise[i] > 0 )
     537             :                     {
     538     1154832 :                         mdctSpectrum[i] = hTonalMDCTConc->lastBlockData.spectralData[i];
     539             :                     }
     540             :                     else
     541             :                     {
     542     1063632 :                         mdctSpectrum[i] = -hTonalMDCTConc->lastBlockData.spectralData[i];
     543             :                     }
     544             :                 }
     545             : 
     546     1399845 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     547             :                 {
     548     1394016 :                     mdctSpectrum[l] = 0.0f;
     549             :                 }
     550             :             }
     551             :             /* actual fadeout is done in this case */
     552             :             else
     553             :             {
     554        4833 :                 g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg );
     555             : 
     556     1843809 :                 for ( i = 0; i < crossOverFreq; i++ )
     557             :                 {
     558     1838976 :                     x = hTonalMDCTConc->lastBlockData.spectralData[i];
     559     1838976 :                     y = concealment_noise[i];
     560             : 
     561     1838976 :                     if ( y > 0 )
     562             :                     {
     563       96642 :                         mdctSpectrum[i] = g * y + crossfadeGain * x;
     564             :                     }
     565             :                     else
     566             :                     {
     567     1742334 :                         mdctSpectrum[i] = g * y - crossfadeGain * x;
     568             :                     }
     569             : 
     570     1838976 :                     hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[i] * mdctSpectrum[i];
     571             :                 }
     572     1279137 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     573             :                 {
     574     1274304 :                     mdctSpectrum[l] = 0.0f;
     575             :                 }
     576             :             }
     577             :         }
     578             :         else
     579             :         {
     580         411 :             assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
     581             : 
     582             :             /* initialize bins of tonal components with zero: basically not
     583             :             necessary, but currently the whole spectrum is rescaled in
     584             :             mdct_noiseShaping() and then there would be a processing of
     585             :             uninitialized values */
     586        3396 :             for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     587             :             {
     588       23874 :                 for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     589             :                 {
     590       20889 :                     mdctSpectrum[l] = 0;
     591       20889 :                     if ( l < crossOverFreq )
     592             :                     {
     593       20658 :                         last_block_nrg_correct += hTonalMDCTConc->lastBlockData.spectralData[l] * hTonalMDCTConc->lastBlockData.spectralData[l];
     594       20658 :                         hTonalMDCTConc->curr_noise_nrg -= concealment_noise[l] * concealment_noise[l];
     595             :                     }
     596             :                 }
     597             :             }
     598             : 
     599             :             /* if fadeout has not started yet, only apply sign scrambling */
     600         411 :             if ( crossfadeGain == 1.0f )
     601             :             {
     602       16530 :                 for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     603             :                 {
     604       16185 :                     if ( concealment_noise[l] > 0 )
     605             :                     {
     606        7806 :                         mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     607             :                     }
     608             :                     else
     609             :                     {
     610        8379 :                         mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
     611             :                     }
     612             :                 }
     613        2604 :                 for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     614             :                 {
     615       30717 :                     for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     616             :                     {
     617       28458 :                         if ( concealment_noise[l] > 0 )
     618             :                         {
     619       14901 :                             mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     620             :                         }
     621             :                         else
     622             :                         {
     623       13557 :                             mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
     624             :                         }
     625             :                     }
     626             :                 }
     627             : 
     628       68226 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     629             :                 {
     630       67881 :                     if ( concealment_noise[l] > 0 )
     631             :                     {
     632       35424 :                         mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     633             :                     }
     634             :                     else
     635             :                     {
     636       32457 :                         mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
     637             :                     }
     638             :                 }
     639             : 
     640       60705 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     641             :                 {
     642       60360 :                     mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     643             :                 }
     644             :             }
     645             :             /* actual fadeout is done in this case */
     646             :             else
     647             :             {
     648          66 :                 g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg );
     649             : 
     650        4233 :                 for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     651             :                 {
     652        4167 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     653        4167 :                     y = concealment_noise[l];
     654             : 
     655        4167 :                     if ( y > 0 )
     656             :                     {
     657         339 :                         mdctSpectrum[l] = g * y + crossfadeGain * x;
     658             :                     }
     659             :                     else
     660             :                     {
     661        3828 :                         mdctSpectrum[l] = g * y - crossfadeGain * x;
     662             :                     }
     663        4167 :                     hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
     664             :                 }
     665         381 :                 for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     666             :                 {
     667        6222 :                     for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     668             :                     {
     669        5907 :                         x = hTonalMDCTConc->lastBlockData.spectralData[l];
     670        5907 :                         y = concealment_noise[l];
     671             : 
     672        5907 :                         if ( y > 0 )
     673             :                         {
     674         384 :                             mdctSpectrum[l] = g * y + crossfadeGain * x;
     675             :                         }
     676             :                         else
     677             :                         {
     678        5523 :                             mdctSpectrum[l] = g * y - crossfadeGain * x;
     679             :                         }
     680        5907 :                         hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
     681             :                     }
     682             :                 }
     683             : 
     684       14049 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     685             :                 {
     686       13983 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     687       13983 :                     y = concealment_noise[l];
     688             : 
     689       13983 :                     if ( y > 0 )
     690             :                     {
     691         186 :                         mdctSpectrum[l] = g * y + crossfadeGain * x;
     692             :                     }
     693             :                     else
     694             :                     {
     695       13797 :                         mdctSpectrum[l] = g * y - crossfadeGain * x;
     696             :                     }
     697       13983 :                     hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
     698             :                 }
     699             : 
     700       13914 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     701             :                 {
     702       13848 :                     mdctSpectrum[l] = 0.0f;
     703             :                 }
     704             :             }
     705             :         }
     706             : 
     707       11073 :         if ( hTonalMDCTConc->faded_signal_nrg > 0.0f && hTonalMDCTConc->curr_noise_nrg > MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG )
     708             :         {
     709             :             float nrg_corr_factor;
     710             : 
     711         498 :             nrg_corr_factor = sqrtf( ( hTonalMDCTConc->last_block_nrg - last_block_nrg_correct ) / hTonalMDCTConc->faded_signal_nrg );
     712         498 :             v_multc( mdctSpectrum, nrg_corr_factor, mdctSpectrum, crossOverFreq );
     713             :         }
     714             :     }
     715             :     else
     716             :     {
     717       23451 :         if ( !tonalConcealmentActive )
     718             :         {
     719    10039419 :             for ( i = 0; i < crossOverFreq; i++ )
     720             :             {
     721    10017426 :                 x = hTonalMDCTConc->lastBlockData.spectralData[i];
     722    10017426 :                 nrgNoiseInLastFrame += x * x;
     723    10017426 :                 rnd = own_random( &rnd );
     724    10017426 :                 mdctSpectrum[i] = tilt * rnd;
     725    10017426 :                 tilt *= tiltFactor;
     726    10017426 :                 nrgWhiteNoise += mdctSpectrum[i] * mdctSpectrum[i];
     727             :             }
     728       21993 :             if ( nrgWhiteNoise > 0 )
     729             :             {
     730       21993 :                 g *= (float) sqrt( nrgNoiseInLastFrame / nrgWhiteNoise );
     731             :             }
     732    10039419 :             for ( i = 0; i < crossOverFreq; i++ )
     733             :             {
     734    10017426 :                 x = hTonalMDCTConc->lastBlockData.spectralData[i];
     735    10017426 :                 y = mdctSpectrum[i];
     736             : 
     737    10017426 :                 if ( y > 0 )
     738             :                 {
     739     5030757 :                     mdctSpectrum[i] = g * y + crossfadeGain * x;
     740             :                 }
     741             :                 else
     742             :                 {
     743     4986669 :                     mdctSpectrum[i] = g * y - crossfadeGain * x;
     744             :                 }
     745             :             }
     746             : 
     747     6494487 :             for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     748             :             {
     749     6472494 :                 mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     750             :             }
     751             :         }
     752             :         else
     753             :         {
     754        1458 :             assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
     755      103911 :             for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     756             :             {
     757      102453 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     758      102453 :                 rnd = own_random( &rnd );
     759      102453 :                 mdctSpectrum[l] = tilt * rnd;
     760      102453 :                 tilt *= tiltFactor;
     761      102453 :                 nrgNoiseInLastFrame += x * x;
     762      102453 :                 nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
     763             :             }
     764             : 
     765        7443 :             for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     766             :             {
     767        5985 :                 tilt *= (float) pow( tiltFactor, hTonalMDCTConc->pTCI->upperIndex[i - 1] - hTonalMDCTConc->pTCI->lowerIndex[i - 1] + 1 );
     768      107142 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     769             :                 {
     770      101157 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     771      101157 :                     rnd = own_random( &rnd );
     772      101157 :                     mdctSpectrum[l] = tilt * rnd;
     773      101157 :                     tilt *= tiltFactor;
     774      101157 :                     nrgNoiseInLastFrame += x * x;
     775      101157 :                     nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
     776             :                 }
     777             :             }
     778        1458 :             tilt *= (float) pow( tiltFactor, hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] - hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1 );
     779             : 
     780      364794 :             for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     781             :             {
     782      363336 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     783      363336 :                 rnd = own_random( &rnd );
     784      363336 :                 mdctSpectrum[l] = tilt * rnd;
     785      363336 :                 tilt *= tiltFactor;
     786      363336 :                 nrgNoiseInLastFrame += x * x;
     787      363336 :                 nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
     788             :             }
     789        1458 :             if ( nrgWhiteNoise > 0 )
     790             :             {
     791        1458 :                 g *= (float) sqrt( nrgNoiseInLastFrame / nrgWhiteNoise );
     792             :             }
     793      103911 :             for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     794             :             {
     795      102453 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     796      102453 :                 y = mdctSpectrum[l];
     797             : 
     798      102453 :                 if ( y > 0 )
     799             :                 {
     800       52725 :                     mdctSpectrum[l] = g * y + crossfadeGain * x;
     801             :                 }
     802             :                 else
     803             :                 {
     804       49728 :                     mdctSpectrum[l] = g * y - crossfadeGain * x;
     805             :                 }
     806             :             }
     807        7443 :             for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     808             :             {
     809      107142 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     810             :                 {
     811      101157 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     812      101157 :                     y = mdctSpectrum[l];
     813             : 
     814      101157 :                     if ( y > 0 )
     815             :                     {
     816       54105 :                         mdctSpectrum[l] = g * y + crossfadeGain * x;
     817             :                     }
     818             :                     else
     819             :                     {
     820       47052 :                         mdctSpectrum[l] = g * y - crossfadeGain * x;
     821             :                     }
     822             :                 }
     823             :             }
     824             :             /* initialize bins of tonal components with zero: basically not
     825             :                necessary, but currently the whole spectrum is rescaled in
     826             :                mdct_noiseShaping() and then there would be a processing of
     827             :                uninitialized values */
     828        8901 :             for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     829             :             {
     830       59517 :                 for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     831             :                 {
     832       52074 :                     mdctSpectrum[l] = 0;
     833             :                 }
     834             :             }
     835      364794 :             for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     836             :             {
     837      363336 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     838      363336 :                 y = mdctSpectrum[l];
     839             : 
     840      363336 :                 if ( y > 0 )
     841             :                 {
     842      179244 :                     mdctSpectrum[l] = g * y + crossfadeGain * x;
     843             :                 }
     844             :                 else
     845             :                 {
     846      184092 :                     mdctSpectrum[l] = g * y - crossfadeGain * x;
     847             :                 }
     848             :             }
     849             : 
     850      666558 :             for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     851             :             {
     852      665100 :                 mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     853             :             }
     854             :         }
     855             :     }
     856             : 
     857       34524 :     *pSeed = rnd;
     858             : 
     859       34524 :     pop_wmops();
     860             : 
     861       34524 :     return;
     862             : }
     863             : 
     864             : 
     865        1869 : void TonalMDCTConceal_Apply(
     866             :     TonalMDCTConcealPtr hTonalMDCTConc, /*IN */
     867             :     float *mdctSpectrum,                /*OUT */
     868             :     const PsychoacousticParameters *psychParamsCurrent )
     869             : {
     870             :     int16_t i, l;
     871             :     float *phaseDiff, *pCurrentPhase;
     872             :     float phaseToAdd;
     873             :     float powerSpectrum[L_FRAME_MAX];
     874             :     int16_t nSamples;
     875             :     int16_t nBands;
     876             : 
     877        1869 :     if ( hTonalMDCTConc->lastBlockData.blockIsValid & hTonalMDCTConc->secondLastBlockData.blockIsValid )
     878             :     {
     879        1869 :         assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
     880             : 
     881        1869 :         nSamples = hTonalMDCTConc->nNonZeroSamples;
     882        1869 :         assert( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] < nSamples );
     883        1869 :         mvr2r( hTonalMDCTConc->secondLastPowerSpectrum, powerSpectrum, nSamples ); /* Convert from 16 bits to 32 bits */
     884        1869 :         if ( psychParamsCurrent == NULL )
     885             :         {
     886         834 :             nBands = FDNS_NPTS;
     887         834 :             mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors, nBands );
     888             :         }
     889             :         else
     890             :         {
     891        1035 :             sns_shape_spectrum( powerSpectrum, psychParamsCurrent, hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->nSamplesCore );
     892        1035 :             nBands = psychParamsCurrent->nBands;
     893             :         }
     894             : 
     895        1869 :         v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, nSamples - hTonalMDCTConc->nSamplesCore );
     896             : 
     897        1869 :         phaseDiff = hTonalMDCTConc->pTCI->phaseDiff; /* if multiple frame loss occurs use the phase from the last frame and continue rotating */
     898        1869 :         pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
     899             : 
     900        1869 :         if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
     901             :         {
     902        1359 :             if ( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
     903             :             {
     904          75 :                 hTonalMDCTConc->nFramesLost += 1;
     905             :             }
     906             :             else
     907             :             {
     908        1284 :                 hTonalMDCTConc->nFramesLost = 1.5;
     909             :             }
     910             :         }
     911             : 
     912             :         /* for each index group */
     913       12297 :         for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     914             :         {
     915       10428 :             phaseToAdd = hTonalMDCTConc->nFramesLost * phaseDiff[i];
     916             : 
     917             :             /* Move phaseToAdd to range -EVS_PI..EVS_PI */
     918       32976 :             while ( phaseToAdd > EVS_PI )
     919             :             {
     920       22548 :                 phaseToAdd -= PI2;
     921             :             }
     922             : 
     923       10428 :             while ( phaseToAdd < -EVS_PI )
     924             :             {
     925             :                 /* should never occur in flt - kept for safety reasons */
     926           0 :                 phaseToAdd += PI2;
     927             :             }
     928             : 
     929       83391 :             for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     930             :             {
     931       72963 :                 const float currentPhase = ( *pCurrentPhase++ ) + phaseToAdd; /* *pCurrentPhase and phaseToAdd are in range -EVS_PI..EVS_PI */
     932       72963 :                 mdctSpectrum[l] = (float) cos( currentPhase ) * powerSpectrum[l];
     933             :             }
     934             :         }
     935             :     }
     936             : 
     937        1869 :     hTonalMDCTConc->nFramesLost++;
     938             : 
     939        1869 :     return;
     940             : }
     941             : 
     942             : 
     943     2768334 : void TonalMDCTConceal_SaveTimeSignal(
     944             :     TonalMDCTConcealPtr hTonalMDCTConc,
     945             :     float *timeSignal,
     946             :     const int16_t nNewSamples )
     947             : {
     948     2768334 :     if ( nNewSamples == hTonalMDCTConc->nSamples )
     949             :     {
     950     2720748 :         assert( nNewSamples <= L_FRAME_MAX );
     951             : 
     952     2720748 :         if ( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
     953             :         {
     954     2719428 :             mvr2r( hTonalMDCTConc->lastPcmOut + hTonalMDCTConc->nSamples / 2, hTonalMDCTConc->secondLastPcmOut, hTonalMDCTConc->nSamples / 2 );
     955             :         }
     956             : 
     957     2720748 :         mvr2r( timeSignal, hTonalMDCTConc->lastPcmOut, hTonalMDCTConc->nSamples );
     958             :     }
     959             : 
     960     2768334 :     return;
     961             : }
     962             : 
     963       11073 : void TonalMdctConceal_create_concealment_noise(
     964             :     float concealment_noise[L_FRAME48k],
     965             :     CPE_DEC_HANDLE hCPE,
     966             :     const int16_t L_frameTCX,
     967             :     const int16_t L_frame,
     968             :     const int16_t idchan,
     969             :     const int16_t subframe_idx,
     970             :     const int16_t core,
     971             :     const float crossfade_gain,
     972             :     const TONALMDCTCONC_NOISE_GEN_MODE noise_gen_mode )
     973             : {
     974             :     STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct;
     975             :     TonalMDCTConcealPtr hTonalMDCTConc;
     976             :     Decoder_State *st;
     977             :     HANDLE_FD_CNG_COM hFdCngCom;
     978             :     int16_t *rnd_c, *rnd;
     979             :     int16_t crossOverFreq, i, save_rnd_c, max_noise_line;
     980             :     float c, c_inv;
     981             :     float noise_shape_buffer[L_FRAME48k];
     982             :     int16_t inc, start_idx, stop_idx;
     983             :     float *cngNoiseLevelPtr;
     984             :     float last_scf;
     985             : 
     986       11073 :     push_wmops( "create_conc_noise" );
     987             : 
     988       11073 :     hStereoMdct = hCPE->hStereoMdct;
     989       11073 :     st = hCPE->hCoreCoder[idchan];
     990       11073 :     hTonalMDCTConc = st->hTonalMDCTConc;
     991       11073 :     hFdCngCom = st->hFdCngDec->hFdCngCom;
     992       11073 :     rnd = &hStereoMdct->noise_seeds_channels[idchan];
     993       11073 :     rnd_c = &hStereoMdct->noise_seed_common;
     994             : 
     995             :     /* determine start bin for IGF */
     996       11073 :     if ( st->igf == 0 )
     997             :     {
     998        4176 :         if ( st->narrowBand == 0 )
     999             :         {
    1000             :             /* minimum needed for output with sampling rates lower then the
    1001             :                nominal sampling rate */
    1002        4176 :             crossOverFreq = min( L_frameTCX, L_frame );
    1003             :         }
    1004             :         else
    1005             :         {
    1006           0 :             crossOverFreq = L_frameTCX;
    1007             :         }
    1008             :     }
    1009             :     else
    1010             :     {
    1011        6897 :         crossOverFreq = min( st->hIGFDec->infoIGFStartLine, L_frameTCX );
    1012             :     }
    1013             : 
    1014             :     /* for tonal mdct concealment with tonal components above the crossover frequency, conditionally raise the frequency index until which noise is generated */
    1015       11073 :     max_noise_line = crossOverFreq;
    1016       11073 :     if ( st->tonal_mdct_plc_active )
    1017             :     {
    1018         411 :         max_noise_line = max( max_noise_line, hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1 );
    1019             :     }
    1020             : 
    1021             :     /* first lost frame is handled separately */
    1022       11073 :     if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
    1023             :     {
    1024        6174 :         *rnd = 1977 + idchan;
    1025             :         /* will be set twice when looping over two channels, but does not matter */
    1026        6174 :         *rnd_c = 1979;
    1027             :     }
    1028             : 
    1029       11073 :     if ( crossfade_gain == 1.0f )
    1030             :     {
    1031             :         /* In first frame, noise is weighted with zero anyway, we only need the random numbers for the sign scrambling */
    1032     2355387 :         for ( i = 0; i < max_noise_line; i++ )
    1033             :         {
    1034     2349213 :             *rnd = own_random( rnd );
    1035     2349213 :             concealment_noise[i] = *rnd;
    1036             :         }
    1037             : 
    1038        6174 :         pop_wmops();
    1039             : 
    1040        6174 :         return;
    1041             :     }
    1042             : 
    1043        4899 :     save_rnd_c = *rnd_c;
    1044             : 
    1045        4899 :     c = sqrtf( hStereoMdct->lastCoh );
    1046        4899 :     c_inv = sqrtf( 1 - hStereoMdct->lastCoh );
    1047             : 
    1048             :     /* pre-compute the noise shape for later weighting of the noise spectra */
    1049        4899 :     cngNoiseLevelPtr = &hFdCngCom->cngNoiseLevel[0];
    1050        4899 :     inc = ( st->core > TCX_20_CORE ) ? 2 : 1;
    1051        4899 :     start_idx = hFdCngCom->startBand / inc;
    1052        4899 :     stop_idx = hFdCngCom->stopFFTbin / inc;
    1053             : 
    1054       14673 :     for ( i = 0; i < start_idx; i++ )
    1055             :     {
    1056        9774 :         noise_shape_buffer[i] = 0.0f;
    1057             :     }
    1058     1558965 :     for ( ; i < stop_idx; i++, cngNoiseLevelPtr += inc )
    1059             :     {
    1060     1554066 :         noise_shape_buffer[i] = sqrtf( *( cngNoiseLevelPtr ) );
    1061             :     }
    1062             : 
    1063        4899 :     last_scf = sqrtf( *( cngNoiseLevelPtr - inc ) );
    1064             : 
    1065      306756 :     for ( ; i < max_noise_line; i++ )
    1066             :     {
    1067      301857 :         noise_shape_buffer[i] = last_scf;
    1068             :     }
    1069             : 
    1070             :     /* fill the noise vector */
    1071        4899 :     hTonalMDCTConc->curr_noise_nrg = MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG;
    1072        4899 :     if ( noise_gen_mode == EQUAL_CORES || ( ( noise_gen_mode == TCX20_IN_0_TCX10_IN_1 && idchan == 0 ) || ( noise_gen_mode == TCX10_IN_0_TCX20_IN_1 && idchan == 1 ) ) )
    1073             :     {
    1074             :         /* current channel is TCX20 -> generate noise for "full-length" spectrum */
    1075     1870596 :         for ( i = 0; i < max_noise_line; i++ )
    1076             :         {
    1077     1865697 :             *rnd = own_random( rnd );
    1078     1865697 :             *rnd_c = own_random( rnd_c );
    1079             : 
    1080     1865697 :             concealment_noise[i] = ( c_inv * *rnd + c * *rnd_c ) * noise_shape_buffer[i];
    1081     1865697 :             hTonalMDCTConc->curr_noise_nrg += concealment_noise[i] * concealment_noise[i];
    1082             :         }
    1083             :     }
    1084             :     else /* ( ( noise_gen_mode == TCX10_IN_0_TCX20_IN_1 && idchan == 0 ) || ( noise_gen_mode == TCX20_IN_0_TCX10_IN_1 && idchan == 1 ) )  */
    1085             :     {
    1086             :         /* current channel is TCX10 and the other is TCX20 -> generate noise for "half-length" spectrum, but "increment" mid seed twice, to have the same seed in mid as the other (TCX20) channel for next frame */
    1087           0 :         for ( i = 0; i < max_noise_line; i++ )
    1088             :         {
    1089           0 :             *rnd = own_random( rnd );
    1090           0 :             *rnd_c = own_random( rnd_c );
    1091             : 
    1092           0 :             concealment_noise[i] = ( c_inv * *rnd + c * *rnd_c ) * noise_shape_buffer[i];
    1093           0 :             hTonalMDCTConc->curr_noise_nrg += concealment_noise[i] * concealment_noise[i];
    1094             : 
    1095           0 :             *rnd_c = own_random( rnd_c );
    1096             :         }
    1097             :     }
    1098             : 
    1099        4899 :     if ( st->tonal_mdct_plc_active )
    1100             :     {
    1101         294 :         for ( i = crossOverFreq; i < max( crossOverFreq, hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] ); ++i )
    1102             :         {
    1103         228 :             concealment_noise[i] *= 0.0f;
    1104             :         }
    1105             :     }
    1106             : 
    1107             :     /* restore common seed
    1108             :          - after finishing the first channel
    1109             :          - after a first subframe if the current channel is TCX10 */
    1110        4899 :     if ( ( idchan == 0 && ( core == TCX_20 || ( core == TCX_10 && subframe_idx == 1 ) ) ) || ( core == TCX_10 && subframe_idx == 0 ) )
    1111             :     {
    1112        2421 :         *rnd_c = save_rnd_c;
    1113             :     }
    1114             : 
    1115        4899 :     st->seed_tcx_plc = *rnd;
    1116             : 
    1117        4899 :     pop_wmops();
    1118             : 
    1119        4899 :     return;
    1120             : }
    1121             : 
    1122        7074 : void TonalMdctConceal_whiten_noise_shape(
    1123             :     Decoder_State *st,
    1124             :     const int16_t L_frame,
    1125             :     const TONALMDCTCONC_NOISE_SHAPE_WHITENING_MODE whitening_mode )
    1126             : {
    1127             :     int16_t inc, start_idx, stop_idx;
    1128             :     float *noiseLevelPtr, *scfs_bg, *scfs_for_shaping;
    1129             :     HANDLE_FD_CNG_COM hFdCngCom;
    1130             :     float whitenend_noise_shape[L_FRAME16k];
    1131             :     float scfs_int[FDNS_NPTS];
    1132             :     const PsychoacousticParameters *psychParams;
    1133             : 
    1134        7074 :     push_wmops( "apply_sns_on_noise_shape" );
    1135             : 
    1136        7074 :     scfs_bg = &st->hTonalMDCTConc->scaleFactorsBackground[0];
    1137        7074 :     psychParams = st->hTonalMDCTConc->psychParams;
    1138        7074 :     hFdCngCom = st->hFdCngDec->hFdCngCom;
    1139             : 
    1140        7074 :     inc = ( ( whitening_mode == ON_FIRST_LOST_FRAME ? st->core : st->last_core ) > TCX_20_CORE ) ? 2 : 1;
    1141        7074 :     start_idx = hFdCngCom->startBand / inc;
    1142        7074 :     stop_idx = L_frame / inc;
    1143        7074 :     noiseLevelPtr = hFdCngCom->cngNoiseLevel;
    1144             : 
    1145        7074 :     set_zero( whitenend_noise_shape, start_idx );
    1146     2232279 :     for ( int16_t j = start_idx; j < stop_idx; j++, noiseLevelPtr += inc )
    1147             :     {
    1148     2225205 :         whitenend_noise_shape[j] = *noiseLevelPtr;
    1149             :     }
    1150             : 
    1151        7074 :     if ( whitening_mode == ON_FIRST_LOST_FRAME )
    1152             :     {
    1153             :         float scf[SNS_NPTS];
    1154             : 
    1155        1263 :         sns_compute_scf( whitenend_noise_shape, psychParams, L_frame, scf );
    1156        1263 :         sns_interpolate_scalefactors( scfs_int, scf, ENC );
    1157        1263 :         sns_interpolate_scalefactors( scfs_bg, scf, DEC );
    1158        1263 :         scfs_for_shaping = &scfs_int[0];
    1159             :     }
    1160             :     else /* whitening_mode == ON_FIRST_GOOD_FRAME */
    1161             :     {
    1162        5811 :         scfs_for_shaping = &scfs_bg[0];
    1163             :     }
    1164             : 
    1165        7074 :     if ( sum_f( scfs_for_shaping, FDNS_NPTS ) > 0.0f )
    1166             :     {
    1167        2475 :         sns_shape_spectrum( whitenend_noise_shape, psychParams, scfs_for_shaping, L_frame );
    1168        2475 :         mvr2r( whitenend_noise_shape + start_idx, hFdCngCom->cngNoiseLevel, stop_idx - start_idx );
    1169             :     }
    1170             :     else
    1171             :     {
    1172        4599 :         set_zero( hFdCngCom->cngNoiseLevel, stop_idx - start_idx );
    1173             :     }
    1174             : 
    1175        7074 :     pop_wmops();
    1176        7074 : }

Generated by: LCOV version 1.14