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

Generated by: LCOV version 1.14