LCOV - code coverage report
Current view: top level - lib_com - tcx_utils.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 6baab0c613aa6c7100498ed7b93676aa8198a493 Lines: 296 313 94.6 %
Date: 2025-05-29 08:28:55 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 <assert.h>
      38             : #include <stdint.h>
      39             : #include "options.h"
      40             : #ifdef DEBUGGING
      41             : #include "debug.h"
      42             : #endif
      43             : #include <math.h>
      44             : #include "cnst.h"
      45             : #include "rom_com.h"
      46             : #include "prot.h"
      47             : #include "wmc_auto.h"
      48             : 
      49             : /*-------------------------------------------------------------------*
      50             :  * tcx_get_windows()
      51             :  *
      52             :  *
      53             :  *-------------------------------------------------------------------*/
      54     5966329 : void tcx_get_windows(
      55             :     TCX_CONFIG_HANDLE hTcxCfg, /* i  : TCX configuration                   */
      56             :     const int16_t left_mode,   /* i  : overlap mode of left window half    */
      57             :     const int16_t right_mode,  /* i  : overlap mode of right window half   */
      58             :     int16_t *left_overlap,     /* o  : left overlap length                 */
      59             :     const float **left_win,    /* o  : left overlap window                 */
      60             :     int16_t *right_overlap,    /* o  : right overlap length                */
      61             :     const float **right_win,   /* o  : right overlap window                */
      62             :     const int16_t fullband     /* i  : fullband flag                       */
      63             : )
      64             : {
      65     5966329 :     if ( !fullband )
      66             :     {
      67             :         /* Left part */
      68             : 
      69      900008 :         if ( left_mode == TRANSITION_OVERLAP )
      70             :         {
      71             :             /* ACELP->TCX transition */
      72        3801 :             *left_overlap = hTcxCfg->tcx_mdct_window_trans_length;
      73        3801 :             *left_win = hTcxCfg->tcx_mdct_window_trans;
      74             :         }
      75      896207 :         else if ( left_mode == MIN_OVERLAP )
      76             :         {
      77       13933 :             *left_overlap = hTcxCfg->tcx_mdct_window_min_length;
      78       13933 :             *left_win = hTcxCfg->tcx_mdct_window_minimum;
      79             :         }
      80      882274 :         else if ( left_mode == HALF_OVERLAP )
      81             :         {
      82        8195 :             *left_overlap = hTcxCfg->tcx_mdct_window_half_length;
      83        8195 :             *left_win = hTcxCfg->tcx_mdct_window_half;
      84             :         }
      85      874079 :         else if ( left_mode == FULL_OVERLAP )
      86             :         {
      87      874079 :             *left_overlap = hTcxCfg->tcx_mdct_window_length;
      88      874079 :             *left_win = hTcxCfg->tcx_aldo_window_1_trunc;
      89             :         }
      90             :         else
      91             :         {
      92           0 :             assert( !"Not supported overlap" );
      93             :         }
      94             : 
      95             :         /* Right part */
      96             : 
      97      900008 :         if ( right_mode == MIN_OVERLAP )
      98             :         {
      99       14049 :             *right_overlap = hTcxCfg->tcx_mdct_window_min_length;
     100       14049 :             *right_win = hTcxCfg->tcx_mdct_window_minimum;
     101             :         }
     102      885959 :         else if ( right_mode == HALF_OVERLAP )
     103             :         {
     104        8478 :             *right_overlap = hTcxCfg->tcx_mdct_window_half_length;
     105        8478 :             *right_win = hTcxCfg->tcx_mdct_window_half;
     106             :         }
     107      877481 :         else if ( right_mode == FULL_OVERLAP )
     108             :         {
     109      877481 :             *right_overlap = hTcxCfg->tcx_mdct_window_delay;
     110      877481 :             *right_win = hTcxCfg->tcx_aldo_window_2;
     111             :         }
     112             :         else
     113             :         {
     114           0 :             assert( !"Not supported overlap" );
     115             :         }
     116             :     }
     117             :     else
     118             :     {
     119             :         /* Left part */
     120             : 
     121     5066321 :         if ( left_mode == TRANSITION_OVERLAP )
     122             :         {
     123             :             /* ACELP->TCX transition */
     124      131163 :             *left_overlap = hTcxCfg->tcx_mdct_window_trans_lengthFB;
     125      131163 :             *left_win = hTcxCfg->tcx_mdct_window_transFB;
     126             :         }
     127     4935158 :         else if ( left_mode == MIN_OVERLAP )
     128             :         {
     129      887976 :             *left_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
     130      887976 :             *left_win = hTcxCfg->tcx_mdct_window_minimumFB;
     131             :         }
     132     4047182 :         else if ( left_mode == HALF_OVERLAP )
     133             :         {
     134      193471 :             *left_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
     135      193471 :             *left_win = hTcxCfg->tcx_mdct_window_halfFB;
     136             :         }
     137     3853711 :         else if ( left_mode == RECTANGULAR_OVERLAP )
     138             :         {
     139      494649 :             *left_overlap = 0;
     140      494649 :             *left_win = NULL;
     141             :         }
     142     3359062 :         else if ( left_mode == FULL_OVERLAP )
     143             :         {
     144     3359062 :             *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB;
     145     3359062 :             *left_win = hTcxCfg->tcx_aldo_window_1_FB_trunc;
     146             :         }
     147             :         else
     148             :         {
     149           0 :             assert( !"Not supported overlap" );
     150             :         }
     151             : 
     152             :         /* Right part */
     153             : 
     154     5066321 :         if ( right_mode == MIN_OVERLAP )
     155             :         {
     156      934101 :             *right_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
     157      934101 :             *right_win = hTcxCfg->tcx_mdct_window_minimumFB;
     158             :         }
     159     4132220 :         else if ( right_mode == HALF_OVERLAP )
     160             :         {
     161      240116 :             *right_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
     162      240116 :             *right_win = hTcxCfg->tcx_mdct_window_halfFB;
     163             :         }
     164     3892104 :         else if ( right_mode == RECTANGULAR_OVERLAP )
     165             :         {
     166      494555 :             *right_overlap = 0;
     167      494555 :             *right_win = NULL;
     168             :         }
     169     3397549 :         else if ( right_mode == FULL_OVERLAP )
     170             :         {
     171     3397549 :             *right_overlap = hTcxCfg->tcx_mdct_window_delayFB;
     172     3397549 :             *right_win = hTcxCfg->tcx_aldo_window_2_FB;
     173             :         }
     174             :         else
     175             :         {
     176           0 :             assert( !"Not supported overlap" );
     177             :         }
     178             :     }
     179             : 
     180     5966329 :     return;
     181             : }
     182             : 
     183             : /*-------------------------------------------------------------------*
     184             :  * tcx_windowing_analysis()
     185             :  *
     186             :  *
     187             :  *-------------------------------------------------------------------*/
     188             : 
     189     5966127 : void tcx_windowing_analysis(
     190             :     const float *signal,         /* i  : signal vector               */
     191             :     const int16_t L_frame,       /* i  : frame length                */
     192             :     const int16_t left_overlap,  /* i  : left overlap length         */
     193             :     const float *left_win,       /* i  : left overlap window         */
     194             :     const int16_t right_overlap, /* i  : right overlap length        */
     195             :     const float *right_win,      /* i  : right overlap window        */
     196             :     float *output                /* o  : windowed signal vector      */
     197             : )
     198             : {
     199             :     int16_t w;
     200             : 
     201             :     /* Left overlap */
     202  1570508365 :     for ( w = 0; w < left_overlap; w++ )
     203             :     {
     204  1564542238 :         *output++ = *signal++ * left_win[w];
     205             :     }
     206             : 
     207             :     /* Non overlapping region */
     208  2260561427 :     for ( w = 0; w < L_frame - ( left_overlap + right_overlap ) / 2; w++ )
     209             :     {
     210  2254595300 :         *output++ = *signal++;
     211             :     }
     212             : 
     213             :     /* Right overlap */
     214  1590396793 :     for ( w = 0; w < right_overlap; w++ )
     215             :     {
     216  1584430666 :         *output++ = *signal++ * right_win[right_overlap - 1 - w];
     217             :     }
     218             : 
     219     5966127 :     return;
     220             : }
     221             : 
     222             : 
     223             : /*-------------------------------------------------------------------*
     224             :  * WindowSignal()
     225             :  *
     226             :  *
     227             :  *-------------------------------------------------------------------*/
     228             : 
     229     5966127 : void WindowSignal(
     230             :     TCX_CONFIG_HANDLE hTcxCfg,        /* i  : configuration of TCX                */
     231             :     int16_t offset,                   /* i  : left folding point offset relative to the input signal pointer */
     232             :     const int16_t left_overlap_mode,  /* i  : overlap mode of left window half    */
     233             :     const int16_t right_overlap_mode, /* i  : overlap mode of right window half   */
     234             :     int16_t *left_overlap_length,     /* o  : TCX window left overlap length      */
     235             :     int16_t *right_overlap_length,    /* o  : TCX window right overlap length     */
     236             :     const float in[],                 /* i  : input signal                        */
     237             :     int16_t *L_frame,                 /* i/o: frame length                        */
     238             :     float out[],                      /* o  : output windowed signal              */
     239             :     const int16_t truncate_aldo,      /* i  : nonzero to truncate long ALDO slope */
     240             :     const int16_t fullband            /* i  : fullband flag                       */
     241             : )
     242             : {
     243             :     int16_t l, r;
     244             :     const float *left_win;
     245             :     const float *right_win;
     246             : 
     247             :     /*-----------------------------------------------------------*
     248             :      * Init                                                      *
     249             :      *-----------------------------------------------------------*/
     250             : 
     251     5966127 :     tcx_get_windows( hTcxCfg, left_overlap_mode, right_overlap_mode, &l, &left_win, &r, &right_win, fullband );
     252             : 
     253             :     /* Init lengths */
     254             : 
     255             :     /* if past frame is ACELP */
     256     5966127 :     if ( left_overlap_mode == TRANSITION_OVERLAP )
     257             :     {
     258             :         /* Increase frame size for 5ms */
     259      134964 :         if ( !fullband )
     260             :         {
     261        3801 :             *L_frame += hTcxCfg->tcx5Size;
     262        3801 :             offset = -hTcxCfg->tcx_mdct_window_trans_length / 2;
     263             :         }
     264             :         else
     265             :         {
     266      131163 :             *L_frame += hTcxCfg->tcx5SizeFB;
     267      131163 :             offset = -hTcxCfg->tcx_mdct_window_trans_lengthFB / 2;
     268             :         }
     269             :     }
     270             : 
     271             :     /*-----------------------------------------------------------*
     272             :      * Windowing                                                 *
     273             :      *-----------------------------------------------------------*/
     274             : 
     275     5966127 :     tcx_windowing_analysis( in - l / 2 + offset, *L_frame, l, left_win, r, right_win, out );
     276             : 
     277     5966127 :     if ( left_overlap_mode == FULL_OVERLAP && truncate_aldo )
     278             :     {
     279             :         /* fade truncated ALDO window to avoid discontinuities */
     280     3861010 :         if ( !fullband )
     281             :         {
     282      874079 :             v_mult( out, hTcxCfg->tcx_mdct_window_minimum, out, hTcxCfg->tcx_mdct_window_min_length );
     283             :         }
     284             :         else
     285             :         {
     286     2986931 :             v_mult( out, hTcxCfg->tcx_mdct_window_minimumFB, out, hTcxCfg->tcx_mdct_window_min_lengthFB );
     287             :         }
     288             :     }
     289             : 
     290     5966127 :     *left_overlap_length = l;
     291     5966127 :     *right_overlap_length = r;
     292             : 
     293     5966127 :     return;
     294             : }
     295             : 
     296             : 
     297             : /*-------------------------------------------------------------------*
     298             :  * tcx_windowing_synthesis_current_frame()
     299             :  *
     300             :  *
     301             :  *-------------------------------------------------------------------*/
     302             : 
     303     4441270 : void tcx_windowing_synthesis_current_frame(
     304             :     float *signal,                    /* i/o: signal vector                             */
     305             :     const float *window,              /* i  : TCX window vector                         */
     306             :     const float *window_half,         /* i  : TCX window vector for half-overlap window */
     307             :     const float *window_min,          /* i  : TCX minimum overlap window                */
     308             :     const int16_t window_length,      /* i  : TCX window length                         */
     309             :     const int16_t window_half_length, /* i  : TCX half window length                    */
     310             :     const int16_t window_min_length,  /* i  : TCX minimum overlap length                */
     311             :     const int16_t left_rect,          /* i  : left part is rectangular                  */
     312             :     const int16_t left_mode,          /* i  : overlap mode of left window half          */
     313             :     float *acelp_zir,                 /* i/o: acelp ZIR                                 */
     314             :     const float *old_syn,             /* i  : old synthesis                             */
     315             :     const float *syn_overl,           /* i  : overlap synthesis                         */
     316             :     const float *A_zir,
     317             :     const float *window_trans,
     318             :     int16_t acelp_zir_len,
     319             :     const int16_t acelp_mem_len,
     320             :     const int16_t last_core_bfi, /* i  : last mode                                 */
     321             :     const int16_t last_is_cng,
     322             :     const int16_t fullbandScale )
     323             : {
     324             :     int16_t i, w, overlap;
     325             :     float tmp[L_FRAME_MAX / 2];
     326             : 
     327             :     /* Init */
     328     4441270 :     overlap = window_length >> 1;
     329             : 
     330             :     /* Past-frame is TCX concealed as CNG and current-frame is TCX */
     331     4441270 :     if ( last_is_cng == 1 && left_rect == 0 )
     332             :     {
     333           0 :         if ( !fullbandScale )
     334             :         {
     335           0 :             set_zero( acelp_zir, acelp_zir_len );
     336           0 :             syn_filt( A_zir, M, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0 );
     337             :         }
     338             :         else
     339             :         {
     340           0 :             lerp( acelp_zir, tmp, acelp_zir_len, acelp_zir_len * FSCALE_DENOM / fullbandScale );
     341           0 :             acelp_zir = tmp;
     342             :         }
     343             : 
     344           0 :         for ( i = 0; i < acelp_zir_len; i++ )
     345             :         {
     346           0 :             signal[i] *= (float) ( i ) / (float) ( acelp_zir_len );
     347           0 :             signal[i] += acelp_zir[i] * (float) ( acelp_zir_len - i ) / (float) ( acelp_zir_len );
     348             :         }
     349             :     }
     350     4441270 :     else if ( left_rect == 1 && last_core_bfi == ACELP_CORE ) /* Rectangular window (past-frame is ACELP) */
     351             :     {
     352    48916633 :         for ( i = 0; i < overlap - acelp_mem_len; i++ )
     353             :         {
     354    48402330 :             signal[i] = 0;
     355             :         }
     356             : 
     357      514303 :         if ( fullbandScale == 0 )
     358             :         {
     359             :             /*OLA with ACELP*/
     360     6433267 :             for ( i = 0; i < 2 * acelp_mem_len; i++ )
     361             :             {
     362             :                 /*window decoded TCX with aliasing*/
     363     6131840 :                 signal[i + overlap - acelp_mem_len] *= window_trans[i];
     364             :                 /*Time TDAC: 1)forward part of ACELP*/
     365     6131840 :                 signal[i + overlap - acelp_mem_len] += old_syn[acelp_zir_len - 2 * acelp_mem_len + i] * window_trans[2 * acelp_mem_len - i - 1] * window_trans[2 * acelp_mem_len - i - 1];
     366             : 
     367             :                 /*Time TDAC: 1)reward part of ACELP*/
     368     6131840 :                 signal[i + overlap - acelp_mem_len] += old_syn[acelp_zir_len - i - 1] * window_trans[i] * window_trans[2 * acelp_mem_len - i - 1];
     369             :             }
     370             : 
     371     5124259 :             for ( i = 0; i < M; i++ )
     372             :             {
     373     4822832 :                 signal[overlap + acelp_mem_len - M + i] -= old_syn[acelp_zir_len - M + i];
     374             :             }
     375             :         }
     376             : 
     377             :         /* ZIR at the end of the ACELP frame */
     378      514303 :         acelp_zir_len = 64;
     379             : 
     380      514303 :         if ( !fullbandScale )
     381             :         {
     382      301427 :             set_zero( acelp_zir, acelp_zir_len );
     383      301427 :             syn_filt( A_zir, M, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0 );
     384             :         }
     385             :         else
     386             :         {
     387      212876 :             lerp( acelp_zir, tmp, acelp_zir_len * fullbandScale / FSCALE_DENOM, acelp_zir_len );
     388      212876 :             acelp_zir_len = acelp_zir_len * fullbandScale / FSCALE_DENOM;
     389      212876 :             acelp_zir = tmp;
     390             : 
     391      212876 :             if ( acelp_zir_len >= 2.0f * 64 )
     392             :             {
     393             :                 /* apply a simple low-pass to the ZIR, to avoid potentially unmasked HF content */
     394    26693798 :                 for ( i = 2; i < acelp_zir_len; i++ )
     395             :                 {
     396    26548796 :                     acelp_zir[i] = 0.25f * acelp_zir[i - 2] + 0.35f * acelp_zir[i - 1] + 0.40f * acelp_zir[i];
     397             :                 }
     398      145002 :                 acelp_zir[acelp_zir_len - 1] = 0.40f * acelp_zir[acelp_zir_len - 1] + 0.35f * acelp_zir[acelp_zir_len - 1] + 0.25f * acelp_zir[acelp_zir_len - 2];
     399      145002 :                 acelp_zir[acelp_zir_len - 2] = 0.40f * acelp_zir[acelp_zir_len - 2] + 0.35f * acelp_zir[acelp_zir_len - 1] + 0.25f * acelp_zir[acelp_zir_len - 1];
     400    26693798 :                 for ( i = acelp_zir_len - 3; i >= 0; i-- )
     401             :                 {
     402    26548796 :                     acelp_zir[i] = 0.40f * acelp_zir[i] + 0.35f * acelp_zir[i + 1] + 0.25f * acelp_zir[i + 2];
     403             :                 }
     404             :             }
     405             :         }
     406             : 
     407    52239879 :         for ( i = 0; i < acelp_zir_len; i++ )
     408             :         {
     409             :             /*remove reconstructed ZIR and add ACELP ZIR*/
     410    51725576 :             signal[i + overlap + acelp_mem_len] -= acelp_zir[i] * (float) ( acelp_zir_len - i ) / (float) acelp_zir_len;
     411             :         }
     412             :     }
     413     3926967 :     else if ( left_rect == 1 && last_core_bfi != 0 ) /* Rectangular window (past-frame is TCX) */
     414             :     {
     415     5653966 :         for ( i = 0; i < overlap + acelp_mem_len; i++ )
     416             :         {
     417     5611552 :             signal[i] = 0;
     418             :         }
     419     9862630 :         for ( i = 0; i < window_length; i++ )
     420             :         {
     421     9820216 :             signal[i + overlap + acelp_mem_len] *= window[i];
     422             :         }
     423             :     }
     424     3884553 :     else if ( left_rect != 1 && last_core_bfi == 0 ) /* Normal window (past-frame is ACELP) */
     425             :     {
     426      506454 :         for ( i = 0; i < window_length; i++ )
     427             :         {
     428      504476 :             signal[i] *= window[i];
     429             :         }
     430             : 
     431      506454 :         for ( i = 0; i < window_length; i++ )
     432             :         {
     433      504476 :             signal[i] += syn_overl[i];
     434             :         }
     435             :     }
     436             :     else /* Normal window (past-frame is TCX) */
     437             :     {
     438     3882575 :         if ( left_mode == 2 )
     439             :         {
     440             :             /* min. overlap */
     441   102380535 :             for ( i = 0; i < ( window_length - window_min_length ) / 2; i++ )
     442             :             {
     443   100069012 :                 signal[i] = 0.0f;
     444             :             }
     445    91478711 :             for ( w = 0; w < window_min_length; i++, w++ )
     446             :             {
     447    89167188 :                 signal[i] *= window_min[w];
     448             :             }
     449             :         }
     450     1571052 :         else if ( left_mode == 3 )
     451             :         {
     452             :             /* half OL */
     453     6191625 :             for ( i = 0; i < ( window_length - window_half_length ) / 2; i++ )
     454             :             {
     455     5735104 :                 signal[i] = 0.0f;
     456             :             }
     457    52845905 :             for ( w = 0; w < window_half_length; i++, w++ )
     458             :             {
     459    52389384 :                 signal[i] *= window_half[w];
     460             :             }
     461             :         }
     462             :         else
     463             :         {
     464             :             /* normal full/maximum overlap */
     465   298973631 :             for ( i = 0; i < window_length; i++ )
     466             :             {
     467   297859100 :                 signal[i] *= window[i];
     468             :             }
     469             :         }
     470             :     }
     471             : 
     472     4441270 :     return;
     473             : }
     474             : 
     475             : 
     476             : /*-------------------------------------------------------------------*
     477             :  * tcx_windowing_synthesis_past_frame()
     478             :  *
     479             :  *
     480             :  *-------------------------------------------------------------------*/
     481             : 
     482     4488510 : void tcx_windowing_synthesis_past_frame(
     483             :     float *signal,                    /* i/o: signal vector                              */
     484             :     const float *window,              /* i  : TCX window vector                          */
     485             :     const float *window_half,         /* i  : TCX window vector for half-overlap window  */
     486             :     const float *window_min,          /* i  : TCX minimum overlap window                 */
     487             :     const int16_t window_length,      /* i  : TCX window length                          */
     488             :     const int16_t window_half_length, /* i  : TCX half window length                     */
     489             :     const int16_t window_min_length,  /* i  : TCX minimum overlap length                 */
     490             :     const int16_t right_mode          /* i  : overlap mode (left_mode of current frame)  */
     491             : )
     492             : {
     493             :     int16_t i, w;
     494             : 
     495     4488510 :     if ( right_mode == MIN_OVERLAP )
     496             :     {
     497             :         /* min. overlap */
     498    96245248 :         for ( i = ( window_length - window_min_length ) / 2, w = 0; w < window_min_length; i++, w++ )
     499             :         {
     500    93811508 :             signal[i] *= window_min[window_min_length - 1 - w];
     501             :         }
     502   146725672 :         for ( ; i < window_length; i++ )
     503             :         {
     504   144291932 :             signal[i] = 0.0f;
     505             :         }
     506             :     }
     507     2054770 :     else if ( right_mode == HALF_OVERLAP )
     508             :     {
     509             :         /* half OL */
     510    76366646 :         for ( i = ( window_length - window_half_length ) / 2, w = 0; w < window_half_length; i++, w++ )
     511             :         {
     512    75692040 :             signal[i] *= window_half[window_half_length - 1 - w];
     513             :         }
     514    51135966 :         for ( ; i < window_length; i++ )
     515             :         {
     516    50461360 :             signal[i] = 0.0f;
     517             :         }
     518             :     }
     519     1380164 :     else if ( right_mode == FULL_OVERLAP )
     520             :     {
     521             :         /* normal full/maximum overlap */
     522   348221010 :         for ( i = 0; i < window_length; i++ )
     523             :         {
     524   346841194 :             signal[i] *= window[window_length - 1 - i];
     525             :         }
     526             :     }
     527             : 
     528     4488510 :     return;
     529             : }
     530             : 
     531             : 
     532             : /*-------------------------------------------------------------------*
     533             :  * lpc2mdct()
     534             :  *
     535             :  *
     536             :  *-------------------------------------------------------------------*/
     537             : 
     538    12831180 : void lpc2mdct(
     539             :     float *lpcCoeffs,
     540             :     const int16_t lpcOrder,
     541             :     float mdct_gains[],
     542             :     const int16_t length,
     543             :     const int16_t noInverse )
     544             : {
     545             :     float RealData[2 * FDNS_NPTS], ImagData[2 * FDNS_NPTS];
     546             :     float tmp;
     547             :     int16_t i, sizeN;
     548             : 
     549    12831180 :     assert( length <= FDNS_NPTS );
     550             : 
     551    12831180 :     sizeN = 2 * length;
     552             : 
     553             :     /* ODFT */
     554   230961240 :     for ( i = 0; i < lpcOrder + 1; i++ )
     555             :     {
     556   218130060 :         tmp = (float) ( ( (float) i ) * EVS_PI / (float) ( sizeN ) );
     557   218130060 :         RealData[i] = (float) ( lpcCoeffs[i] * cos( tmp ) );
     558   218130060 :         ImagData[i] = (float) ( -lpcCoeffs[i] * sin( tmp ) );
     559             :     }
     560             : 
     561  1437092160 :     for ( ; i < sizeN; i++ )
     562             :     {
     563  1424260980 :         RealData[i] = 0.f;
     564  1424260980 :         ImagData[i] = 0.f;
     565             :     }
     566             : 
     567    12831180 :     DoFFT( RealData, ImagData, sizeN );
     568             : 
     569    12831180 :     if ( noInverse )
     570             :     {
     571           0 :         for ( i = 0; i < length; i++ )
     572             :         {
     573           0 :             mdct_gains[i] = (float) ( sqrt( RealData[i] * RealData[i] + ImagData[i] * ImagData[i] ) );
     574             :         }
     575             :     }
     576             :     else
     577             :     /* Get amplitude */
     578             :     {
     579   834026700 :         for ( i = 0; i < length; i++ )
     580             :         {
     581   821195520 :             mdct_gains[i] = (float) ( 1.0f / max( EPSILON, sqrt( RealData[i] * RealData[i] + ImagData[i] * ImagData[i] ) ) );
     582             :         }
     583             :     }
     584             : 
     585    12831180 :     return;
     586             : }
     587             : 
     588             : 
     589             : /*-------------------------------------------------------------------*
     590             :  * mdct_noiseShaping()
     591             :  *
     592             :  *
     593             :  *-------------------------------------------------------------------*/
     594             : 
     595    12336245 : void mdct_noiseShaping(
     596             :     float x[],
     597             :     const int16_t lg,
     598             :     const float gains[],
     599             :     const int16_t nBands )
     600             : {
     601             :     int16_t i, j, k, l;
     602             :     float g;
     603             :     int16_t m, n, k1, k2;
     604             : 
     605    12336245 :     j = 0;
     606    12336245 :     assert( nBands != 0 );
     607    12336245 :     k = lg / nBands;
     608    12336245 :     m = lg % nBands;
     609             : 
     610    12336245 :     if ( m )
     611             :     {
     612      218703 :         if ( m <= ( FDNS_NPTS / 2 ) )
     613             :         {
     614      218703 :             n = FDNS_NPTS / m;
     615      218703 :             k1 = k;
     616      218703 :             k2 = k + 1;
     617             :         }
     618             :         else
     619             :         {
     620           0 :             n = FDNS_NPTS / ( FDNS_NPTS - m );
     621           0 :             k1 = k + 1;
     622           0 :             k2 = k;
     623             :         }
     624             : 
     625    14215695 :         for ( i = 0; i < lg; )
     626             :         {
     627    13996992 :             if ( j % n )
     628             :             {
     629     9889360 :                 k = k1;
     630             :             }
     631             :             else
     632             :             {
     633     4107632 :                 k = k2;
     634             :             }
     635    13996992 :             g = gains[j++];
     636             : 
     637             :             /* Limit number of loops, if end is reached */
     638    13996992 :             k = min( k, lg - i );
     639             : 
     640    96193712 :             for ( l = 0; l < k; l++ )
     641             :             {
     642    82196720 :                 x[i++] *= g;
     643             :             }
     644             :         }
     645             :     }
     646             :     else
     647             :     {
     648   787640230 :         for ( i = 0; i < lg; )
     649             :         {
     650   775522688 :             g = gains[j++];
     651             : 
     652  5219942336 :             for ( l = 0; l < k; l++ )
     653             :             {
     654  4444419648 :                 x[i++] *= g;
     655             :             }
     656             :         }
     657             :     }
     658             : 
     659    12336245 :     return;
     660             : }
     661             : 
     662             : 
     663             : /*-------------------------------------------------------------------*
     664             :  * PsychAdaptLowFreqDeemph()
     665             :  *
     666             :  *
     667             :  *-------------------------------------------------------------------*/
     668             : 
     669     1016200 : void PsychAdaptLowFreqDeemph(
     670             :     float x[],
     671             :     const float lpcGains[],
     672             :     float lf_deemph_factors[] )
     673             : {
     674             :     int16_t i;
     675             :     float max_val, fac, tmp;
     676             : 
     677     1016200 :     max_val = tmp = lpcGains[0];
     678             : 
     679             :     /* find minimum (tmp) and maximum (max) of LPC gains in low frequencies */
     680     9145800 :     for ( i = 1; i < 9; i++ )
     681             :     {
     682     8129600 :         if ( tmp > lpcGains[i] )
     683             :         {
     684     5322166 :             tmp = lpcGains[i];
     685             :         }
     686     8129600 :         if ( max_val < lpcGains[i] )
     687             :         {
     688     1968201 :             max_val = lpcGains[i];
     689             :         }
     690             :     }
     691             : 
     692     1016200 :     tmp *= 32.0f;
     693             : 
     694     1016200 :     if ( ( max_val < tmp ) && ( tmp > FLT_MIN ) )
     695             :     {
     696     1013912 :         fac = tmp = (float) pow( max_val / tmp, 0.0078125f );
     697             : 
     698     1013912 :         if ( lf_deemph_factors )
     699             :         {
     700             :             /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
     701    20958003 :             for ( i = 31; i >= 0; i-- )
     702             :             {
     703    20322912 :                 x[i] *= fac;
     704    20322912 :                 lf_deemph_factors[i] *= fac;
     705    20322912 :                 fac *= tmp;
     706             :             }
     707             :         }
     708             :         else
     709             :         {
     710             :             /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
     711    12501093 :             for ( i = 31; i >= 0; i-- )
     712             :             {
     713    12122272 :                 x[i] *= fac;
     714    12122272 :                 fac *= tmp;
     715             :             }
     716             :         }
     717             :     }
     718             : 
     719     1016200 :     return;
     720             : }
     721             : 
     722             : 
     723             : /*-------------------------------------------------------------------*
     724             :  * AdaptLowFreqDeemph()
     725             :  *
     726             :  *
     727             :  *-------------------------------------------------------------------*/
     728             : 
     729     5683578 : void AdaptLowFreqDeemph(
     730             :     float x[],
     731             :     int16_t tcx_lpc_shaped_ari,
     732             :     const float lpcGains[],
     733             :     const int16_t lg,
     734             :     float lf_deemph_factors[] )
     735             : {
     736             :     int16_t i, i_max_old, i_max;
     737             : 
     738     5683578 :     if ( !tcx_lpc_shaped_ari )
     739             :     {
     740             :         /* 1. find first magnitude maximum in lower quarter of spectrum */
     741     5048487 :         i_max = -1;
     742             : 
     743    57194899 :         for ( i = 0; i < lg / 4; i++ )
     744             :         {
     745    56665287 :             if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
     746             :             {
     747     4518875 :                 x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
     748     4518875 :                 i_max = i;
     749     4518875 :                 break;
     750             :             }
     751             :         }
     752             :         /* 2. expand value range of all xi up to i_max: two extra steps */
     753             : 
     754    16710507 :         for ( i = 0; i < i_max; i++ )
     755             :         {
     756    11662020 :             x[i] *= 0.5f;
     757    11662020 :             lf_deemph_factors[i] *= 0.5f;
     758             :         }
     759             :         /* 3. find first magnitude maximum in lower quarter of spectrum */
     760     5048487 :         i_max_old = i_max;
     761             : 
     762     5048487 :         if ( i_max_old > -1 )
     763             :         {
     764     4518875 :             i_max = -1;
     765             : 
     766    23830522 :             for ( i = 0; i < lg / 4; i++ )
     767             :             {
     768    23825291 :                 if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
     769             :                 {
     770     4513644 :                     x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
     771     4513644 :                     i_max = i;
     772     4513644 :                     break;
     773             :                 }
     774             :             }
     775             :         }
     776             :         /* 4. expand value range of all xi up to i_max: two extra steps */
     777    23984562 :         for ( i = 0; i < i_max; i++ )
     778             :         {
     779    18936075 :             x[i] *= 0.5f;
     780    18936075 :             lf_deemph_factors[i] *= 0.5f;
     781             :         }
     782             :         /* 5. always expand two lines; lines could be at index 0 and 1! */
     783     5048487 :         if ( i_max < i_max_old )
     784             :         {
     785        5231 :             i_max = i_max_old;
     786             :         }
     787     5048487 :         i = i_max + 1;
     788     5048487 :         if ( x[i] < 0.0f )
     789             :         {
     790     2056842 :             if ( x[i] > -4.0f )
     791             :             {
     792      745683 :                 lf_deemph_factors[i] *= 0.5f;
     793             :             }
     794     2056842 :             x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
     795             :         }
     796             :         else
     797             :         {
     798     2991645 :             if ( x[i] < 4.0f )
     799             :             {
     800     1619433 :                 lf_deemph_factors[i] *= 0.5f;
     801             :             }
     802     2991645 :             x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
     803             :         }
     804     5048487 :         i++;
     805     5048487 :         if ( x[i] < 0.0f )
     806             :         {
     807     2027835 :             if ( x[i] > -4.0f )
     808             :             {
     809      857667 :                 lf_deemph_factors[i] *= 0.5f;
     810             :             }
     811     2027835 :             x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
     812             :         }
     813             :         else
     814             :         {
     815     3020652 :             if ( x[i] < 4.0f )
     816             :             {
     817     1882565 :                 lf_deemph_factors[i] *= 0.5f;
     818             :             }
     819     3020652 :             x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
     820             :         }
     821             :     }
     822             :     else
     823             :     {
     824      635091 :         PsychAdaptLowFreqDeemph( x, lpcGains, lf_deemph_factors );
     825             :     }
     826             : 
     827     5683578 :     return;
     828             : }
     829             : 
     830             : 
     831             : /*-------------------------------------------------------------------*
     832             :  * tcx_noise_filling()
     833             :  *
     834             :  *
     835             :  *-------------------------------------------------------------------*/
     836             : 
     837    27868732 : void tcx_noise_filling(
     838             :     float *Q,
     839             :     const int16_t noiseFillSeed,
     840             :     const int16_t iFirstLine,
     841             :     const int16_t lowpassLine,
     842             :     const int16_t nTransWidth,
     843             :     const int16_t L_frame,
     844             :     const float tiltCompFactor,
     845             :     float fac_ns,
     846             :     uint8_t *infoTCXNoise,
     847             :     const int16_t element_mode /* i  : IVAS element mode                         */
     848             : )
     849             : {
     850             :     int16_t i, m, segmentOffset;
     851             :     int16_t win; /* window coefficient */
     852             :     Word16 seed;
     853             :     float tilt_factor, nrg, tmp1, tmp2;
     854             : 
     855             :     /* 16-bit random number generator seed for generating filled lines */
     856    27868732 :     seed = (Word16) noiseFillSeed;
     857             : 
     858    27868732 :     tilt_factor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / (float) L_frame );
     859    27868732 :     fac_ns /= (float) ( nTransWidth * nTransWidth );
     860             : 
     861             :     /* find last nonzero line below iFirstLine, use it as start offset */
     862    27868732 :     i = iFirstLine;
     863             : 
     864    27868732 :     if ( element_mode == IVAS_CPE_MDCT ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
     865             :     {
     866    20369123 :         segmentOffset = i;
     867             :     }
     868             :     else
     869             :     {
     870    26980596 :         for ( ; i > ( iFirstLine >> 1 ); i-- )
     871             :         {
     872    26853503 :             if ( Q[i] != 0.0f )
     873             :             {
     874     7372516 :                 break;
     875             :             }
     876             :         }
     877             : 
     878     7499609 :         fac_ns *= (float) pow( tilt_factor, (float) i );
     879     7499609 :         segmentOffset = ++i;
     880             :     }
     881             : 
     882    27868732 :     nrg = 1e-9f;
     883    27868732 :     win = 0;
     884             : 
     885 10998859389 :     for ( ; i < lowpassLine; i++ )
     886             :     {
     887 10970990657 :         fac_ns *= tilt_factor;
     888             : 
     889 10970990657 :         if ( Q[i] != 0.0f )
     890             :         {
     891  2720026172 :             if ( win > 0 )
     892             :             {
     893             :                 /* RMS-normalize current noise-filled segment */
     894  1192445616 :                 tmp1 = (float) sqrt( ( i - segmentOffset ) / nrg );
     895  1192445616 :                 tmp2 = tmp1 * (float) nTransWidth;
     896             : 
     897  3296479627 :                 for ( m = segmentOffset; m < i - win; m++ )
     898             :                 {
     899  2104034011 :                     Q[m] *= tmp2;
     900             :                 }
     901             : 
     902  4591688213 :                 for ( ; win > 0; win-- )
     903             :                 {
     904  3399242597 :                     Q[m++] *= tmp1 * (float) win;
     905             :                 }
     906  1192445616 :                 nrg = 1e-9f; /* start new segment: reset noise segment energy */
     907             :             }
     908  2720026172 :             segmentOffset = i + 1;
     909             :         }
     910             :         else
     911             :         {
     912             :             /* line is zero, so fill line and update window and energy */
     913  8250964485 :             if ( win < nTransWidth )
     914             :             {
     915  3560830538 :                 win++;
     916             :             }
     917  8250964485 :             tmp1 = (float) own_random( &seed );
     918  8250964485 :             nrg += tmp1 * tmp1; /* sum up energy of current noise segment */
     919  8250964485 :             Q[i] = tmp1 * (float) win * fac_ns;
     920             : 
     921  8250964485 :             if ( infoTCXNoise )
     922             :             {
     923             :                 /* set noiseflags for IGF */
     924  4176407131 :                 infoTCXNoise[i] = 1;
     925             :             }
     926             :         }
     927             :     }
     928             : 
     929    27868732 :     if ( win > 0 )
     930             :     {
     931             :         /* RMS-normalize uppermost noise-filled segment */
     932    25139093 :         tmp1 = (float) sqrt( ( lowpassLine - segmentOffset ) / nrg );
     933    25139093 :         tmp2 = tmp1 * (float) nTransWidth;
     934             : 
     935  2772826970 :         for ( m = segmentOffset; m < lowpassLine; m++ )
     936             :         {
     937  2747687877 :             Q[m] *= tmp2;
     938             :         }
     939             :     }
     940             : 
     941    27868732 :     return;
     942             : }
     943             : 
     944             : 
     945             : /*-------------------------------------------------------------------*
     946             :  * InitTnsConfigs()
     947             :  *
     948             :  *
     949             :  *-------------------------------------------------------------------*/
     950             : 
     951     1069950 : void InitTnsConfigs(
     952             :     const int16_t bwidth,
     953             :     const int16_t L_frame,
     954             :     STnsConfig tnsConfig[2][2],
     955             :     const int16_t igfStopFreq,
     956             :     const int32_t total_brate,
     957             :     const int16_t element_mode,
     958             :     const int16_t MCT_flag )
     959             : {
     960     1069950 :     if ( total_brate > ACELP_32k )
     961             :     {
     962      834166 :         InitTnsConfiguration( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
     963             :     }
     964             : 
     965     1069950 :     InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
     966             : 
     967     1069950 :     InitTnsConfiguration( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
     968             : 
     969     1069950 :     return;
     970             : }
     971             : 
     972             : 
     973             : /*-------------------------------------------------------------------*
     974             :  *  SetAllowTnsOnWhite
     975             :  *
     976             :  *  set TNS config flag for possible application of TNS in the whitened domain
     977             :  *-------------------------------------------------------------------*/
     978             : 
     979     1069950 : void SetAllowTnsOnWhite(
     980             :     STnsConfig tnsConfig[2][2],  /* o  : updated TNS configurations */
     981             :     const int8_t allowTnsOnWhite /* i  : flag for TNS in whiteded domain mode */
     982             : )
     983             : {
     984     1069950 :     tnsConfig[0][0].allowTnsOnWhite = allowTnsOnWhite;
     985     1069950 :     tnsConfig[0][1].allowTnsOnWhite = allowTnsOnWhite;
     986     1069950 :     tnsConfig[1][0].allowTnsOnWhite = allowTnsOnWhite;
     987     1069950 :     tnsConfig[1][1].allowTnsOnWhite = allowTnsOnWhite;
     988             : 
     989     1069950 :     return;
     990             : }
     991             : 
     992             : 
     993             : /*-------------------------------------------------------------------*
     994             :  * SetTnsConfig()
     995             :  *
     996             :  *
     997             :  *-------------------------------------------------------------------*/
     998             : 
     999    41694541 : void SetTnsConfig(
    1000             :     TCX_CONFIG_HANDLE hTcxCfg,
    1001             :     const int16_t isTCX20,
    1002             :     const int16_t isAfterACELP )
    1003             : {
    1004    41694541 :     hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[isTCX20][isAfterACELP];
    1005    41694541 :     assert( hTcxCfg->pCurrentTnsConfig != NULL );
    1006             : 
    1007    41694541 :     return;
    1008             : }

Generated by: LCOV version 1.14