LCOV - code coverage report
Current view: top level - lib_dec - tonalMDCTconcealment.c (source / functions) Hit Total Coverage
Test: Coverage on main @ fec202a8f89be4a2f278a9fc377bfb58b58fab11 Lines: 441 447 98.7 %
Date: 2025-09-11 08:49:05 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      754173 : 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      754173 :     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      754173 :     assert( ( hTonalMDCTConc->nScaleFactors == nScaleFactors ) || ( hTonalMDCTConc->nSamples != nSamples ) ); /* If nSamples doesn't change then also nScaleFactors must stay the same */
      69             : 
      70      754173 :     hTonalMDCTConc->tcx_cfg = hTcxCfg;
      71      754173 :     hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
      72      754173 :     hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
      73      754173 :     hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
      74      754173 :     hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
      75      754173 :     hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
      76      754173 :     hTonalMDCTConc->lastBlockData.blockIsValid = 0;
      77      754173 :     hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
      78      754173 :     hTonalMDCTConc->nSamples = 0;
      79      754173 :     hTonalMDCTConc->nScaleFactors = 0;
      80             : 
      81      754173 :     hTonalMDCTConc->lastBlockData.blockIsConcealed = 0;
      82      754173 :     hTonalMDCTConc->secondLastBlockData.blockIsConcealed = 0;
      83      754173 :     hTonalMDCTConc->pTCI = (TonalComponentsInfo *) hTonalMDCTConc->timeDataBuffer;
      84             : 
      85      754173 :     hTonalMDCTConc->lastPitchLag = 0;
      86             : 
      87      754173 :     if ( hTonalMDCTConc->nSamples != nSamples )
      88             :     {
      89      754173 :         hTonalMDCTConc->secondLastBlockData.blockIsValid = 0;
      90      754173 :         hTonalMDCTConc->lastBlockData.blockIsValid = 0;
      91             :     }
      92      754173 :     hTonalMDCTConc->nSamples = nSamples;
      93      754173 :     hTonalMDCTConc->nSamplesCore = nSamplesCore;
      94      754173 :     hTonalMDCTConc->nScaleFactors = nScaleFactors;
      95             : 
      96      754173 :     set_zero( hTonalMDCTConc->scaleFactorsBackground, FDNS_NPTS );
      97      754173 :     hTonalMDCTConc->scf_fadeout = 1.0f;
      98      754173 :     PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k, 64, 1, 1, &hTonalMDCTConc->psychParamsTCX20 );
      99      754173 :     PsychoacousticParameters_Init( INT_FS_16k, L_FRAME16k / 2, 64, 0, 1, &hTonalMDCTConc->psychParamsTCX10 );
     100      754173 :     hTonalMDCTConc->psychParams = NULL;
     101             : 
     102      754173 :     hTonalMDCTConc->last_block_nrg = 0.0f;
     103      754173 :     hTonalMDCTConc->curr_noise_nrg = 0.0f;
     104      754173 :     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      754173 :     hTonalMDCTConc->secondLastPcmOut = &hTonalMDCTConc->timeDataBuffer[( 3 * L_FRAME_MAX ) / 2 - ( 3 * min( L_FRAME_MAX, nSamples ) ) / 2];
     110      754173 :     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      754173 :     assert( sizeof( *hTonalMDCTConc->pTCI ) <= ( hTonalMDCTConc->lastPcmOut - hTonalMDCTConc->timeDataBuffer ) * sizeof( hTonalMDCTConc->timeDataBuffer[0] ) );
     115             : 
     116      754173 :     return IVAS_ERR_OK;
     117             : }
     118             : 
     119             : 
     120    27406495 : 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    27406495 :     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    27406495 :     if ( !hTonalMDCTConc->lastBlockData.tonalConcealmentActive || ( hTonalMDCTConc->lastBlockData.nSamples != nNewSamples ) )
     137             :     {
     138    27362040 :         if ( nNewSamples <= L_FRAME_MAX )
     139             :         {
     140             :             /* Shift the buffers */
     141    27247207 :             temp = hTonalMDCTConc->secondLastBlockData.spectralData; /* Save the pointer */
     142    27247207 :             hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->lastBlockData.spectralData;
     143    27247207 :             hTonalMDCTConc->lastBlockData.spectralData = temp;
     144    27247207 :             temp = hTonalMDCTConc->secondLastBlockData.scaleFactors;
     145    27247207 :             hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->lastBlockData.scaleFactors;
     146    27247207 :             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      114833 :             hTonalMDCTConc->lastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[0];
     152      114833 :             hTonalMDCTConc->secondLastBlockData.spectralData = hTonalMDCTConc->spectralDataBuffers[1];
     153      114833 :             hTonalMDCTConc->lastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[0];
     154      114833 :             hTonalMDCTConc->secondLastBlockData.scaleFactors = hTonalMDCTConc->scaleFactorsBuffers[1];
     155             :         }
     156    27362040 :         nOldSamples = hTonalMDCTConc->lastBlockData.nSamples;
     157    27362040 :         hTonalMDCTConc->lastBlockData.nSamples = nNewSamples;
     158    27362040 :         hTonalMDCTConc->secondLastBlockData.nSamples = nOldSamples;
     159    27362040 :         nOldSamples = hTonalMDCTConc->lastBlockData.nSamplesCore;
     160    27362040 :         hTonalMDCTConc->lastBlockData.nSamplesCore = nNewSamplesCore;
     161    27362040 :         hTonalMDCTConc->secondLastBlockData.nSamplesCore = nOldSamples;
     162             :     }
     163             : 
     164    27406495 :     if ( ( nNewSamples > 0 ) && ( nNewSamples <= 2 * L_FRAME_MAX ) )
     165             :     {
     166             :         /* Store new data */
     167             :         int16_t i;
     168             : 
     169    27406495 :         hTonalMDCTConc->last_block_nrg = 0.0f;
     170 12349911371 :         for ( i = 0; i < infoIGFStartLine; i++ )
     171             :         {
     172 12322504876 :             hTonalMDCTConc->lastBlockData.spectralData[i] = mdctSpectrum[i];
     173 12322504876 :             hTonalMDCTConc->last_block_nrg += mdctSpectrum[i] * mdctSpectrum[i];
     174             :         }
     175  8037030859 :         for ( ; i < nNewSamples; i++ )
     176             :         {
     177  8009624364 :             hTonalMDCTConc->lastBlockData.spectralData[i] = mdctSpectrum[i];
     178             :         }
     179             : 
     180    27406495 :         mvr2r( scaleFactors, hTonalMDCTConc->lastBlockData.scaleFactors, hTonalMDCTConc->nScaleFactors );
     181             :     }
     182             : 
     183    27406495 :     return;
     184             : }
     185             : 
     186             : 
     187    32647776 : 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    32647776 :     assert( !( !badBlock && tonalConcealmentActive ) );
     197             : 
     198    32647776 :     if ( badBlock )
     199             :     {
     200     2226073 :         newBlockIsValid = hTonalMDCTConc->lastBlockData.blockIsValid;
     201             :     }
     202             :     else
     203             :     {
     204    30421703 :         newBlockIsValid = ( nNewSamples <= 2 * L_FRAME_MAX ) && ( nNewSamples > 0 );
     205             :     }
     206             : 
     207             :     /* Shift old state */
     208    32647776 :     hTonalMDCTConc->secondLastBlockData.blockIsConcealed = hTonalMDCTConc->lastBlockData.blockIsConcealed;
     209    32647776 :     hTonalMDCTConc->secondLastBlockData.blockIsValid = hTonalMDCTConc->lastBlockData.blockIsValid;
     210    32647776 :     hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive = hTonalMDCTConc->lastBlockData.tonalConcealmentActive;
     211             : 
     212             :     /* Store new state */
     213    32647776 :     hTonalMDCTConc->lastBlockData.blockIsConcealed = badBlock;
     214    32647776 :     hTonalMDCTConc->lastBlockData.blockIsValid = newBlockIsValid;
     215    32647776 :     hTonalMDCTConc->lastBlockData.tonalConcealmentActive = tonalConcealmentActive;
     216    32647776 :     hTonalMDCTConc->lastPitchLag = pitchLag;
     217             : 
     218    32647776 :     return;
     219             : }
     220             : 
     221             : 
     222      171929 : 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      171929 :     pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
     232             :     /* for each index/index group */
     233      468389 :     for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     234             :     {
     235     2353833 :         for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     236             :         {
     237     2057373 :             *pCurrentPhase++ = (float) atan2( secondLastMDST[l], secondLastMDCT[l] );
     238             :         }
     239             :     }
     240             : 
     241      171929 :     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      171929 : 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      171929 :     phaseDiff = hTonalMDCTConc->pTCI->phaseDiff;
     264      468389 :     for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     265             :     {
     266      296460 :         k = hTonalMDCTConc->pTCI->indexOfTonalPeak[i];
     267      296460 :         odft_left = powerSpectrum[k - 1];
     268      296460 :         odft_right = powerSpectrum[k + 1];
     269      296460 :         if ( odft_left >= CNST_maxRatio * odft_right )
     270             :         {
     271        2070 :             a = (float) tan( 0.0f * EVS_PI / CNST_bandwidth );
     272             :         }
     273             :         else
     274             :         {
     275      294390 :             if ( odft_right >= CNST_maxRatio * odft_left )
     276             :             {
     277        2595 :                 a = (float) tan( 2.0f * EVS_PI / CNST_bandwidth );
     278             :             }
     279             :             else
     280             :             {
     281      291795 :                 Q = (float) pow( odft_left / odft_right, CNST_G );
     282      291795 :                 a = ( CNST_m - Q * CNST_s ) / ( CNST_n + Q * CNST_j );
     283             :             }
     284             :         }
     285      296460 :         fractional = (float) atan( a ) * ( CNST_bandwidth / 2.0f );
     286      296460 :         assert( ( fractional >= 0 ) && ( fractional <= EVS_PI + 1.192092896e-07F ) );
     287      296460 :         phaseDiff[i] = fractional + EVS_PI * ( k % 4 );
     288             :     }
     289             : 
     290      171929 :     return;
     291             : }
     292             : 
     293      171929 : 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    87204463 :     for ( k = 1; k <= nSamples - 2; k++ )
     304             :     {
     305    87032534 :         x = mdctSpec[k] * mdctSpec[k] + mdstSpec[k] * mdstSpec[k];
     306    87032534 :         powerSpec[k] = max( floorPowerSpectrum, x );
     307             :     }
     308      171929 :     powerSpec[0] = 0.5f * powerSpec[1];
     309      171929 :     powerSpec[nSamples - 1] = 0.5f * powerSpec[nSamples - 2];
     310             : 
     311      171929 :     return;
     312             : }
     313             : 
     314      171929 : 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      171929 :     nSamples = hTonalMDCTConc->nNonZeroSamples;
     328             : 
     329             :     /* It is taken into account that the MDCT is not normalized. */
     330      171929 :     floorPowerSpectrum = hTonalMDCTConc->nSamples * hTonalMDCTConc->nSamples / 400.0f;
     331      171929 :     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      171929 :     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      171929 :     if ( hTonalMDCTConc->nSamplesCore > hTonalMDCTConc->nSamples )
     341             :     {
     342         983 :         set_zero( powerSpectrum + hTonalMDCTConc->nSamples, hTonalMDCTConc->nSamplesCore - hTonalMDCTConc->nSamples );
     343             :     }
     344             : 
     345      171929 :     DetectTonalComponents( hTonalMDCTConc->pTCI->indexOfTonalPeak, hTonalMDCTConc->pTCI->lowerIndex, hTonalMDCTConc->pTCI->upperIndex, &hTonalMDCTConc->pTCI->numIndexes, hTonalMDCTConc->lastPitchLag, pitchLag,
     346      171929 :                            hTonalMDCTConc->lastBlockData.spectralData, hTonalMDCTConc->lastBlockData.scaleFactors, powerSpectrum, nSamples, hTonalMDCTConc->nSamplesCore, floorPowerSpectrum, psychParamsCurrent );
     347             : 
     348      171929 :     FindPhases( hTonalMDCTConc, secondLastMDCT, secondLastMDST );
     349             : 
     350      171929 :     FindPhaseDifferences( hTonalMDCTConc, powerSpectrum );
     351             : 
     352      171929 :     if ( hTonalMDCTConc->pTCI->numIndexes > 0 )
     353             :     {
     354       68179 :         hTonalMDCTConc->secondLastPowerSpectrum = hTonalMDCTConc->secondLastBlockData.spectralData;
     355             : 
     356    33990103 :         for ( i = 0; i < nSamples; i++ )
     357             :         {
     358    33921924 :             powerSpectrum[i] = (float) sqrt( powerSpectrum[i] );
     359             :         }
     360             : 
     361     4431635 :         for ( i = 0; i < hTonalMDCTConc->nScaleFactors; i++ )
     362             :         {
     363     4363456 :             invScaleFactors[i] = 1.0f / hTonalMDCTConc->secondLastBlockData.scaleFactors[i];
     364             :         }
     365             : 
     366       68179 :         if ( psychParamsCurrent == NULL )
     367             :         {
     368       27585 :             nBands = FDNS_NPTS;
     369       27585 :             mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, invScaleFactors, nBands );
     370             :         }
     371             :         else
     372             :         {
     373       40594 :             sns_shape_spectrum( powerSpectrum, psychParamsCurrent, invScaleFactors, hTonalMDCTConc->nSamplesCore );
     374       40594 :             nBands = psychParamsCurrent->nBands;
     375             :         }
     376             : 
     377       68179 :         v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, invScaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples - hTonalMDCTConc->nSamplesCore );
     378       68179 :         mvr2r( powerSpectrum, hTonalMDCTConc->secondLastPowerSpectrum, hTonalMDCTConc->nSamples ); /* 16 bits are now enough for storing the power spectrum */
     379             :     }
     380             : 
     381      171929 :     return;
     382             : }
     383             : 
     384             : 
     385      343858 : 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      343858 :     L_frame = hTonalMDCTConc->nSamples;
     396      343858 :     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      343858 :     if ( type == 'S' )
     399             :     {
     400      171929 :         TCX_MDST( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - ( left_overlap + right_overlap ) / 2, right_overlap, EVS_MONO );
     401             :     }
     402             :     else
     403             :     {
     404      171929 :         TCX_MDCT( windowedTimeSignal, mdxtOutput, left_overlap, L_frame - ( left_overlap + right_overlap ) / 2, right_overlap, EVS_MONO );
     405             :     }
     406             : 
     407      343858 :     return;
     408             : }
     409             : 
     410             : 
     411      270508 : 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      270508 :     float *powerSpectrum = secondLastMDST;
     420             :     int16_t i, nSamples;
     421             :     int16_t nBands;
     422             : 
     423      270508 :     nSamples = hTonalMDCTConc->nSamples;
     424      270508 :     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      181358 :         if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
     429             :         {
     430      181358 :             if ( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
     431             :             {
     432      171929 :                 CalcMDXT( hTonalMDCTConc, 'S', hTonalMDCTConc->secondLastPcmOut, secondLastMDST );
     433      171929 :                 CalcMDXT( hTonalMDCTConc, 'C', hTonalMDCTConc->secondLastPcmOut, secondLastMDCT );
     434      171929 :                 hTonalMDCTConc->nNonZeroSamples = 0;
     435   116127929 :                 for ( i = 0; i < hTonalMDCTConc->nSamples; i++ )
     436             :                 {
     437   115956000 :                     if ( hTonalMDCTConc->secondLastBlockData.spectralData[i] != 0 )
     438             :                     {
     439    78216639 :                         hTonalMDCTConc->nNonZeroSamples = i;
     440             :                     }
     441             :                 }
     442             :                 /* 23 is the maximum length of the MA filter in getEnvelope */
     443      171929 :                 hTonalMDCTConc->nNonZeroSamples = min( hTonalMDCTConc->nSamples, hTonalMDCTConc->nNonZeroSamples + 23 );
     444      171929 :                 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        9429 :                 nSamples = hTonalMDCTConc->nNonZeroSamples;
     451        9429 :                 mvr2r( hTonalMDCTConc->secondLastPowerSpectrum, powerSpectrum, nSamples ); /* Convert from 16 bits to 32 bits */
     452        9429 :                 if ( psychParamsCurrent == NULL )
     453             :                 {
     454        2451 :                     nBands = FDNS_NPTS;
     455        2451 :                     mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors, nBands );
     456             :                 }
     457             :                 else
     458             :                 {
     459        6978 :                     sns_shape_spectrum( powerSpectrum, psychParamsCurrent, hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->nSamplesCore );
     460        6978 :                     nBands = psychParamsCurrent->nBands;
     461             :                 }
     462             : 
     463        9429 :                 v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, nSamples - hTonalMDCTConc->nSamplesCore );
     464        9429 :                 v_mult( powerSpectrum, powerSpectrum, powerSpectrum, nSamples );
     465             : 
     466        9429 :                 RefineTonalComponents( hTonalMDCTConc->pTCI->indexOfTonalPeak, hTonalMDCTConc->pTCI->lowerIndex, hTonalMDCTConc->pTCI->upperIndex, hTonalMDCTConc->pTCI->phaseDiff,
     467        9429 :                                        hTonalMDCTConc->pTCI->phase_currentFramePredicted, &hTonalMDCTConc->pTCI->numIndexes, hTonalMDCTConc->lastPitchLag, pitchLag,
     468        9429 :                                        hTonalMDCTConc->lastBlockData.spectralData, hTonalMDCTConc->lastBlockData.scaleFactors, powerSpectrum,
     469        9429 :                                        nSamples, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->nSamples * hTonalMDCTConc->nSamples / 400.0f /* floorPowerSpectrum */, psychParamsCurrent );
     470             :             }
     471             :         }
     472             :     }
     473             :     else
     474             :     {
     475       89150 :         hTonalMDCTConc->pTCI->numIndexes = 0;
     476             :     }
     477             : 
     478      270508 :     *numIndices = hTonalMDCTConc->pTCI->numIndexes;
     479             : 
     480      270508 :     return;
     481             : }
     482             : 
     483             : 
     484     1587645 : 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     1587645 :     push_wmops( "InsertNoise" );
     502             : 
     503     1587645 :     g = 1.0f - crossfadeGain;
     504     1587645 :     if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
     505             :     {
     506      584442 :         rnd = 1977;
     507             :     }
     508             :     else
     509             :     {
     510     1003203 :         rnd = *pSeed;
     511             :     }
     512             : 
     513             :     /* based on what is done in tcx_noise_filling() */
     514             :     /* always initialize these to avoid compiler warnings */
     515     1587645 :     tiltFactor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / hTonalMDCTConc->lastBlockData.nSamples );
     516     1587645 :     tilt = 1.0f;
     517     1587645 :     nrgNoiseInLastFrame = 0.0f;
     518     1587645 :     nrgWhiteNoise = 0.0f;
     519     1587645 :     hTonalMDCTConc->faded_signal_nrg = 0.0f;
     520     1587645 :     last_block_nrg_correct = 0.0f;
     521             : 
     522     1587645 :     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     1587645 :     else if ( concealment_noise != NULL )
     528             :     {
     529      419474 :         if ( !tonalConcealmentActive )
     530             :         {
     531             :             /* if fadeout has not started yet, only apply sign scrambling */
     532      385972 :             if ( crossfadeGain == 1.0f )
     533             :             {
     534    59788787 :                 for ( i = 0; i < crossOverFreq; i++ )
     535             :                 {
     536    59636172 :                     if ( concealment_noise[i] > 0 )
     537             :                     {
     538    31079313 :                         mdctSpectrum[i] = hTonalMDCTConc->lastBlockData.spectralData[i];
     539             :                     }
     540             :                     else
     541             :                     {
     542    28556859 :                         mdctSpectrum[i] = -hTonalMDCTConc->lastBlockData.spectralData[i];
     543             :                     }
     544             :                 }
     545             : 
     546    37723083 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     547             :                 {
     548    37570468 :                     mdctSpectrum[l] = 0.0f;
     549             :                 }
     550             :             }
     551             :             /* actual fadeout is done in this case */
     552             :             else
     553             :             {
     554      233357 :                 g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg );
     555             : 
     556    91451477 :                 for ( i = 0; i < crossOverFreq; i++ )
     557             :                 {
     558    91218120 :                     x = hTonalMDCTConc->lastBlockData.spectralData[i];
     559    91218120 :                     y = concealment_noise[i];
     560             : 
     561    91218120 :                     if ( y > 0 )
     562             :                     {
     563    11068561 :                         mdctSpectrum[i] = g * y + crossfadeGain * x;
     564             :                     }
     565             :                     else
     566             :                     {
     567    80149559 :                         mdctSpectrum[i] = g * y - crossfadeGain * x;
     568             :                     }
     569             : 
     570    91218120 :                     hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[i] * mdctSpectrum[i];
     571             :                 }
     572    56888917 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     573             :                 {
     574    56655560 :                     mdctSpectrum[l] = 0.0f;
     575             :                 }
     576             :             }
     577             :         }
     578             :         else
     579             :         {
     580       33502 :             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      186296 :             for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     587             :             {
     588     1220104 :                 for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     589             :                 {
     590     1067310 :                     mdctSpectrum[l] = 0;
     591     1067310 :                     if ( l < crossOverFreq )
     592             :                     {
     593     1030379 :                         last_block_nrg_correct += hTonalMDCTConc->lastBlockData.spectralData[l] * hTonalMDCTConc->lastBlockData.spectralData[l];
     594     1030379 :                         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       33502 :             if ( crossfadeGain == 1.0f )
     601             :             {
     602      947745 :                 for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     603             :                 {
     604      935267 :                     if ( concealment_noise[l] > 0 )
     605             :                     {
     606      464477 :                         mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     607             :                     }
     608             :                     else
     609             :                     {
     610      470790 :                         mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
     611             :                     }
     612             :                 }
     613       56300 :                 for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     614             :                 {
     615     1030241 :                     for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     616             :                     {
     617      986419 :                         if ( concealment_noise[l] > 0 )
     618             :                         {
     619      515989 :                             mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     620             :                         }
     621             :                         else
     622             :                         {
     623      470430 :                             mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
     624             :                         }
     625             :                     }
     626             :                 }
     627             : 
     628     2530567 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     629             :                 {
     630     2518089 :                     if ( concealment_noise[l] > 0 )
     631             :                     {
     632     1333085 :                         mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     633             :                     }
     634             :                     else
     635             :                     {
     636     1185004 :                         mdctSpectrum[l] = -hTonalMDCTConc->lastBlockData.spectralData[l];
     637             :                     }
     638             :                 }
     639             : 
     640     3215046 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     641             :                 {
     642     3202568 :                     mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     643             :                 }
     644             :             }
     645             :             /* actual fadeout is done in this case */
     646             :             else
     647             :             {
     648       21024 :                 g *= (float) sqrt( cngLevelBackgroundTrace_bfi / hTonalMDCTConc->curr_noise_nrg );
     649             : 
     650     2111761 :                 for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     651             :                 {
     652     2090737 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     653     2090737 :                     y = concealment_noise[l];
     654             : 
     655     2090737 :                     if ( y > 0 )
     656             :                     {
     657      384291 :                         mdctSpectrum[l] = g * y + crossfadeGain * x;
     658             :                     }
     659             :                     else
     660             :                     {
     661     1706446 :                         mdctSpectrum[l] = g * y - crossfadeGain * x;
     662             :                     }
     663     2090737 :                     hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
     664             :                 }
     665       96494 :                 for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     666             :                 {
     667     1842842 :                     for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     668             :                     {
     669     1767372 :                         x = hTonalMDCTConc->lastBlockData.spectralData[l];
     670     1767372 :                         y = concealment_noise[l];
     671             : 
     672     1767372 :                         if ( y > 0 )
     673             :                         {
     674      453475 :                             mdctSpectrum[l] = g * y + crossfadeGain * x;
     675             :                         }
     676             :                         else
     677             :                         {
     678     1313897 :                             mdctSpectrum[l] = g * y - crossfadeGain * x;
     679             :                         }
     680     1767372 :                         hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
     681             :                     }
     682             :                 }
     683             : 
     684     3568695 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     685             :                 {
     686     3547671 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     687     3547671 :                     y = concealment_noise[l];
     688             : 
     689     3547671 :                     if ( y > 0 )
     690             :                     {
     691      768764 :                         mdctSpectrum[l] = g * y + crossfadeGain * x;
     692             :                     }
     693             :                     else
     694             :                     {
     695     2778907 :                         mdctSpectrum[l] = g * y - crossfadeGain * x;
     696             :                     }
     697     3547671 :                     hTonalMDCTConc->faded_signal_nrg += mdctSpectrum[l] * mdctSpectrum[l];
     698             :                 }
     699             : 
     700     5274760 :                 for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     701             :                 {
     702     5253736 :                     mdctSpectrum[l] = 0.0f;
     703             :                 }
     704             :             }
     705             :         }
     706             : 
     707      419474 :         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       72433 :             nrg_corr_factor = sqrtf( ( hTonalMDCTConc->last_block_nrg - last_block_nrg_correct ) / hTonalMDCTConc->faded_signal_nrg );
     712       72433 :             v_multc( mdctSpectrum, nrg_corr_factor, mdctSpectrum, crossOverFreq );
     713             :         }
     714             :     }
     715             :     else
     716             :     {
     717     1168171 :         if ( !tonalConcealmentActive )
     718             :         {
     719   487668828 :             for ( i = 0; i < crossOverFreq; i++ )
     720             :             {
     721   486604346 :                 x = hTonalMDCTConc->lastBlockData.spectralData[i];
     722   486604346 :                 nrgNoiseInLastFrame += x * x;
     723   486604346 :                 rnd = own_random( &rnd );
     724   486604346 :                 mdctSpectrum[i] = tilt * rnd;
     725   486604346 :                 tilt *= tiltFactor;
     726   486604346 :                 nrgWhiteNoise += mdctSpectrum[i] * mdctSpectrum[i];
     727             :             }
     728     1064482 :             if ( nrgWhiteNoise > 0 )
     729             :             {
     730     1064482 :                 g *= (float) sqrt( nrgNoiseInLastFrame / nrgWhiteNoise );
     731             :             }
     732   487668828 :             for ( i = 0; i < crossOverFreq; i++ )
     733             :             {
     734   486604346 :                 x = hTonalMDCTConc->lastBlockData.spectralData[i];
     735   486604346 :                 y = mdctSpectrum[i];
     736             : 
     737   486604346 :                 if ( y > 0 )
     738             :                 {
     739   241720022 :                     mdctSpectrum[i] = g * y + crossfadeGain * x;
     740             :                 }
     741             :                 else
     742             :                 {
     743   244884324 :                     mdctSpectrum[i] = g * y - crossfadeGain * x;
     744             :                 }
     745             :             }
     746             : 
     747   207746856 :             for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     748             :             {
     749   206682374 :                 mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     750             :             }
     751             :         }
     752             :         else
     753             :         {
     754      103689 :             assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
     755     8730060 :             for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     756             :             {
     757     8626371 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     758     8626371 :                 rnd = own_random( &rnd );
     759     8626371 :                 mdctSpectrum[l] = tilt * rnd;
     760     8626371 :                 tilt *= tiltFactor;
     761     8626371 :                 nrgNoiseInLastFrame += x * x;
     762     8626371 :                 nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
     763             :             }
     764             : 
     765      465253 :             for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     766             :             {
     767      361564 :                 tilt *= (float) pow( tiltFactor, hTonalMDCTConc->pTCI->upperIndex[i - 1] - hTonalMDCTConc->pTCI->lowerIndex[i - 1] + 1 );
     768     7822086 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     769             :                 {
     770     7460522 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     771     7460522 :                     rnd = own_random( &rnd );
     772     7460522 :                     mdctSpectrum[l] = tilt * rnd;
     773     7460522 :                     tilt *= tiltFactor;
     774     7460522 :                     nrgNoiseInLastFrame += x * x;
     775     7460522 :                     nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
     776             :                 }
     777             :             }
     778      103689 :             tilt *= (float) pow( tiltFactor, hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] - hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1 );
     779             : 
     780    22751676 :             for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     781             :             {
     782    22647987 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     783    22647987 :                 rnd = own_random( &rnd );
     784    22647987 :                 mdctSpectrum[l] = tilt * rnd;
     785    22647987 :                 tilt *= tiltFactor;
     786    22647987 :                 nrgNoiseInLastFrame += x * x;
     787    22647987 :                 nrgWhiteNoise += mdctSpectrum[l] * mdctSpectrum[l];
     788             :             }
     789      103689 :             if ( nrgWhiteNoise > 0 )
     790             :             {
     791      103689 :                 g *= (float) sqrt( nrgNoiseInLastFrame / nrgWhiteNoise );
     792             :             }
     793     8730060 :             for ( l = 0; l < hTonalMDCTConc->pTCI->lowerIndex[0]; l++ )
     794             :             {
     795     8626371 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     796     8626371 :                 y = mdctSpectrum[l];
     797             : 
     798     8626371 :                 if ( y > 0 )
     799             :                 {
     800     4380692 :                     mdctSpectrum[l] = g * y + crossfadeGain * x;
     801             :                 }
     802             :                 else
     803             :                 {
     804     4245679 :                     mdctSpectrum[l] = g * y - crossfadeGain * x;
     805             :                 }
     806             :             }
     807      465253 :             for ( i = 1; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     808             :             {
     809     7822086 :                 for ( l = hTonalMDCTConc->pTCI->upperIndex[i - 1] + 1; l < hTonalMDCTConc->pTCI->lowerIndex[i]; l++ )
     810             :                 {
     811     7460522 :                     x = hTonalMDCTConc->lastBlockData.spectralData[l];
     812     7460522 :                     y = mdctSpectrum[l];
     813             : 
     814     7460522 :                     if ( y > 0 )
     815             :                     {
     816     3802549 :                         mdctSpectrum[l] = g * y + crossfadeGain * x;
     817             :                     }
     818             :                     else
     819             :                     {
     820     3657973 :                         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      568942 :             for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     829             :             {
     830     3665430 :                 for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     831             :                 {
     832     3200177 :                     mdctSpectrum[l] = 0;
     833             :                 }
     834             :             }
     835    22751676 :             for ( l = hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] + 1; l < crossOverFreq; l++ )
     836             :             {
     837    22647987 :                 x = hTonalMDCTConc->lastBlockData.spectralData[l];
     838    22647987 :                 y = mdctSpectrum[l];
     839             : 
     840    22647987 :                 if ( y > 0 )
     841             :                 {
     842    11157859 :                     mdctSpectrum[l] = g * y + crossfadeGain * x;
     843             :                 }
     844             :                 else
     845             :                 {
     846    11490128 :                     mdctSpectrum[l] = g * y - crossfadeGain * x;
     847             :                 }
     848             :             }
     849             : 
     850    23790705 :             for ( l = crossOverFreq; l < hTonalMDCTConc->lastBlockData.nSamples; l++ )
     851             :             {
     852    23687016 :                 mdctSpectrum[l] = hTonalMDCTConc->lastBlockData.spectralData[l];
     853             :             }
     854             :         }
     855             :     }
     856             : 
     857     1587645 :     *pSeed = rnd;
     858             : 
     859     1587645 :     pop_wmops();
     860             : 
     861     1587645 :     return;
     862             : }
     863             : 
     864             : 
     865      137191 : 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      137191 :     if ( hTonalMDCTConc->lastBlockData.blockIsValid & hTonalMDCTConc->secondLastBlockData.blockIsValid )
     878             :     {
     879      137191 :         assert( hTonalMDCTConc->pTCI->numIndexes > 0 );
     880             : 
     881      137191 :         nSamples = hTonalMDCTConc->nNonZeroSamples;
     882      137191 :         assert( hTonalMDCTConc->pTCI->upperIndex[hTonalMDCTConc->pTCI->numIndexes - 1] < nSamples );
     883      137191 :         mvr2r( hTonalMDCTConc->secondLastPowerSpectrum, powerSpectrum, nSamples ); /* Convert from 16 bits to 32 bits */
     884      137191 :         if ( psychParamsCurrent == NULL )
     885             :         {
     886       50484 :             nBands = FDNS_NPTS;
     887       50484 :             mdct_noiseShaping( powerSpectrum, hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors, nBands );
     888             :         }
     889             :         else
     890             :         {
     891       86707 :             sns_shape_spectrum( powerSpectrum, psychParamsCurrent, hTonalMDCTConc->secondLastBlockData.scaleFactors, hTonalMDCTConc->nSamplesCore );
     892       86707 :             nBands = psychParamsCurrent->nBands;
     893             :         }
     894             : 
     895      137191 :         v_multc( powerSpectrum + hTonalMDCTConc->nSamplesCore, hTonalMDCTConc->secondLastBlockData.scaleFactors[nBands - 1], powerSpectrum + hTonalMDCTConc->nSamplesCore, nSamples - hTonalMDCTConc->nSamplesCore );
     896             : 
     897      137191 :         phaseDiff = hTonalMDCTConc->pTCI->phaseDiff; /* if multiple frame loss occurs use the phase from the last frame and continue rotating */
     898      137191 :         pCurrentPhase = hTonalMDCTConc->pTCI->phase_currentFramePredicted;
     899             : 
     900      137191 :         if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
     901             :         {
     902       45677 :             if ( hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
     903             :             {
     904        3589 :                 hTonalMDCTConc->nFramesLost += 1;
     905             :             }
     906             :             else
     907             :             {
     908       42088 :                 hTonalMDCTConc->nFramesLost = 1.5;
     909             :             }
     910             :         }
     911             : 
     912             :         /* for each index group */
     913      755238 :         for ( i = 0; i < hTonalMDCTConc->pTCI->numIndexes; i++ )
     914             :         {
     915      618047 :             phaseToAdd = hTonalMDCTConc->nFramesLost * phaseDiff[i];
     916             : 
     917             :             /* Move phaseToAdd to range -EVS_PI..EVS_PI */
     918     8266772 :             while ( phaseToAdd > EVS_PI )
     919             :             {
     920     7648725 :                 phaseToAdd -= PI2;
     921             :             }
     922             : 
     923      618047 :             while ( phaseToAdd < -EVS_PI )
     924             :             {
     925             :                 /* should never occur in flt - kept for safety reasons */
     926           0 :                 phaseToAdd += PI2;
     927             :             }
     928             : 
     929     4885534 :             for ( l = hTonalMDCTConc->pTCI->lowerIndex[i]; l <= hTonalMDCTConc->pTCI->upperIndex[i]; l++ )
     930             :             {
     931     4267487 :                 const float currentPhase = ( *pCurrentPhase++ ) + phaseToAdd; /* *pCurrentPhase and phaseToAdd are in range -EVS_PI..EVS_PI */
     932     4267487 :                 mdctSpectrum[l] = (float) cos( currentPhase ) * powerSpectrum[l];
     933             :             }
     934             :         }
     935             :     }
     936             : 
     937      137191 :     hTonalMDCTConc->nFramesLost++;
     938             : 
     939      137191 :     return;
     940             : }
     941             : 
     942             : 
     943    29731485 : void TonalMDCTConceal_SaveTimeSignal(
     944             :     TonalMDCTConcealPtr hTonalMDCTConc,
     945             :     float *timeSignal,
     946             :     const int16_t nNewSamples )
     947             : {
     948    29731485 :     if ( nNewSamples == hTonalMDCTConc->nSamples )
     949             :     {
     950    29136943 :         assert( nNewSamples <= L_FRAME_MAX );
     951             : 
     952    29136943 :         if ( !hTonalMDCTConc->secondLastBlockData.tonalConcealmentActive )
     953             :         {
     954    29092022 :             mvr2r( hTonalMDCTConc->lastPcmOut + hTonalMDCTConc->nSamples / 2, hTonalMDCTConc->secondLastPcmOut, hTonalMDCTConc->nSamples / 2 );
     955             :         }
     956             : 
     957    29136943 :         mvr2r( timeSignal, hTonalMDCTConc->lastPcmOut, hTonalMDCTConc->nSamples );
     958             :     }
     959             : 
     960    29731485 :     return;
     961             : }
     962             : 
     963      419474 : 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      419474 :     push_wmops( "create_conc_noise" );
     987             : 
     988      419474 :     hStereoMdct = hCPE->hStereoMdct;
     989      419474 :     st = hCPE->hCoreCoder[idchan];
     990      419474 :     hTonalMDCTConc = st->hTonalMDCTConc;
     991      419474 :     hFdCngCom = st->hFdCngDec->hFdCngCom;
     992      419474 :     rnd = &hStereoMdct->noise_seeds_channels[idchan];
     993      419474 :     rnd_c = &hStereoMdct->noise_seed_common;
     994             : 
     995             :     /* determine start bin for IGF */
     996      419474 :     if ( st->igf == 0 )
     997             :     {
     998      168165 :         if ( st->narrowBand == 0 )
     999             :         {
    1000             :             /* minimum needed for output with sampling rates lower then the
    1001             :                nominal sampling rate */
    1002      168165 :             crossOverFreq = min( L_frameTCX, L_frame );
    1003             :         }
    1004             :         else
    1005             :         {
    1006           0 :             crossOverFreq = L_frameTCX;
    1007             :         }
    1008             :     }
    1009             :     else
    1010             :     {
    1011      251309 :         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      419474 :     max_noise_line = crossOverFreq;
    1016      419474 :     if ( st->tonal_mdct_plc_active )
    1017             :     {
    1018       33502 :         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      419474 :     if ( !hTonalMDCTConc->lastBlockData.blockIsConcealed )
    1023             :     {
    1024      165093 :         *rnd = 1977 + idchan;
    1025             :         /* will be set twice when looping over two channels, but does not matter */
    1026      165093 :         *rnd_c = 1979;
    1027             :     }
    1028             : 
    1029      419474 :     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    64634500 :         for ( i = 0; i < max_noise_line; i++ )
    1033             :         {
    1034    64469407 :             *rnd = own_random( rnd );
    1035    64469407 :             concealment_noise[i] = *rnd;
    1036             :         }
    1037             : 
    1038      165093 :         pop_wmops();
    1039             : 
    1040      165093 :         return;
    1041             :     }
    1042             : 
    1043      254381 :     save_rnd_c = *rnd_c;
    1044             : 
    1045      254381 :     c = sqrtf( hStereoMdct->lastCoh );
    1046      254381 :     c_inv = sqrtf( 1 - hStereoMdct->lastCoh );
    1047             : 
    1048             :     /* pre-compute the noise shape for later weighting of the noise spectra */
    1049      254381 :     cngNoiseLevelPtr = &hFdCngCom->cngNoiseLevel[0];
    1050      254381 :     inc = ( st->core > TCX_20_CORE ) ? 2 : 1;
    1051      254381 :     start_idx = hFdCngCom->startBand / inc;
    1052      254381 :     stop_idx = hFdCngCom->stopFFTbin / inc;
    1053             : 
    1054      756363 :     for ( i = 0; i < start_idx; i++ )
    1055             :     {
    1056      501982 :         noise_shape_buffer[i] = 0.0f;
    1057             :     }
    1058    80069519 :     for ( ; i < stop_idx; i++, cngNoiseLevelPtr += inc )
    1059             :     {
    1060    79815138 :         noise_shape_buffer[i] = sqrtf( *( cngNoiseLevelPtr ) );
    1061             :     }
    1062             : 
    1063      254381 :     last_scf = sqrtf( *( cngNoiseLevelPtr - inc ) );
    1064             : 
    1065    19235011 :     for ( ; i < max_noise_line; i++ )
    1066             :     {
    1067    18980630 :         noise_shape_buffer[i] = last_scf;
    1068             :     }
    1069             : 
    1070             :     /* fill the noise vector */
    1071      254381 :     hTonalMDCTConc->curr_noise_nrg = MDCT_ST_PLC_FADEOUT_MIN_NOISE_NRG;
    1072      254381 :     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    99346986 :         for ( i = 0; i < max_noise_line; i++ )
    1076             :         {
    1077    99093190 :             *rnd = own_random( rnd );
    1078    99093190 :             *rnd_c = own_random( rnd_c );
    1079             : 
    1080    99093190 :             concealment_noise[i] = ( c_inv * *rnd + c * *rnd_c ) * noise_shape_buffer[i];
    1081    99093190 :             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      205145 :         for ( i = 0; i < max_noise_line; i++ )
    1088             :         {
    1089      204560 :             *rnd = own_random( rnd );
    1090      204560 :             *rnd_c = own_random( rnd_c );
    1091             : 
    1092      204560 :             concealment_noise[i] = ( c_inv * *rnd + c * *rnd_c ) * noise_shape_buffer[i];
    1093      204560 :             hTonalMDCTConc->curr_noise_nrg += concealment_noise[i] * concealment_noise[i];
    1094             : 
    1095      204560 :             *rnd_c = own_random( rnd_c );
    1096             :         }
    1097             :     }
    1098             : 
    1099      254381 :     if ( st->tonal_mdct_plc_active )
    1100             :     {
    1101      282235 :         for ( i = crossOverFreq; i < max( crossOverFreq, hTonalMDCTConc->pTCI->lowerIndex[hTonalMDCTConc->pTCI->numIndexes - 1] ); ++i )
    1102             :         {
    1103      261211 :             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      254381 :     if ( ( idchan == 0 && ( core == TCX_20 || ( core == TCX_10 && subframe_idx == 1 ) ) ) || ( core == TCX_10 && subframe_idx == 0 ) )
    1111             :     {
    1112      126652 :         *rnd_c = save_rnd_c;
    1113             :     }
    1114             : 
    1115      254381 :     st->seed_tcx_plc = *rnd;
    1116             : 
    1117      254381 :     pop_wmops();
    1118             : 
    1119      254381 :     return;
    1120             : }
    1121             : 
    1122      221073 : 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      221073 :     push_wmops( "apply_sns_on_noise_shape" );
    1135             : 
    1136      221073 :     scfs_bg = &st->hTonalMDCTConc->scaleFactorsBackground[0];
    1137      221073 :     psychParams = st->hTonalMDCTConc->psychParams;
    1138      221073 :     hFdCngCom = st->hFdCngDec->hFdCngCom;
    1139             : 
    1140      221073 :     inc = ( ( whitening_mode == ON_FIRST_LOST_FRAME ? st->core : st->last_core ) > TCX_20_CORE ) ? 2 : 1;
    1141      221073 :     start_idx = hFdCngCom->startBand / inc;
    1142      221073 :     stop_idx = L_frame / inc;
    1143      221073 :     noiseLevelPtr = hFdCngCom->cngNoiseLevel;
    1144             : 
    1145      221073 :     set_zero( whitenend_noise_shape, start_idx );
    1146    69745572 :     for ( int16_t j = start_idx; j < stop_idx; j++, noiseLevelPtr += inc )
    1147             :     {
    1148    69524499 :         whitenend_noise_shape[j] = *noiseLevelPtr;
    1149             :     }
    1150             : 
    1151      221073 :     if ( whitening_mode == ON_FIRST_LOST_FRAME )
    1152             :     {
    1153             :         float scf[SNS_NPTS];
    1154             : 
    1155       61232 :         sns_compute_scf( whitenend_noise_shape, psychParams, L_frame, scf );
    1156       61232 :         sns_interpolate_scalefactors( scfs_int, scf, ENC );
    1157       61232 :         sns_interpolate_scalefactors( scfs_bg, scf, DEC );
    1158       61232 :         scfs_for_shaping = &scfs_int[0];
    1159             :     }
    1160             :     else /* whitening_mode == ON_FIRST_GOOD_FRAME */
    1161             :     {
    1162      159841 :         scfs_for_shaping = &scfs_bg[0];
    1163             :     }
    1164             : 
    1165      221073 :     if ( sum_f( scfs_for_shaping, FDNS_NPTS ) > 0.0f )
    1166             :     {
    1167      121954 :         sns_shape_spectrum( whitenend_noise_shape, psychParams, scfs_for_shaping, L_frame );
    1168      121954 :         mvr2r( whitenend_noise_shape + start_idx, hFdCngCom->cngNoiseLevel, stop_idx - start_idx );
    1169             :     }
    1170             :     else
    1171             :     {
    1172       99119 :         set_zero( hFdCngCom->cngNoiseLevel, stop_idx - start_idx );
    1173             :     }
    1174             : 
    1175      221073 :     pop_wmops();
    1176      221073 : }

Generated by: LCOV version 1.14