LCOV - code coverage report
Current view: top level - lib_enc - fd_cng_enc.c (source / functions) Hit Total Coverage
Test: Coverage on main -- conformance test test_26252.py @ a21f94bc6bac334fe001a5bad2f7b32b79038097 Lines: 465 527 88.2 %
Date: 2025-11-01 05:07:43 Functions: 13 13 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             : #include "cnst.h"
      38             : #include "ivas_cnst.h"
      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 "rom_enc.h"
      47             : #include "rom_com.h"
      48             : #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
      49             : #include "ivas_rom_com.h"
      50             : #endif
      51             : #include "prot.h"
      52             : #include "ivas_prot.h"
      53             : #include "stat_enc.h"
      54             : #include "wmc_auto.h"
      55             : 
      56             : /*-------------------------------------------------------------------*
      57             :  * createFdCngEnc()
      58             :  *
      59             :  *
      60             :  *-------------------------------------------------------------------*/
      61             : 
      62         364 : ivas_error createFdCngEnc(
      63             :     HANDLE_FD_CNG_ENC *hFdCngEnc /* i/o: FD_CNG structure        */
      64             : )
      65             : {
      66             :     HANDLE_FD_CNG_ENC hs;
      67             :     ivas_error error;
      68         364 :     error = IVAS_ERR_OK;
      69             : 
      70             :     /* Set output to NULL in case of errors and early return */
      71         364 :     *hFdCngEnc = NULL;
      72             : 
      73             :     /* Allocate memory */
      74         364 :     if ( ( hs = (HANDLE_FD_CNG_ENC) malloc( sizeof( FD_CNG_ENC ) ) ) == NULL )
      75             :     {
      76           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for FD CNG ENC structure" );
      77             :     }
      78             : 
      79         364 :     if ( ( error = createFdCngCom( &( hs->hFdCngCom ) ) ) != IVAS_ERR_OK )
      80             :     {
      81           0 :         return error;
      82             :     }
      83             : 
      84         364 :     *hFdCngEnc = hs;
      85             : 
      86         364 :     return error;
      87             : }
      88             : 
      89             : /*-------------------------------------------------------------------*
      90             :  * initFdCngEnc()
      91             :  *
      92             :  * Initialize FD_CNG
      93             :  *-------------------------------------------------------------------*/
      94             : 
      95         364 : void initFdCngEnc(
      96             :     HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: Contains the variables related to the FD-based CNG process */
      97             :     const int32_t input_Fs,      /* i  : input signal sampling frequency in Hz   */
      98             :     const float scale            /* i  : scaling factor                          */
      99             : )
     100             : {
     101             :     int16_t j;
     102         364 :     HANDLE_FD_CNG_COM hsCom = hFdCngEnc->hFdCngCom;
     103             : 
     104             :     /* Initialize common */
     105         364 :     initFdCngCom( hsCom, scale );
     106             : 
     107             :     /* Configure the Noise Estimator */
     108         364 :     hsCom->numSlots = 16;
     109         364 :     hsCom->numCoreBands = 16;
     110         364 :     hsCom->regularStopBand = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH );
     111         364 :     if ( hsCom->regularStopBand > 40 )
     112             :     {
     113         288 :         hsCom->regularStopBand = 40;
     114             :     }
     115             : 
     116         364 :     hsCom->startBand = 2;
     117         364 :     if ( hsCom->regularStopBand == 10 )
     118             :     {
     119           0 :         hsCom->stopFFTbin = 160;
     120           0 :         hsCom->stopBand = 160;
     121           0 :         hsCom->nFFTpart = 17;
     122             :     }
     123             :     else
     124             :     {
     125         364 :         hsCom->stopFFTbin = 256;
     126         364 :         hsCom->stopBand = hsCom->regularStopBand - hsCom->numCoreBands + hsCom->stopFFTbin;
     127         364 :         hsCom->nFFTpart = 20;
     128             :     }
     129             : 
     130         364 :     initPartitions( sidparts_encoder_noise_est, SIZE_SIDPARTS_ENC_NOISE_EST, hsCom->startBand, hsCom->stopBand, hsCom->part, &hsCom->npart, hsCom->midband, hsCom->psize, hsCom->psize_inv, 0 );
     131             : 
     132         364 :     hsCom->nCLDFBpart = hsCom->npart - hsCom->nFFTpart;
     133        1790 :     for ( j = 0; j < hsCom->nCLDFBpart; j++ )
     134             :     {
     135        1426 :         hsCom->CLDFBpart[j] = hsCom->part[j + hsCom->nFFTpart] - ( 256 - hsCom->startBand );
     136        1426 :         hsCom->CLDFBpsize_inv[j] = hsCom->psize_inv[j + hsCom->nFFTpart];
     137             :     }
     138             : 
     139             :     /* Initialize the Noise Estimator */
     140         364 :     set_f( hFdCngEnc->msPeriodog, 0.0f, NPART );
     141         364 :     set_f( hFdCngEnc->msAlpha, 0.0f, NPART );
     142         364 :     set_f( hFdCngEnc->msBminWin, 0.0f, NPART );
     143         364 :     set_f( hFdCngEnc->msBminSubWin, 0.0f, NPART );
     144         364 :     set_f( hFdCngEnc->msPsd, 0.0f, NPART );
     145         364 :     set_f( hFdCngEnc->msNoiseFloor, 0.0f, NPART );
     146         364 :     set_f( hFdCngEnc->msNoiseEst, 0.0f, NPART );
     147         364 :     set_f( hFdCngEnc->energy_ho, 0.0f, NPART );
     148         364 :     set_f( hFdCngEnc->msNoiseEst_old, 0.0f, NPART );
     149         364 :     set_f( hFdCngEnc->msMinBuf, FLT_MAX, MSNUMSUBFR * NPART );
     150         364 :     set_f( hFdCngEnc->msCurrentMin, FLT_MAX, NPART );
     151         364 :     set_f( hFdCngEnc->msCurrentMinOut, FLT_MAX, NPART );
     152         364 :     set_f( hFdCngEnc->msCurrentMinSubWindow, FLT_MAX, NPART );
     153         364 :     set_s( hFdCngEnc->msLocalMinFlag, 0, NPART );
     154         364 :     set_s( hFdCngEnc->msNewMinFlag, 0, NPART );
     155         364 :     set_f( hFdCngEnc->msPsdFirstMoment, 0.0f, NPART );
     156         364 :     set_f( hFdCngEnc->msPsdSecondMoment, 0.0f, NPART );
     157         364 :     hFdCngEnc->msPeriodogBufPtr = 0;
     158         364 :     set_f( hFdCngEnc->msPeriodogBuf, 0.0f, MSBUFLEN * NPART );
     159         364 :     set_f( hFdCngEnc->msLogPeriodog, 0.0f, NPART );
     160         364 :     set_f( hFdCngEnc->msLogNoiseEst, 0.0f, NPART );
     161             : 
     162             : #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
     163        2184 :     for ( int16_t i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ )
     164             :     {
     165        1820 :         set_f( hFdCngEnc->mem_coherence[i], EPSILON, 4 );
     166             :     }
     167             : #else
     168             :     set_f( hFdCngEnc->mem_coherence, EPSILON, 4 );
     169             : #endif
     170             : 
     171         364 :     return;
     172             : }
     173             : 
     174             : /*-------------------------------------------------------------------*
     175             :  * configureFdCngEnc()
     176             :  *
     177             :  * Configure FD_CNG
     178             :  *-------------------------------------------------------------------*/
     179             : 
     180       24586 : void configureFdCngEnc(
     181             :     HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: Contains the variables related to the FD-based CNG process */
     182             :     const int16_t bwidth,
     183             :     const int32_t total_brate )
     184             : {
     185       24586 :     HANDLE_FD_CNG_COM hsCom = hFdCngEnc->hFdCngCom;
     186             :     float psizeDec[NPART];
     187             :     float psize_invDec[NPART];
     188             : 
     189       24586 :     hsCom->CngBandwidth = bwidth;
     190       24586 :     if ( hsCom->CngBandwidth == FB )
     191             :     {
     192       17763 :         hsCom->CngBandwidth = SWB;
     193             :     }
     194       24586 :     hsCom->CngBitrate = total_brate;
     195             : 
     196             :     /* NB configuration */
     197       24586 :     if ( bwidth == NB )
     198             :     {
     199           0 :         hsCom->FdCngSetup = FdCngSetup_nb;
     200             :     }
     201             : 
     202             :     /* WB configuration */
     203       24586 :     else if ( bwidth == WB )
     204             :     {
     205             :         /* FFT 6.4kHz, no CLDFB */
     206        1544 :         if ( total_brate <= ACELP_8k00 )
     207             :         {
     208           0 :             hsCom->FdCngSetup = FdCngSetup_wb1;
     209             :         }
     210             :         /* FFT 6.4kHz, CLDFB 8.0kHz */
     211        1544 :         else if ( total_brate <= ACELP_13k20 )
     212             :         {
     213         721 :             hsCom->FdCngSetup = FdCngSetup_wb2;
     214             :         }
     215             :         /* FFT 8.0kHz, no CLDFB */
     216             :         else
     217             :         {
     218         823 :             hsCom->FdCngSetup = FdCngSetup_wb3;
     219             :         }
     220             :     }
     221             : 
     222             :     /* SWB/FB configuration */
     223             :     else
     224             :     {
     225             :         /* FFT 6.4kHz, CLDFB 14kHz */
     226       23042 :         if ( total_brate <= ACELP_13k20 )
     227             :         {
     228       13388 :             hsCom->FdCngSetup = FdCngSetup_swb1;
     229             :         }
     230             :         /* FFT 8.0kHz, CLDFB 16kHz */
     231             :         else
     232             :         {
     233        9654 :             hsCom->FdCngSetup = FdCngSetup_swb2;
     234             :         }
     235             :     }
     236       24586 :     hsCom->fftlen = hsCom->FdCngSetup.fftlen;
     237       24586 :     hFdCngEnc->stopFFTbinDec = hsCom->FdCngSetup.stopFFTbin;
     238             : 
     239             :     /* Configure the SID quantizer and the Confort Noise Generator */
     240             : 
     241       24586 :     hFdCngEnc->startBandDec = hsCom->startBand;
     242       24586 :     hFdCngEnc->stopBandDec = hsCom->FdCngSetup.sidPartitions[hsCom->FdCngSetup.numPartitions - 1] + 1;
     243       24586 :     initPartitions( hsCom->FdCngSetup.sidPartitions, hsCom->FdCngSetup.numPartitions, hFdCngEnc->startBandDec, hFdCngEnc->stopBandDec, hFdCngEnc->partDec, &hFdCngEnc->npartDec, hFdCngEnc->midbandDec, psizeDec, psize_invDec, 0 );
     244             : 
     245       24586 :     if ( hFdCngEnc->stopFFTbinDec == 160 )
     246             :     {
     247           0 :         hFdCngEnc->nFFTpartDec = 17;
     248             :     }
     249       24586 :     else if ( hFdCngEnc->stopFFTbinDec == 256 )
     250             :     {
     251       14109 :         hFdCngEnc->nFFTpartDec = 20;
     252             :     }
     253             :     else
     254             :     {
     255       10477 :         hFdCngEnc->nFFTpartDec = 21;
     256             :     }
     257             : 
     258       24586 :     switch ( hsCom->fftlen )
     259             :     {
     260       14109 :         case 512:
     261       14109 :             hsCom->fftSineTab = NULL;
     262       14109 :             hsCom->olapWinAna = olapWinAna512;
     263       14109 :             hsCom->olapWinSyn = olapWinSyn256;
     264       14109 :             break;
     265       10477 :         case 640:
     266       10477 :             hsCom->fftSineTab = fftSineTab640;
     267       10477 :             hsCom->olapWinAna = olapWinAna640;
     268       10477 :             hsCom->olapWinSyn = olapWinSyn320;
     269       10477 :             break;
     270           0 :         default:
     271           0 :             assert( !"Unsupported FFT length for FD-based CNG" );
     272             :             break;
     273             :     }
     274       24586 :     hsCom->frameSize = hsCom->fftlen >> 1;
     275             : 
     276       24586 :     return;
     277             : }
     278             : 
     279             : 
     280             : /*-------------------------------------------------------------------*
     281             :  * deleteFdCngEnc()
     282             :  *
     283             :  * Delete the instance of type FD_CNG
     284             :  *-------------------------------------------------------------------*/
     285             : 
     286        5919 : void deleteFdCngEnc(
     287             :     HANDLE_FD_CNG_ENC *hFdCngEnc /* i/o: FD_CNG structure        */
     288             : )
     289             : {
     290             : 
     291        5919 :     HANDLE_FD_CNG_ENC hsEnc = *hFdCngEnc;
     292             : 
     293        5919 :     if ( hsEnc != NULL )
     294             :     {
     295         364 :         deleteFdCngCom( &( hsEnc->hFdCngCom ) );
     296         364 :         free( hsEnc );
     297         364 :         *hFdCngEnc = NULL;
     298             :     }
     299             : 
     300        5919 :     return;
     301             : }
     302             : 
     303             : /*-------------------------------------------------------------------*
     304             :  * resetFdCngEnc()
     305             :  *
     306             :  * Reset the instance of type FD_CNG
     307             :  *-------------------------------------------------------------------*/
     308             : 
     309       96596 : void resetFdCngEnc(
     310             :     Encoder_State *st /* i/o: encoder state structure     */
     311             : )
     312             : {
     313             :     int16_t n;
     314             :     float totalNoiseIncrease;
     315             : 
     316             :     /* Detect fast increase of totalNoise */
     317       96596 :     totalNoiseIncrease = st->hNoiseEst->totalNoise - st->last_totalNoise;
     318       96596 :     st->last_totalNoise = st->hNoiseEst->totalNoise;
     319       96596 :     if ( totalNoiseIncrease > 0 )
     320             :     {
     321        9496 :         if ( st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE )
     322             :         {
     323        4336 :             for ( n = 0; n < TOTALNOISE_HIST_SIZE - 1; n++ )
     324             :             {
     325        3252 :                 st->totalNoise_increase_hist[n] = st->totalNoise_increase_hist[n + 1];
     326             :             }
     327        1084 :             st->totalNoise_increase_hist[TOTALNOISE_HIST_SIZE - 1] = totalNoiseIncrease;
     328             :         }
     329             :         else
     330             :         {
     331        8412 :             st->totalNoise_increase_hist[st->totalNoise_increase_len] = totalNoiseIncrease;
     332        8412 :             st->totalNoise_increase_len++;
     333             :         }
     334             :     }
     335             :     else
     336             :     {
     337       87100 :         st->totalNoise_increase_len = 0;
     338             :     }
     339             : 
     340       96596 :     totalNoiseIncrease = 0.f;
     341      113750 :     for ( n = 0; n < st->totalNoise_increase_len; n++ )
     342             :     {
     343       17154 :         totalNoiseIncrease += st->totalNoise_increase_hist[n];
     344             :     }
     345             : 
     346       96596 :     if (
     347         610 :         ( totalNoiseIncrease > 5 && st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE && st->ini_frame > 150 ) ||
     348       96587 :         ( st->input_bwidth > st->last_input_bwidth ) ||
     349       96294 :         ( st->last_core == AMR_WB_CORE ) )
     350             :     {
     351         302 :         st->fd_cng_reset_flag = 1;
     352         302 :         st->hFdCngEnc->hFdCngCom->msFrCnt_init_counter = 0;
     353         302 :         st->hFdCngEnc->hFdCngCom->init_old = FLT_MAX;
     354             :     }
     355       96294 :     else if ( st->fd_cng_reset_flag > 0 && st->fd_cng_reset_flag < 10 )
     356             :     {
     357        2700 :         st->fd_cng_reset_flag++;
     358             :     }
     359             :     else
     360             :     {
     361       93594 :         st->fd_cng_reset_flag = 0;
     362             :     }
     363             : 
     364       96596 :     return;
     365             : }
     366             : 
     367             : 
     368             : /*-------------------------------------------------------------------*
     369             :  * perform_noise_estimation_enc()
     370             :  *
     371             :  * Perform noise estimation
     372             :  *-------------------------------------------------------------------*/
     373             : 
     374       79998 : void perform_noise_estimation_enc(
     375             :     float *band_energies,        /* i  : energy in critical bands without minimum noise floor E_MIN*/
     376             :     float *enerBuffer,           /* i  : energy buffer                                             */
     377             :     HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG structure containing all buffers and variables        */
     378             :     const int32_t input_Fs,      /* i  : input sampling rate                                       */
     379             :     CPE_ENC_HANDLE hCPE          /* i  : CPE encoder structure                                     */
     380             : )
     381             : {
     382             :     int16_t i, j;
     383       79998 :     int16_t numCoreBands = hFdCngEnc->hFdCngCom->numCoreBands;
     384       79998 :     int16_t regularStopBand = hFdCngEnc->hFdCngCom->regularStopBand;
     385       79998 :     int16_t numSlots = hFdCngEnc->hFdCngCom->numSlots;
     386       79998 :     float numSlots_inv = 1.f / (float) numSlots; /*enough if done only once*/
     387       79998 :     float *periodog = hFdCngEnc->hFdCngCom->periodog;
     388       79998 :     float *ptr_per = periodog;
     389       79998 :     int16_t npart = hFdCngEnc->hFdCngCom->npart;
     390       79998 :     int16_t nFFTpart = hFdCngEnc->hFdCngCom->nFFTpart;
     391       79998 :     float *psize = hFdCngEnc->hFdCngCom->psize;
     392       79998 :     float *msPeriodog = hFdCngEnc->msPeriodog;
     393       79998 :     float *msNoiseEst = hFdCngEnc->msNoiseEst;
     394             : 
     395       79998 :     float *msLogPeriodog = hFdCngEnc->msLogPeriodog;
     396       79998 :     float *msLogNoiseEst = hFdCngEnc->msLogNoiseEst;
     397             : 
     398             :     float band_res_dft, chan_width_f;
     399             :     float chan_width_bins;
     400             :     float scaleEB;
     401             : 
     402       79998 :     if ( hCPE != NULL && hCPE->hStereoDft != NULL )
     403             :     {
     404       15762 :         band_res_dft = ( (float) input_Fs ) / hCPE->hStereoDft->NFFT;
     405       15762 :         chan_width_f = 24000.f / CLDFB_NO_CHANNELS_MAX;
     406       15762 :         chan_width_bins = chan_width_f / band_res_dft;
     407             : 
     408             :         /* Scaling of Energy buffer to get energy per sample, same scaling as for band_energies, 3 is to compensate for the 1/3 scaling in calculate_energy_buffer */
     409       15762 :         scaleEB = 3 * 4.0f / ( hCPE->hStereoDft->NFFT * hCPE->hStereoDft->NFFT );
     410             : 
     411             :         /* Scale with number of bins in one band */
     412       15762 :         scaleEB = scaleEB / chan_width_bins;
     413             :     }
     414             :     else
     415             :     {
     416       64236 :         scaleEB = numSlots_inv * hFdCngEnc->hFdCngCom->scalingFactor;
     417             :     }
     418             : 
     419             :     /* preemphasis compensation and grouping of per bin energies into msPeriodog */
     420     1679958 :     for ( i = 0; i < nFFTpart; i++ )
     421             :     {
     422     1599960 :         msPeriodog[i] = 0.5f * ( band_energies[i] + band_energies[i + NB_BANDS] );
     423     1599960 :         msPeriodog[i] *= preemphCompensation[i];
     424             :     }
     425             : 
     426             :     /* Adjust to the desired time resolution by averaging the periodograms over the time slots */
     427     1847950 :     for ( j = numCoreBands; j < regularStopBand; j++ )
     428             :     {
     429     1767952 :         ( *ptr_per ) = enerBuffer[j] * scaleEB;
     430     1767952 :         ptr_per++;
     431             :     }
     432             : 
     433             :     /* Adjust filterbank to the desired frequency resolution by averaging over spectral partitions for SID transmission */
     434       79998 :     if ( numCoreBands < regularStopBand )
     435             :     {
     436       79998 :         bandcombinepow( periodog, regularStopBand - numCoreBands, hFdCngEnc->hFdCngCom->CLDFBpart, hFdCngEnc->hFdCngCom->nCLDFBpart, hFdCngEnc->hFdCngCom->CLDFBpsize_inv, &msPeriodog[nFFTpart] );
     437             :     }
     438             : 
     439             :     /* Compress MS inputs */
     440       79998 :     compress_range( msPeriodog, msLogPeriodog, npart );
     441             : 
     442             :     /* Call the minimum statistics routine for noise estimation */
     443      117222 :     minimum_statistics( npart, nFFTpart, psize, msLogPeriodog, hFdCngEnc->msNoiseFloor, msLogNoiseEst, hFdCngEnc->msAlpha, hFdCngEnc->msPsd, hFdCngEnc->msPsdFirstMoment, hFdCngEnc->msPsdSecondMoment, hFdCngEnc->msMinBuf, hFdCngEnc->msBminWin, hFdCngEnc->msBminSubWin, hFdCngEnc->msCurrentMin, hFdCngEnc->msCurrentMinOut, hFdCngEnc->msCurrentMinSubWindow, hFdCngEnc->msLocalMinFlag, hFdCngEnc->msNewMinFlag, hFdCngEnc->msPeriodogBuf, &( hFdCngEnc->msPeriodogBufPtr ), hFdCngEnc->hFdCngCom,
     444       37224 :                         ENC, ( hCPE == NULL ) ? 0 : hCPE->element_mode );
     445             : 
     446             :     /* Expand MS outputs */
     447       79998 :     expand_range( msLogNoiseEst, msNoiseEst, npart );
     448             : 
     449       79998 :     return;
     450             : }
     451             : 
     452             : 
     453             : /*-------------------------------------------------------------------*
     454             :  * AdjustFirstSID()
     455             :  *
     456             :  * Adjust the noise estimator at the beginning of each CNG phase (encoder-side)
     457             :  *-------------------------------------------------------------------*/
     458             : 
     459       76928 : void AdjustFirstSID(
     460             :     Encoder_State *st /* i/o: encoder state structure     */
     461             : )
     462             : {
     463             :     float lambda;
     464             :     int16_t i;
     465       76928 :     int16_t npart = st->hFdCngEnc->hFdCngCom->npart;
     466       76928 :     float *msPeriodog = st->hFdCngEnc->msPeriodog;
     467       76928 :     float *energy_ho = st->hFdCngEnc->energy_ho;
     468       76928 :     float *msNoiseEst = st->hFdCngEnc->msNoiseEst;
     469       76928 :     float *msNoiseEst_old = st->hFdCngEnc->msNoiseEst_old;
     470       76928 :     int16_t *active_frame_counter = &( st->hFdCngEnc->hFdCngCom->active_frame_counter );
     471             : 
     472       76928 :     if ( st->hDtxEnc->cnt_SID == 1 && st->last_core_brate > SID_2k40 )
     473             :     {
     474             :         /* Detect the hangover period and the first SID frame at the beginning of each CNG phase */
     475             : 
     476             :         /* Average input energy over hangover period */
     477        1675 :         mvr2r( msPeriodog, energy_ho, npart ); /*First hangover frame*/
     478             :         /* Set first SID to current input level but add some smoothing */
     479        1675 :         lambda = (float) pow( 0.96f, (float) ( *active_frame_counter + 1 ) );
     480        1675 :         v_multc( msNoiseEst_old, lambda, msNoiseEst_old, npart );
     481        1675 :         v_multc( energy_ho, 1 - lambda, energy_ho, npart );
     482             : 
     483        1675 :         v_add( msNoiseEst_old, energy_ho, energy_ho, npart );
     484       41623 :         for ( i = 0; i < npart; i++ )
     485             :         {
     486       39948 :             if ( msNoiseEst[i] > energy_ho[i] )
     487             :             {
     488       24208 :                 msNoiseEst[i] = energy_ho[i];
     489             :             }
     490             :         }
     491        1675 :         *active_frame_counter = 0;
     492             :     }
     493             : 
     494       76928 :     if ( st->core_brate != SID_2k40 && st->core_brate != FRAME_NO_DATA )
     495             :     {
     496       57777 :         ( *active_frame_counter )++; /* Count the number of active frames in a row */
     497             :     }
     498             :     else
     499             :     {
     500       19151 :         mvr2r( msNoiseEst, msNoiseEst_old, npart ); /* Store the noise estimate obtained in the CNG phases */
     501             :     }
     502             : 
     503       76928 :     return;
     504             : }
     505             : 
     506             : /*-------------------------------------------------------------------*
     507             :  * FdCng_encodeSID()
     508             :  *
     509             :  * Generate a bitstream out of the partition levels
     510             :  *-------------------------------------------------------------------*/
     511             : 
     512        1189 : void FdCng_encodeSID(
     513             :     Encoder_State *st /* i/o: encoder state structure     */
     514             : )
     515             : {
     516             :     int16_t N;
     517        1189 :     HANDLE_FD_CNG_ENC hFdCngEnc = st->hFdCngEnc;
     518        1189 :     HANDLE_FD_CNG_COM hFdCngCom = hFdCngEnc->hFdCngCom;
     519        1189 :     BSTR_ENC_HANDLE hBstr = st->hBstr;
     520        1189 :     float *E = hFdCngEnc->msNoiseEst;
     521             :     float gain;
     522             :     int16_t i, index;
     523             :     float v[32], e;
     524             :     int16_t indices[32];
     525             :     float w[32];
     526        1189 :     float preemph_fac = st->preemph_fac;
     527             : 
     528             :     float *invTrfMatrix;
     529             :     float tmpRAM[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC];
     530             :     float dct_target[FDCNG_VQ_DCT_MAXTRUNC];
     531             :     float tot_sig_ext[FDCNG_VQ_MAX_LEN];
     532        1189 :     const float gain_q_offset = ( st->element_mode == EVS_MONO ) ? GAIN_Q_OFFSET_EVS : GAIN_Q_OFFSET_IVAS;
     533             : 
     534             :     /* Init */
     535        1189 :     N = hFdCngEnc->npartDec;
     536             : 
     537        1189 :     invTrfMatrix = (float *) tmpRAM; /* dynamically filled  */
     538        1189 :     set_zero( v, FDCNG_VQ_MAX_LEN );
     539             : 
     540             :     /* Convert to LOG */
     541        1189 :     e = 0.f;
     542       28774 :     for ( i = 0; i < N; i++ )
     543             :     {
     544       27585 :         v[i] = 10.f * (float) log10( E[i] + 1e-4f );
     545       27585 :         e += v[i];
     546             :     }
     547             : 
     548             :     /* Normalize MSVQ input */
     549        1189 :     gain = 0.f;
     550       16646 :     for ( i = N_GAIN_MIN; i < N_GAIN_MAX; i++ )
     551             :     {
     552       15457 :         gain += v[i];
     553             :     }
     554             : 
     555        1189 :     gain /= (float) ( N_GAIN_MAX - N_GAIN_MIN );
     556             : 
     557       28774 :     for ( i = 0; i < N; i++ )
     558             :     {
     559       27585 :         v[i] -= gain;
     560             :     }
     561             : 
     562             :     /* MSVQ encoder */
     563        1189 :     set_f( w, 1.0f, N );
     564             : 
     565        1189 :     if ( st->element_mode != EVS_MONO )
     566             :     {
     567             :         /* DCT domain compressed/truncated indices used for first stage  */
     568             :         /*  quantization with stage1 stored in DCT24 domain,   stages 2 through 6 directly dearched
     569             :            in FDCNG band domain
     570             :         */
     571        1189 :         if ( N == FDCNG_VQ_MAX_LEN_WB )
     572             :         {
     573         317 :             create_IDCT_N_Matrix( invTrfMatrix, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) );
     574             :             /* truncated DCT21 analysis */
     575         317 :             dctT2_N_apply_matrix( (const float *) v, dct_target, FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX );
     576             :             /* truncated IDCT21 extension to 24 bands  */
     577         317 :             extend_dctN_input( v, dct_target, N, tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 );
     578             : 
     579         317 :             mvr2r( tot_sig_ext, v, FDCNG_VQ_MAX_LEN ); /*  write  extended result as input to  VQ stage #1 */
     580             :         }
     581        1189 :         create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) );
     582        1189 :         msvq_enc( cdk_37bits_ivas, NULL, NULL, v, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, w, N, FD_CNG_maxN_37bits, 1, invTrfMatrix, indices );
     583        1189 :         msvq_dec( cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N, FD_CNG_maxN_37bits, indices, 1, invTrfMatrix, v, NULL );
     584             :     }
     585             :     else
     586             :     { /* EVS_MONO tables */
     587           0 :         msvq_enc( cdk_37bits, NULL, NULL, v, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, w, N, FD_CNG_maxN_37bits, 0, NULL, indices );
     588           0 :         msvq_dec( cdk_37bits, NULL, NULL, FD_CNG_stages_37bits, N, FD_CNG_maxN_37bits, indices, 0, NULL, v, NULL );
     589             :     }
     590             : 
     591             : 
     592             :     /* Compute gain */
     593        1189 :     gain = 0.f;
     594       28774 :     for ( i = 0; i < N; i++ )
     595             :     {
     596       27585 :         gain += v[i];
     597             :     }
     598             : 
     599        1189 :     gain = ( e - gain ) / (float) N;
     600             : 
     601             :     /* Apply bitrate-dependant scale */
     602        1189 :     if ( st->element_mode > EVS_MONO )
     603             :     {
     604        1189 :         apply_scale( &gain, hFdCngCom->CngBandwidth, hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO );
     605             :     }
     606             :     else
     607             :     {
     608           0 :         apply_scale( &gain, hFdCngCom->CngBandwidth, hFdCngCom->CngBitrate, scaleTableMono, SIZE_SCALE_TABLE_MONO );
     609             :     }
     610             : 
     611             :     /* Quantize gain */
     612        1189 :     index = (int16_t) floor( gain * 1.5f + gain_q_offset + 0.5f );
     613             : 
     614        1189 :     if ( index < 0 )
     615             :     {
     616         159 :         index = 0;
     617             :     }
     618             : 
     619        1189 :     if ( index > 127 )
     620             :     {
     621           0 :         index = 127;
     622             :     }
     623             : 
     624        1189 :     gain = ( (float) index - gain_q_offset ) / 1.5f;
     625             : 
     626             :     /* Apply gain and undo log */
     627       28774 :     for ( i = 0; i < N; i++ )
     628             :     {
     629             : 
     630       27585 :         hFdCngCom->sidNoiseEst[i] = (float) pow( 10.f, ( v[i] + gain ) / 10.f );
     631             :     }
     632             : 
     633             :     /* NB last band energy compensation */
     634        1189 :     if ( hFdCngCom->CngBandwidth == NB )
     635             :     {
     636           0 :         hFdCngCom->sidNoiseEst[N - 1] *= NB_LAST_BAND_SCALE;
     637             :     }
     638             : 
     639        1189 :     if ( hFdCngCom->CngBandwidth == SWB && hFdCngCom->CngBitrate <= ACELP_13k20 )
     640             :     {
     641         568 :         hFdCngCom->sidNoiseEst[N - 1] *= SWB_13k2_LAST_BAND_SCALE;
     642             :     }
     643             : 
     644             :     /* Write bitstream */
     645        1189 :     if ( st->codec_mode == MODE2 )
     646             :     {
     647           0 :         for ( i = 0; i < FD_CNG_stages_37bits; i++ )
     648             :         {
     649           0 :             push_next_indice( hBstr, indices[i], bits_37bits[i] );
     650             :         }
     651             : 
     652           0 :         push_next_indice( hBstr, index, 7 );
     653             :     }
     654             :     else
     655             :     {
     656        1189 :         push_indice( hBstr, IND_SID_TYPE, 1, 1 );
     657        1189 :         push_indice( hBstr, IND_BWIDTH, st->bwidth, 2 );
     658        1189 :         push_indice( hBstr, IND_ACELP_16KHZ, st->L_frame == L_FRAME16k ? 1 : 0, 1 );
     659             : 
     660        8323 :         for ( i = 0; i < FD_CNG_stages_37bits; i++ )
     661             :         {
     662        7134 :             push_indice( hBstr, IND_LSF, indices[i], bits_37bits[i] );
     663             :         }
     664             : 
     665        1189 :         push_indice( hBstr, IND_ENERGY, index, 7 );
     666             :     }
     667             : 
     668             :     /* Interpolate the bin/band-wise levels from the partition levels */
     669        1189 :     scalebands( hFdCngCom->sidNoiseEst, hFdCngEnc->partDec, hFdCngEnc->npartDec, hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, hFdCngEnc->stopBandDec - hFdCngEnc->startBandDec, hFdCngCom->cngNoiseLevel, 1 );
     670             : 
     671        1189 :     lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, preemph_fac );
     672             : 
     673        1189 :     return;
     674             : }
     675             : 
     676             : 
     677             : /*-------------------------------------------------------------------*
     678             :  * generate_comfort_noise_enc()
     679             :  *
     680             :  *
     681             :  *-------------------------------------------------------------------*/
     682             : 
     683        6790 : void generate_comfort_noise_enc(
     684             :     Encoder_State *st /* i/o: encoder state structure     */
     685             : )
     686             : {
     687             :     int16_t i;
     688             :     float *ptr_r;
     689             :     float *ptr_i;
     690        6790 :     HANDLE_FD_CNG_ENC hFdCngEnc = st->hFdCngEnc;
     691        6790 :     HANDLE_FD_CNG_COM hFdCngCom = hFdCngEnc->hFdCngCom;
     692        6790 :     float *cngNoiseLevel = hFdCngCom->cngNoiseLevel;
     693        6790 :     float *ptr_level = cngNoiseLevel;
     694        6790 :     int16_t *seed = &( hFdCngCom->seed );
     695        6790 :     float scale = 1.f;
     696        6790 :     float *fftBuffer = hFdCngCom->fftBuffer;
     697        6790 :     float *timeDomainOutput = hFdCngCom->timeDomainBuffer;
     698        6790 :     float preemph_fac = st->preemph_fac;
     699        6790 :     int16_t tcx_transition = 0;
     700             :     float enr;
     701             : 
     702             :     /* Generate Gaussian random noise in real and imaginary parts of the FFT bins
     703             :       Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin */
     704        6790 :     if ( hFdCngEnc->startBandDec == 0 )
     705             :     {
     706           0 :         rand_gauss( &fftBuffer[0], seed );
     707           0 :         fftBuffer[0] *= (float) sqrt( scale * *ptr_level ); /* DC component in FFT */
     708           0 :         ptr_level++;
     709           0 :         ptr_r = fftBuffer + 2;
     710             :     }
     711             :     else
     712             :     {
     713        6790 :         fftBuffer[0] = 0.f;
     714        6790 :         set_f( fftBuffer + 2, 0.0f, 2 * ( hFdCngEnc->startBandDec - 1 ) );
     715        6790 :         ptr_r = fftBuffer + 2 * hFdCngEnc->startBandDec;
     716             :     }
     717             : 
     718        6790 :     ptr_i = ptr_r + 1;
     719     1920186 :     for ( ; ptr_level < cngNoiseLevel + hFdCngEnc->stopFFTbinDec - hFdCngEnc->startBandDec; ptr_level++ )
     720             :     {
     721             :         /* Real part in FFT bins */
     722     1913396 :         rand_gauss( ptr_r, seed );
     723     1913396 :         ( *ptr_r ) *= (float) sqrt( ( scale * *ptr_level ) * 0.5f );
     724     1913396 :         ptr_r += 2;
     725             :         /* Imaginary part in FFT bins */
     726     1913396 :         rand_gauss( ptr_i, seed );
     727     1913396 :         ( *ptr_i ) *= (float) sqrt( ( scale * *ptr_level ) * 0.5f );
     728     1913396 :         ptr_i += 2;
     729             :     }
     730             : 
     731             :     /* Remaining FFT bins are set to zero */
     732        6790 :     set_f( fftBuffer + 2 * hFdCngEnc->stopFFTbinDec, 0.0f, hFdCngCom->fftlen - 2 * hFdCngEnc->stopFFTbinDec );
     733             : 
     734             :     /* Nyquist frequency is discarded */
     735        6790 :     fftBuffer[1] = 0.f;
     736             : 
     737             :     /* If previous frame is active, reset the overlap-add buffer */
     738        6790 :     if ( st->last_core_brate > SID_2k40 )
     739             :     {
     740         538 :         set_f( hFdCngCom->olapBufferSynth, 0.0f, hFdCngCom->fftlen );
     741             : 
     742         538 :         if ( ( st->last_core > ACELP_CORE && st->codec_mode == MODE2 ) || st->codec_mode == MODE1 )
     743             :         {
     744         538 :             tcx_transition = 1;
     745             :         }
     746             :     }
     747             : 
     748             :     /* Perform STFT synthesis */
     749        6790 :     SynthesisSTFT( fftBuffer, timeDomainOutput, hFdCngCom->olapBufferSynth, hFdCngCom->olapWinSyn, tcx_transition, hFdCngCom, -1, -1 );
     750             : 
     751        6790 :     if ( st->hTdCngEnc != NULL )
     752             :     {
     753             :         /* update CNG excitation energy for LP_CNG */
     754             :         /* calculate the residual signal energy */
     755        5105 :         enr = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, hFdCngCom->exc_cng, hFdCngCom->frameSize );
     756             : 
     757        5105 :         st->hTdCngEnc->lp_ener = (float) ( 0.8f * st->hTdCngEnc->lp_ener + 0.2f * pow( 2.0f, enr ) );
     758             :     }
     759             : 
     760             :     /* Overlap-add when previous frame is active */
     761        6790 :     if ( st->last_core_brate > SID_2k40 && st->codec_mode == MODE2 )
     762             :     {
     763           0 :         float noise[2048], old_exc_ener = 0.f, gain = 0.f, tmp;
     764           0 :         int16_t N = hFdCngCom->frameSize;
     765           0 :         int16_t seed_loc = hFdCngCom->seed;
     766             :         float *old_exc, old_Aq[M + 1], *old_syn_pe, old_syn;
     767             : 
     768           0 :         if ( st->last_core > ACELP_CORE )
     769             :         {
     770           0 :             tcx_windowing_synthesis_current_frame( timeDomainOutput, st->hTcxCfg->tcx_mdct_window, /*Keep sine windows for limiting Time modulation*/
     771           0 :                                                    st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, st->hTcxCfg->tcx_mdct_window_length, st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, 0, st->hTcxCfg->tcx_last_overlap_mode == ALDO_WINDOW ? FULL_OVERLAP : st->hTcxCfg->tcx_last_overlap_mode, NULL, NULL, NULL, NULL, NULL, N / 2, st->hTcxCfg->tcx_offset < 0 ? -st->hTcxCfg->tcx_offset : 0, 1, 0, 0 );
     772             : 
     773           0 :             if ( st->hTcxCfg->last_aldo )
     774             :             {
     775           0 :                 for ( i = 0; i < hFdCngCom->frameSize; i++ )
     776             :                 {
     777           0 :                     timeDomainOutput[i] += st->hTcxEnc->old_out[i + NS2SA( st->sr_core, N_ZERO_MDCT_NS )];
     778             :                 }
     779             :             }
     780             :             else
     781             :             {
     782           0 :                 tcx_windowing_synthesis_past_frame( st->hTcxEnc->Txnq, st->hTcxCfg->tcx_aldo_window_1_trunc, st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, st->hTcxCfg->tcx_mdct_window_length, st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, st->hTcxCfg->tcx_last_overlap_mode );
     783             : 
     784           0 :                 for ( i = 0; i < st->hTcxCfg->tcx_mdct_window_length; i++ )
     785             :                 {
     786           0 :                     timeDomainOutput[i] += st->hTcxEnc->Txnq[i];
     787             :                 }
     788             :             }
     789             :         }
     790             :         else
     791             :         {
     792           0 :             lsp2a_stab( st->lsp_old, old_Aq, M );
     793           0 :             old_exc = st->hLPDmem->old_exc + L_EXC_MEM - ( N / 2 );
     794           0 :             old_syn_pe = st->hLPDmem->mem_syn2;
     795           0 :             old_syn = st->hLPDmem->syn[M];
     796           0 :             for ( i = 0; i < N / 2; i++ )
     797             :             {
     798           0 :                 old_exc_ener += old_exc[i] * old_exc[i];
     799             :             }
     800             : 
     801           0 :             old_exc_ener = (float) sqrt( old_exc_ener / (float) ( N / 2 ) );
     802             : 
     803           0 :             for ( i = 0; i < N; i++ )
     804             :             {
     805           0 :                 rand_gauss( &( noise[i] ), &( seed_loc ) );
     806           0 :                 gain += noise[i] * noise[i];
     807             :             }
     808             : 
     809           0 :             gain = old_exc_ener / (float) sqrt( gain / (float) N );
     810             : 
     811           0 :             for ( i = 0; i < N; i++ )
     812             :             {
     813           0 :                 noise[i] *= gain;
     814             :             }
     815             : 
     816           0 :             syn_filt( old_Aq, M, noise, noise, N, old_syn_pe, 0 );
     817             : 
     818           0 :             tmp = old_syn;
     819             : 
     820           0 :             deemph( noise, preemph_fac, N, &tmp );
     821             : 
     822           0 :             for ( i = 0; i < N / 2; i++ )
     823             :             {
     824           0 :                 timeDomainOutput[i] += noise[i] * hFdCngCom->olapWinSyn[N / 2 + i];
     825             :             }
     826             :         }
     827             :     }
     828             : 
     829        6790 :     return;
     830             : }
     831             : 
     832             : /*-------------------------------------------------------------------*
     833             :  * cng_energy()
     834             :  *
     835             :  *
     836             :  *-------------------------------------------------------------------*/
     837             : 
     838             : /*! r: CNG energy */
     839        5810 : float cng_energy(
     840             :     const int16_t element_mode, /* i  : element mode                */
     841             :     const int16_t bwidth,       /* i  : audio bandwidh              */
     842             :     const int16_t CNG_mode,     /* i  : mode for DTX configuration  */
     843             :     const float CNG_att,        /* i  : attenuation factor for CNG  */
     844             :     const float *exc,           /* i  : input signal                */
     845             :     const int16_t len           /* i  : vector length               */
     846             : )
     847             : {
     848             :     float enr, att;
     849             : 
     850             :     /* calculate the residual signal energy */
     851        5810 :     enr = dotp( exc, exc, len ) / len;
     852             : 
     853             :     /* convert log2 of residual signal energy */
     854        5810 :     enr = (float) log10( enr + 0.1f ) / (float) log10( 2.0f );
     855             : 
     856             :     /* decrease the energy in case of WB input */
     857        5810 :     if ( element_mode == IVAS_CPE_DFT || element_mode == IVAS_CPE_TD )
     858             :     {
     859        4160 :         enr += CNG_att * FAC_LOG2 / 10.0f;
     860             :     }
     861        1650 :     else if ( bwidth != NB )
     862             :     {
     863        1650 :         if ( bwidth == WB )
     864             :         {
     865         921 :             if ( CNG_mode >= 0 )
     866             :             {
     867             :                 /* Bitrate adapted attenuation */
     868           0 :                 att = ENR_ATT[CNG_mode];
     869             :             }
     870             :             else
     871             :             {
     872             :                 /* Use least attenuation for higher bitrates */
     873         921 :                 att = ENR_ATT[4];
     874             :             }
     875             :         }
     876             :         else
     877             :         {
     878         729 :             att = 1.5f;
     879             :         }
     880        1650 :         enr -= att;
     881             :     }
     882             : 
     883        5810 :     return ( enr );
     884             : }
     885             : 
     886             : 
     887             : /*-------------------------------------------------------------------*
     888             :  * stereoFdCngCoherence()
     889             :  *
     890             :  * compute coherence of channels for use in FD-CNG
     891             :  *-------------------------------------------------------------------*/
     892             : 
     893       10328 : void stereoFdCngCoherence(
     894             :     Encoder_State **sts,                    /* i/o: core encoder structures          */
     895             :     const int16_t last_element_mode,        /* i  : last element mode                */
     896             :     float fft_buff[CPE_CHANNELS][2 * L_FFT] /* i  : fft buffers for L and R channels */
     897             : )
     898             : {
     899             :     const float *pt_fftL, *pt_fftR;
     900             :     int16_t i_subfr, i;
     901             :     float cr, ci, eL, eR;
     902             :     float *mem;
     903             : 
     904       10328 :     if ( last_element_mode != IVAS_CPE_MDCT )
     905             :     {
     906             : #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
     907         378 :         for ( i = 0; i < MDCT_ST_DTX_NUM_COHERENCE_BANDS; i++ )
     908             :         {
     909         315 :             set_f( sts[0]->hFdCngEnc->mem_coherence[i], EPSILON, 4 );
     910             :         }
     911             : #else
     912             :         set_f( sts[0]->hFdCngEnc->mem_coherence, EPSILON, 4 );
     913             : #endif
     914             :     }
     915             : 
     916       10328 :     if ( sts[0]->core_brate == -1 || sts[1]->core_brate == -1 )
     917             :     {
     918             :         /* case: at least one channel has triggered VAD -> ACTIVE FRAME */
     919        8304 :         if ( sts[0]->core_brate == -1 )
     920             :         {
     921        8036 :             sts[1]->total_brate = sts[0]->total_brate;
     922        8036 :             sts[1]->active_cnt = sts[0]->active_cnt;
     923        8036 :             if ( sts[1]->active_cnt >= CNG_TYPE_HO )
     924             :             {
     925        7469 :                 sts[1]->last_total_brate_cng = -1;
     926             :             }
     927             :         }
     928        8304 :         if ( sts[1]->core_brate == -1 )
     929             :         {
     930        8004 :             sts[0]->total_brate = sts[1]->total_brate;
     931        8004 :             sts[0]->active_cnt = sts[1]->active_cnt;
     932        8004 :             if ( sts[0]->active_cnt >= CNG_TYPE_HO )
     933             :             {
     934        7529 :                 sts[0]->last_total_brate_cng = -1;
     935             :             }
     936             :         }
     937        8304 :         sts[0]->core_brate = -1;
     938        8304 :         sts[1]->core_brate = -1;
     939        8304 :         sts[0]->hDtxEnc->cnt_SID = 0;
     940        8304 :         sts[1]->hDtxEnc->cnt_SID = 0;
     941             :     }
     942        2024 :     else if ( sts[0]->core_brate <= SID_2k40 && sts[1]->core_brate <= SID_2k40 )
     943             :     {
     944             :         /* case: no VAD for both channels -> INACTIVE FRAME */
     945        2024 :         reset_indices_enc( sts[0]->hBstr, sts[0]->hBstr->nb_ind_tot );
     946             : 
     947        2024 :         reset_indices_enc( sts[1]->hBstr, sts[1]->hBstr->nb_ind_tot );
     948             : 
     949             :         /* synchronize SID sending for variable SID rate */
     950        2024 :         if ( sts[0]->core_brate != sts[1]->core_brate )
     951             :         {
     952           0 :             sts[0]->core_brate = SID_2k40;
     953           0 :             sts[1]->core_brate = SID_2k40;
     954             :         }
     955             : 
     956             :         /* synchronize SID counters */
     957        2024 :         sts[0]->hDtxEnc->cnt_SID = min( sts[0]->hDtxEnc->cnt_SID, sts[1]->hDtxEnc->cnt_SID );
     958        2024 :         sts[1]->hDtxEnc->cnt_SID = sts[0]->hDtxEnc->cnt_SID;
     959             :     }
     960             : 
     961       10328 :     pt_fftL = fft_buff[0];
     962       10328 :     pt_fftR = fft_buff[1];
     963             : #ifndef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
     964             :     mem = sts[0]->hFdCngEnc->mem_coherence;
     965             : #endif
     966             : 
     967             :     /* only estimate coherence in inactive frames (or in the first 50 frames to build an initial value) */
     968       10328 :     if ( !( sts[0]->ini_frame <= 50 || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) ) )
     969             :     {
     970        6619 :         return;
     971             :     }
     972             : 
     973             : #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
     974       11127 :     for ( i_subfr = 0; i_subfr < 2; i_subfr++ )
     975             :     {
     976             :         int16_t band_len_cum;
     977             : 
     978        7418 :         band_len_cum = 0;
     979        7418 :         i = MDCT_ST_DTX_FIRST_BAND_OFFSET;
     980             : 
     981       44508 :         for ( int16_t b = 0; b < MDCT_ST_DTX_NUM_COHERENCE_BANDS; b++ )
     982             :         {
     983       37090 :             band_len_cum += mdct_stereo_dtx_coherence_bandlengths[b];
     984       37090 :             cr = ci = eL = eR = EPSILON;
     985       37090 :             mem = sts[0]->hFdCngEnc->mem_coherence[b];
     986             : 
     987             :             /* for last band, we need to make adjustments to fit with the FFT buffer layout */
     988             :             /* do the calculations for fftbin 0 (not anymore as it is skipped - we only calculate coherence above the 2nd bin) and L_FFT/2 outside the loop - imaginary part is always zero there, but not part of the buffer */
     989       37090 :             if ( b == MDCT_ST_DTX_NUM_COHERENCE_BANDS - 1 )
     990             :             {
     991             :                 /* this calculates values for fft bin at L_FFT/2 - no imaginary value there, not even part of the array */
     992        7418 :                 cr += pt_fftL[L_FFT / 2] * pt_fftR[L_FFT / 2];
     993        7418 :                 eL += pt_fftL[L_FFT / 2] * pt_fftL[L_FFT / 2];
     994        7418 :                 eR += pt_fftR[L_FFT / 2] * pt_fftR[L_FFT / 2];
     995             : 
     996             :                 /* skip last fft bin (fs/2 Hz) bin in the loop later */
     997        7418 :                 --band_len_cum;
     998             :             }
     999             : 
    1000      949504 :             for ( ; i < band_len_cum; i++ )
    1001             :             {
    1002      912414 :                 cr += pt_fftL[i] * pt_fftR[i] + pt_fftL[L_FFT - i] * pt_fftR[L_FFT - i];
    1003      912414 :                 ci += -pt_fftL[i] * pt_fftR[L_FFT - i] + pt_fftR[i] * pt_fftL[L_FFT - i];
    1004      912414 :                 eL += pt_fftL[i] * pt_fftL[i] + pt_fftL[L_FFT - i] * pt_fftL[L_FFT - i];
    1005      912414 :                 eR += pt_fftR[i] * pt_fftR[i] + pt_fftR[L_FFT - i] * pt_fftR[L_FFT - i];
    1006             :             }
    1007             : 
    1008       37090 :             mem[0] = 0.95f * mem[0] + 0.05f * cr;
    1009       37090 :             mem[1] = 0.95f * mem[1] + 0.05f * ci;
    1010       37090 :             mem[2] = 0.95f * mem[2] + 0.05f * eL;
    1011       37090 :             mem[3] = 0.95f * mem[3] + 0.05f * eR;
    1012             : 
    1013             :             /* could be done outside the loop, as the second assignment overwrites the first, but this would mean a second loop over bands */
    1014       37090 :             sts[0]->hFdCngEnc->hFdCngCom->coherence[b] = sqrtf( ( mem[0] * mem[0] + mem[1] * mem[1] ) / ( mem[2] * mem[3] ) );
    1015             :         }
    1016             : 
    1017        7418 :         pt_fftL += L_FFT;
    1018        7418 :         pt_fftR += L_FFT;
    1019             :     }
    1020             : 
    1021             : #else
    1022             :     for ( i_subfr = 0; i_subfr < 2; i_subfr++ )
    1023             :     {
    1024             :         cr = ci = eL = eR = EPSILON;
    1025             : 
    1026             :         cr += pt_fftL[0] * pt_fftR[0] + pt_fftL[L_FFT / 2] * pt_fftR[L_FFT / 2];
    1027             :         eL += pt_fftL[0] * pt_fftL[0] + pt_fftL[L_FFT / 2] * pt_fftL[L_FFT / 2];
    1028             :         eR += pt_fftR[0] * pt_fftR[0] + pt_fftR[L_FFT / 2] * pt_fftR[L_FFT / 2];
    1029             : 
    1030             :         for ( i = 1; i < L_FFT / 2; i++ )
    1031             :         {
    1032             :             cr += pt_fftL[i] * pt_fftR[i] + pt_fftL[L_FFT - i] * pt_fftR[L_FFT - i];
    1033             :             ci += -pt_fftL[i] * pt_fftR[L_FFT - i] + pt_fftR[i] * pt_fftL[L_FFT - i];
    1034             :             eL += pt_fftL[i] * pt_fftL[i] + pt_fftL[L_FFT - i] * pt_fftL[L_FFT - i];
    1035             :             eR += pt_fftR[i] * pt_fftR[i] + pt_fftR[L_FFT - i] * pt_fftR[L_FFT - i];
    1036             :         }
    1037             : 
    1038             :         if ( sts[0]->ini_frame <= 50 || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) )
    1039             :         {
    1040             :             mem[0] = 0.95f * mem[0] + 0.05f * cr;
    1041             :             mem[1] = 0.95f * mem[1] + 0.05f * ci;
    1042             :             mem[2] = 0.95f * mem[2] + 0.05f * eL;
    1043             :             mem[3] = 0.95f * mem[3] + 0.05f * eR;
    1044             :         }
    1045             : 
    1046             :         pt_fftL += L_FFT;
    1047             :         pt_fftR += L_FFT;
    1048             :     }
    1049             : #endif
    1050             : #ifndef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
    1051             :     sts[0]->hFdCngEnc->hFdCngCom->coherence = sqrtf( ( mem[0] * mem[0] + mem[1] * mem[1] ) / ( mem[2] * mem[3] ) );
    1052             : #endif
    1053             : 
    1054        3709 :     return;
    1055             : }
    1056             : 
    1057             : 
    1058             : /*-------------------------------------------------------------------*
    1059             :  * FdCngEncodeMDCTStereoSID()
    1060             :  *
    1061             :  * Encode DTX parameters and noise shapes into SID for MDCT-Stereo DTX
    1062             :  *-------------------------------------------------------------------*/
    1063             : 
    1064         214 : void FdCngEncodeMDCTStereoSID(
    1065             :     CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure     */
    1066             : )
    1067             : {
    1068             :     ENC_CORE_HANDLE sts[CPE_CHANNELS];
    1069             :     float *lr_in_ptr[CPE_CHANNELS];
    1070             :     float *ms_ptr[CPE_CHANNELS];
    1071             :     float *lr_out_ptr[CPE_CHANNELS];
    1072             :     float logNoiseEst[CPE_CHANNELS][NPART];
    1073             :     float E[CPE_CHANNELS];
    1074             :     float gain[CPE_CHANNELS];
    1075             :     float weights[NPART];
    1076             :     int16_t indices[CPE_CHANNELS][FD_CNG_stages_37bits];
    1077             :     int16_t gain_idx[CPE_CHANNELS];
    1078             :     int16_t N, stages, ch, p, coh_idx;
    1079             :     float side_energy;
    1080             :     int16_t no_side_flag;
    1081             :     int16_t is_inp_ms;
    1082             : 
    1083             :     float tot_sig_ext[FDCNG_VQ_MAX_LEN], dct_target[CPE_CHANNELS][FDCNG_VQ_DCT_MAXTRUNC]; /* 24 +2*18*/
    1084             :     float *invTrfMatrix;
    1085             :     float tmpRAM[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; /*24*18*/
    1086         214 :     invTrfMatrix = (float *) tmpRAM;                       /* dynamically filled  */
    1087             : 
    1088             : 
    1089         214 :     is_inp_ms = 0;
    1090         214 :     if ( hCPE->hCoreCoder[0]->cng_sba_flag == 1 )
    1091             :     {
    1092           0 :         is_inp_ms = 1;
    1093             :     }
    1094             : 
    1095             :     /* set pointers and initialize */
    1096         642 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1097             :     {
    1098         428 :         sts[ch] = hCPE->hCoreCoder[ch];
    1099         428 :         lr_in_ptr[ch] = &sts[ch]->hFdCngEnc->msNoiseEst[0];
    1100         428 :         ms_ptr[ch] = &logNoiseEst[ch][0];
    1101         428 :         lr_out_ptr[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst[0];
    1102             :     }
    1103             : #ifdef DEBUGGING
    1104             :     assert( sts[0]->hFdCngEnc->npartDec == sts[1]->hFdCngEnc->npartDec );
    1105             : #endif
    1106         214 :     N = sts[0]->hFdCngEnc->npartDec;
    1107         214 :     set_f( weights, 1.f, NPART );
    1108             : 
    1109             :     /* apply log and save energy of original left and right channels */
    1110         642 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1111             :     {
    1112         428 :         E[ch] = 0.0f;
    1113       10208 :         for ( p = 0; p < N; p++ )
    1114             :         {
    1115        9780 :             ms_ptr[ch][p] = 10.f * log10f( lr_in_ptr[ch][p] + EPSILON );
    1116        9780 :             E[ch] += ms_ptr[ch][p];
    1117             :         }
    1118             :     }
    1119             : 
    1120             :     /* M/S transform on log envelopes */
    1121         214 :     if ( is_inp_ms == 0 )
    1122             :     {
    1123         214 :         convertToMS( N, ms_ptr[0], ms_ptr[1], 0.5f );
    1124             :     }
    1125             : 
    1126         214 :     side_energy = sum2_f( ms_ptr[1], N );
    1127             : 
    1128             :     /* do not transmit side shape if initial noise shapes are very similar */
    1129         214 :     if ( side_energy <= 0.1f )
    1130             :     {
    1131           8 :         no_side_flag = 1;
    1132             :     }
    1133             :     else
    1134             :     {
    1135         206 :         no_side_flag = 0;
    1136             :     }
    1137             : 
    1138             :     /* Quantize noise shapes */
    1139         642 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1140             :     {
    1141             :         /* Normalize MSVQ input */
    1142         428 :         gain[ch] = 0.f;
    1143        5992 :         for ( p = N_GAIN_MIN; p < N_GAIN_MAX; p++ )
    1144             :         {
    1145        5564 :             gain[ch] += ms_ptr[ch][p];
    1146             :         }
    1147         428 :         gain[ch] /= (float) ( N_GAIN_MAX - N_GAIN_MIN );
    1148             : 
    1149       10208 :         for ( p = 0; p < N; p++ )
    1150             :         {
    1151        9780 :             ms_ptr[ch][p] -= gain[ch];
    1152             :         }
    1153             :     }
    1154             :     /* always split channel targetloop */
    1155             : 
    1156             :     /* extend fdcng envelope from length 21 to a 24 length fdncg domain envelope signal */
    1157             :     /* High quality cosine smooth basis extension used  to not introduce noise in stage#1  DCT24 analysis and subsequent VQ-steps */
    1158         214 :     if ( N == FDCNG_VQ_MAX_LEN_WB )
    1159             :     {
    1160          82 :         create_IDCT_N_Matrix( invTrfMatrix, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /*WB: create truncated IDCT21 matrix */
    1161             : 
    1162         246 :         for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1163             :         {
    1164             :             /* run DCT_N N==21 , truncated at 18/21 ~= 86% , i.e use a bit better better quality in extrapolation , than subsequent DCT24 analysis which is truncated at 75%*/
    1165             : 
    1166             :             /* truncated DCT 21 analysis */
    1167         164 :             dctT2_N_apply_matrix( (const float *) ms_ptr[ch], dct_target[ch], FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX );
    1168             : 
    1169             :             /* extrapolate extend fdcng envelope signal in the fdncg ienvelope/"time" domain using DCT21 basis vectors,
    1170             :                 estimated DCT21 coeffs scaling extended basis vectors are used to create extrapolated   length 24 input target envelope signal */
    1171             :             /* this DCT21 extension does not introduce DCT24 coefficient noise for  the subsequent dct24 target analysis, and later in IDCT24 synthesis  */
    1172             : 
    1173             :             /* truncated IDCT 21 extension synthesis  */
    1174         164 :             extend_dctN_input( ms_ptr[ch], dct_target[ch], N, tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix /* DCT_N basis vectors */, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/
    1175             : 
    1176         164 :             mvr2r( tot_sig_ext, ms_ptr[ch], FDCNG_VQ_MAX_LEN ); /*  write  extended result as input to  VQ */
    1177             :         }
    1178             :     }
    1179         214 :     create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); /*always create/set up  IDCT24 matrix in RAM */
    1180             : 
    1181             :     /* end split */
    1182         642 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1183             :     {
    1184             :         /* MSVQ */
    1185         428 :         if ( ch )
    1186             :         {
    1187         214 :             stages = FD_CNG_JOINT_stages_25bits;
    1188             :         }
    1189             :         else
    1190             :         {
    1191         214 :             stages = FD_CNG_stages_37bits;
    1192             :         }
    1193             : 
    1194             :         /* DCT24 domain compressed/truncated indices used for first stage  */
    1195             :         /*             mid  channel quantization using stages 1 through 6 */
    1196             :         /*           & side channel quantization using stages 1 through 4 */
    1197             : 
    1198             :         {
    1199         428 :             msvq_enc( cdk_37bits_ivas, NULL, NULL, ms_ptr[ch], levels_37bits, FD_CNG_maxC_37bits, stages, weights, N, FD_CNG_maxN_37bits, 1, invTrfMatrix, indices[ch] );
    1200         428 :             msvq_dec( cdk_37bits_ivas, NULL, NULL, stages, N, FD_CNG_maxN_37bits, indices[ch], 1, invTrfMatrix, ms_ptr[ch], NULL );
    1201             :         }
    1202             :     }
    1203             : 
    1204         214 :     if ( no_side_flag )
    1205             :     {
    1206           8 :         set_zero( ms_ptr[1], N );
    1207             :     }
    1208             : 
    1209             :     /* undo M/S */
    1210         214 :     if ( is_inp_ms == 0 )
    1211             :     {
    1212         214 :         convertToMS( N, ms_ptr[0], ms_ptr[1], 1.0f );
    1213             :     }
    1214             : 
    1215             :     /* Compute gain against original left and right channels */
    1216         642 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1217             :     {
    1218         428 :         gain[ch] = 0.f;
    1219       10208 :         for ( p = 0; p < N; p++ )
    1220             :         {
    1221        9780 :             gain[ch] += ms_ptr[ch][p];
    1222             :         }
    1223         428 :         gain[ch] = ( E[ch] - gain[ch] ) / (float) N;
    1224         428 :         apply_scale( &gain[ch], sts[ch]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[ch]->element_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO );
    1225             : 
    1226             :         /* quantize gain */
    1227         428 :         gain_idx[ch] = (int16_t) floor( gain[ch] * 1.5f + GAIN_Q_OFFSET_IVAS + .5f );
    1228         428 :         gain_idx[ch] = max( 0, min( 127, gain_idx[ch] ) );
    1229             : 
    1230         428 :         gain[ch] = ( (float) gain_idx[ch] - GAIN_Q_OFFSET_IVAS ) / 1.5f;
    1231             :     }
    1232             : 
    1233             :     /* restore channel noise envelopes */
    1234         642 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1235             :     {
    1236         428 :         HANDLE_FD_CNG_ENC hFdCngEnc = sts[ch]->hFdCngEnc;
    1237         428 :         HANDLE_FD_CNG_COM hFdCngCom = hFdCngEnc->hFdCngCom;
    1238             : 
    1239       10208 :         for ( p = 0; p < N; p++ )
    1240             :         {
    1241        9780 :             lr_out_ptr[ch][p] = powf( 10.f, ( ms_ptr[ch][p] + gain[ch] ) / 10.f );
    1242             :         }
    1243             : 
    1244             :         /* scale bands and get scalefactors */
    1245         428 :         scalebands( lr_out_ptr[ch], hFdCngEnc->partDec, N, hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, hFdCngEnc->stopBandDec - hFdCngEnc->startBandDec, hFdCngCom->cngNoiseLevel, 1 );
    1246             : 
    1247         428 :         lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac );
    1248             : 
    1249         428 :         sts[ch]->hDtxEnc->last_CNG_L_frame = sts[ch]->L_frame;
    1250             :     }
    1251             : 
    1252             :     /* quantize channel coherence */
    1253             : #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
    1254         214 :     coh_idx = (int16_t) floor( sts[0]->hFdCngEnc->hFdCngCom->coherence[0] * 15.f + 0.5f );
    1255             : #else
    1256             :     coh_idx = (int16_t) floor( sts[0]->hFdCngEnc->hFdCngCom->coherence * 15.f + 0.5f );
    1257             : #endif
    1258         214 :     coh_idx = max( 0, min( coh_idx, 15 ) );
    1259             : 
    1260             :     /* ---- Write SID bitstream ---- */
    1261             : 
    1262             : 
    1263             :     /* noise shapes and channel gains */
    1264         642 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1265             :     {
    1266         428 :         if ( ch )
    1267             :         {
    1268         214 :             stages = FD_CNG_JOINT_stages_25bits;
    1269         214 :             sts[ch]->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot;
    1270             : 
    1271             :             /* side info */
    1272         214 :             push_indice( sts[ch]->hBstr, IND_SID_TYPE, coh_idx, 4 );
    1273         214 :             push_indice( sts[ch]->hBstr, IND_SID_TYPE, no_side_flag, 1 );
    1274             :         }
    1275             :         else
    1276             :         {
    1277         214 :             stages = FD_CNG_stages_37bits;
    1278             :             /* side info */
    1279         214 :             push_indice( sts[ch]->hBstr, IND_SID_TYPE, 1, 1 );
    1280         214 :             push_indice( sts[ch]->hBstr, IND_BWIDTH, sts[0]->bwidth, 2 );
    1281         214 :             push_indice( sts[ch]->hBstr, IND_ACELP_16KHZ, sts[0]->L_frame == L_FRAME16k ? 1 : 0, 1 );
    1282             :         }
    1283             : 
    1284        2568 :         for ( int16_t i = 0; i < stages; i++ )
    1285             :         {
    1286        2140 :             push_indice( sts[ch]->hBstr, IND_LSF, indices[ch][i], bits_37bits[i] );
    1287             :         }
    1288         428 :         push_indice( sts[ch]->hBstr, IND_ENERGY, gain_idx[ch], 7 );
    1289             :     }
    1290             : 
    1291             : #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
    1292             :     /* write the four additional coherence values */
    1293        1070 :     for ( int16_t b = 1; b < MDCT_ST_DTX_NUM_COHERENCE_BANDS; b++ )
    1294             :     {
    1295         856 :         coh_idx = (int16_t) floor( sts[0]->hFdCngEnc->hFdCngCom->coherence[b] * 15.f + 0.5f );
    1296         856 :         coh_idx = max( 0, min( coh_idx, 15 ) );
    1297         856 :         push_indice( sts[1]->hBstr, IND_ENERGY, coh_idx, 4 );
    1298             :     }
    1299             : #else
    1300             :     /* pad with zeros to reach common SID frame size */
    1301             :     push_indice( sts[1]->hBstr, IND_ENERGY, 0, ( IVAS_SID_5k2 - 4400 ) / FRAMES_PER_SEC );
    1302             : #endif
    1303             : 
    1304             : 
    1305         214 :     return;
    1306             : }
    1307             : 
    1308             : 
    1309             : /*-------------------------------------------------------------------*
    1310             :  * FdCngEncodeDiracMDCTStereoSID()
    1311             :  *
    1312             :  * Encode DTX parameters and noise shapes into SID for MDCT-Stereo DTX
    1313             :  * together with Dirac
    1314             :  *-------------------------------------------------------------------*/
    1315             : 
    1316          75 : void FdCngEncodeDiracMDCTStereoSID(
    1317             :     CPE_ENC_HANDLE hCPE /* i/o: CPE encoder state structure     */
    1318             : )
    1319             : {
    1320             :     ENC_CORE_HANDLE sts[CPE_CHANNELS];
    1321             :     float *lr_in_ptr[CPE_CHANNELS];
    1322             :     float *ms_ptr[CPE_CHANNELS];
    1323             :     float *lr_out_ptr[CPE_CHANNELS];
    1324             :     float logNoiseEst[CPE_CHANNELS][NPART];
    1325             :     float E[CPE_CHANNELS];
    1326             :     float gain[CPE_CHANNELS];
    1327             :     float weights[NPART];
    1328             :     int16_t N[CPE_CHANNELS];
    1329             :     int16_t indices[CPE_CHANNELS][FD_CNG_stages_37bits];
    1330             :     int16_t gain_idx[CPE_CHANNELS];
    1331             :     int16_t ch, p;
    1332             :     float *invTrfMatrix;
    1333             :     float tmpRAM[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC];
    1334             :     float dct_target[FDCNG_VQ_DCT_MAXTRUNC];
    1335             :     float tot_sig_ext[FDCNG_VQ_MAX_LEN];
    1336          75 :     invTrfMatrix = (float *) tmpRAM; /* dynamically filled  */
    1337             : 
    1338             :     /* set pointers and initialize */
    1339         225 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1340             :     {
    1341         150 :         sts[ch] = hCPE->hCoreCoder[ch];
    1342         150 :         N[ch] = sts[ch]->hFdCngEnc->npartDec;
    1343         150 :         lr_in_ptr[ch] = &sts[ch]->hFdCngEnc->msNoiseEst[0];
    1344         150 :         ms_ptr[ch] = &logNoiseEst[ch][0];
    1345         150 :         lr_out_ptr[ch] = &sts[ch]->hFdCngEnc->hFdCngCom->sidNoiseEst[0];
    1346             :     }
    1347          75 :     set_f( weights, 1.f, NPART );
    1348             : #ifdef DEBUGGING
    1349             :     assert( N[0] == N[1] );
    1350             : #endif
    1351             : 
    1352             :     /* apply log and save energy of original left and right channels */
    1353         225 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1354             :     {
    1355         150 :         E[ch] = 0.0f;
    1356        3750 :         for ( p = 0; p < N[ch]; p++ )
    1357             :         {
    1358        3600 :             ms_ptr[ch][p] = 10.f * log10f( lr_in_ptr[ch][p] + EPSILON );
    1359        3600 :             E[ch] += ms_ptr[ch][p];
    1360             :         }
    1361             :     }
    1362             : 
    1363             :     /* M/S transform on log envelopes */
    1364          75 :     convertToMS( N[0], ms_ptr[0], ms_ptr[1], 0.5f );
    1365             : 
    1366          75 :     E[0] = sum_f( ms_ptr[0], N[0] );
    1367             : 
    1368             :     /* Quantize M noise shape */
    1369             :     /* Normalize MSVQ input */
    1370          75 :     gain[0] = sum_f( ms_ptr[0] + N_GAIN_MIN, N_GAIN_MAX - N_GAIN_MIN );
    1371          75 :     gain[0] /= (float) ( N_GAIN_MAX - N_GAIN_MIN );
    1372             : 
    1373        1875 :     for ( p = 0; p < N[0]; p++ )
    1374             :     {
    1375        1800 :         ms_ptr[0][p] -= gain[0];
    1376             :     }
    1377             : 
    1378             :     /* MSVQ */
    1379             :     /* DCT domain compressed/truncated indices used for first stage  */
    1380             :     /*  mid quantization using stages #1 through 6 */
    1381          75 :     if ( N[0] == FDCNG_VQ_MAX_LEN_WB )
    1382             :     {
    1383           0 :         create_IDCT_N_Matrix( invTrfMatrix, N[0], FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) );
    1384             :         /* truncated DCT 21 analysis */
    1385           0 :         dctT2_N_apply_matrix( (const float *) ms_ptr[0], dct_target, FDCNG_VQ_DCT_MAXTRUNC, N[0], invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX );
    1386             :         /* truncated IDCT21 extension to 24 synthesis  */
    1387           0 :         extend_dctN_input( ms_ptr[0], dct_target, N[0], tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21 ); /* use 18 basis vectors*/
    1388             : 
    1389           0 :         mvr2r( tot_sig_ext, ms_ptr[0], FDCNG_VQ_MAX_LEN ); /*  write  extended result as input to  VQ stage #1 */
    1390             :     }
    1391          75 :     create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) );
    1392             : 
    1393          75 :     msvq_enc( cdk_37bits_ivas, NULL, NULL, ms_ptr[0], levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, weights, N[0], FD_CNG_maxN_37bits, 1, invTrfMatrix, indices[0] );
    1394          75 :     msvq_dec( cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N[0], FD_CNG_maxN_37bits, indices[0], 1, invTrfMatrix, ms_ptr[0], NULL );
    1395             : 
    1396             : 
    1397             :     /* set S to zero */
    1398          75 :     set_zero( ms_ptr[1], NPART );
    1399             : 
    1400             :     /* compute M gain */
    1401          75 :     gain[0] = sum_f( ms_ptr[0], N[0] );
    1402          75 :     gain[0] = ( E[0] - gain[0] ) / (float) N[0];
    1403          75 :     apply_scale( &gain[0], sts[0]->hFdCngEnc->hFdCngCom->CngBandwidth, sts[0]->hDtxEnc->last_active_brate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO );
    1404             : 
    1405             :     /* quantize gain */
    1406          75 :     gain_idx[0] = (int16_t) floor( gain[0] * 1.5f + GAIN_Q_OFFSET_IVAS + .5f );
    1407          75 :     gain_idx[0] = max( 0, min( 127, gain_idx[0] ) );
    1408             : 
    1409          75 :     gain[0] = ( (float) gain_idx[0] - GAIN_Q_OFFSET_IVAS ) / 1.5f;
    1410          75 :     gain[1] = gain[0];
    1411             : 
    1412             :     /* undo M/S */
    1413          75 :     convertToMS( NPART, ms_ptr[0], ms_ptr[1], 1.0f );
    1414             : 
    1415             :     /* restore channel noise envelopes */
    1416         225 :     for ( ch = 0; ch < CPE_CHANNELS; ch++ )
    1417             :     {
    1418         150 :         HANDLE_FD_CNG_ENC hFdCngEnc = sts[ch]->hFdCngEnc;
    1419         150 :         HANDLE_FD_CNG_COM hFdCngCom = hFdCngEnc->hFdCngCom;
    1420             : 
    1421        3750 :         for ( p = 0; p < N[0]; p++ )
    1422             :         {
    1423        3600 :             lr_out_ptr[ch][p] = powf( 10.f, ( ms_ptr[ch][p] + gain[ch] ) / 10.f );
    1424             :         }
    1425             : 
    1426             :         /* NB last band energy compensation */
    1427         150 :         if ( hFdCngCom->CngBandwidth == NB )
    1428             :         {
    1429           0 :             lr_out_ptr[ch][N[ch] - 1] *= NB_LAST_BAND_SCALE;
    1430             :         }
    1431         150 :         else if ( hFdCngCom->CngBandwidth == SWB && hFdCngCom->CngBitrate <= ACELP_13k20 )
    1432             :         {
    1433           0 :             lr_out_ptr[ch][N[ch] - 1] *= SWB_13k2_LAST_BAND_SCALE;
    1434             :         }
    1435             : 
    1436             :         /* scale bands and get scalefactors */
    1437         150 :         scalebands( lr_out_ptr[ch], hFdCngEnc->partDec, N[ch], hFdCngEnc->midbandDec, hFdCngEnc->nFFTpartDec, hFdCngEnc->stopBandDec - hFdCngEnc->startBandDec, hFdCngCom->cngNoiseLevel, 1 );
    1438             : 
    1439         150 :         lpc_from_spectrum( hFdCngCom, hFdCngEnc->startBandDec, hFdCngEnc->stopFFTbinDec, sts[ch]->preemph_fac );
    1440             : 
    1441         150 :         sts[ch]->hDtxEnc->last_CNG_L_frame = sts[ch]->L_frame;
    1442             :     }
    1443             : #ifdef NONBE_MDCT_ST_DTX_FIX_SUBOPT_SPATIAL_CNG
    1444          75 :     sts[0]->hFdCngEnc->hFdCngCom->coherence[0] = 0.0f;
    1445          75 :     sts[1]->hFdCngEnc->hFdCngCom->coherence[0] = 0.0f;
    1446             : #else
    1447             :     sts[0]->hFdCngEnc->hFdCngCom->coherence = 0.0f;
    1448             :     sts[1]->hFdCngEnc->hFdCngCom->coherence = 0.0f;
    1449             : #endif
    1450             : 
    1451             :     /* ---- Write SID bitstream ---- */
    1452             : 
    1453             :     /* side info */
    1454          75 :     push_indice( sts[0]->hBstr, IND_SID_TYPE, 1, 1 );
    1455          75 :     push_indice( sts[0]->hBstr, IND_BWIDTH, sts[0]->bwidth, 2 );
    1456          75 :     push_indice( sts[0]->hBstr, IND_ACELP_16KHZ, sts[0]->L_frame == L_FRAME16k ? 1 : 0, 1 );
    1457             : 
    1458             :     /* noise shapes and channel gains */
    1459         525 :     for ( int16_t i = 0; i < FD_CNG_stages_37bits; i++ )
    1460             :     {
    1461         450 :         push_indice( sts[0]->hBstr, IND_LSF, indices[0][i], bits_37bits[i] );
    1462             :     }
    1463          75 :     push_indice( sts[0]->hBstr, IND_ENERGY, gain_idx[0], 7 );
    1464             : 
    1465          75 :     return;
    1466             : }

Generated by: LCOV version 1.14