LCOV - code coverage report
Current view: top level - lib_com - tcx_utils.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 1ecb9137d23f3dad766c8f6f3eb1e829e795f071 Lines: 296 312 94.9 %
Date: 2025-10-29 06:44:26 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     1333738 : 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     1333738 :     if ( !fullband )
      66             :     {
      67             :         /* Left part */
      68             : 
      69      210537 :         if ( left_mode == TRANSITION_OVERLAP )
      70             :         {
      71             :             /* ACELP->TCX transition */
      72         426 :             *left_overlap = hTcxCfg->tcx_mdct_window_trans_length;
      73         426 :             *left_win = hTcxCfg->tcx_mdct_window_trans;
      74             :         }
      75      210111 :         else if ( left_mode == MIN_OVERLAP )
      76             :         {
      77        3793 :             *left_overlap = hTcxCfg->tcx_mdct_window_min_length;
      78        3793 :             *left_win = hTcxCfg->tcx_mdct_window_minimum;
      79             :         }
      80      206318 :         else if ( left_mode == HALF_OVERLAP )
      81             :         {
      82        2932 :             *left_overlap = hTcxCfg->tcx_mdct_window_half_length;
      83        2932 :             *left_win = hTcxCfg->tcx_mdct_window_half;
      84             :         }
      85      203386 :         else if ( left_mode == FULL_OVERLAP )
      86             :         {
      87      203386 :             *left_overlap = hTcxCfg->tcx_mdct_window_length;
      88      203386 :             *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      210537 :         if ( right_mode == MIN_OVERLAP )
      98             :         {
      99        3808 :             *right_overlap = hTcxCfg->tcx_mdct_window_min_length;
     100        3808 :             *right_win = hTcxCfg->tcx_mdct_window_minimum;
     101             :         }
     102      206729 :         else if ( right_mode == HALF_OVERLAP )
     103             :         {
     104        3080 :             *right_overlap = hTcxCfg->tcx_mdct_window_half_length;
     105        3080 :             *right_win = hTcxCfg->tcx_mdct_window_half;
     106             :         }
     107      203649 :         else if ( right_mode == FULL_OVERLAP )
     108             :         {
     109      203649 :             *right_overlap = hTcxCfg->tcx_mdct_window_delay;
     110      203649 :             *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     1123201 :         if ( left_mode == TRANSITION_OVERLAP )
     122             :         {
     123             :             /* ACELP->TCX transition */
     124       20930 :             *left_overlap = hTcxCfg->tcx_mdct_window_trans_lengthFB;
     125       20930 :             *left_win = hTcxCfg->tcx_mdct_window_transFB;
     126             :         }
     127     1102271 :         else if ( left_mode == MIN_OVERLAP )
     128             :         {
     129      214753 :             *left_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
     130      214753 :             *left_win = hTcxCfg->tcx_mdct_window_minimumFB;
     131             :         }
     132      887518 :         else if ( left_mode == HALF_OVERLAP )
     133             :         {
     134       73281 :             *left_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
     135       73281 :             *left_win = hTcxCfg->tcx_mdct_window_halfFB;
     136             :         }
     137      814237 :         else if ( left_mode == RECTANGULAR_OVERLAP )
     138             :         {
     139      133509 :             *left_overlap = 0;
     140      133509 :             *left_win = NULL;
     141             :         }
     142      680728 :         else if ( left_mode == FULL_OVERLAP )
     143             :         {
     144      680728 :             *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB;
     145      680728 :             *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     1123201 :         if ( right_mode == MIN_OVERLAP )
     155             :         {
     156      214738 :             *right_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
     157      214738 :             *right_win = hTcxCfg->tcx_mdct_window_minimumFB;
     158             :         }
     159      908463 :         else if ( right_mode == HALF_OVERLAP )
     160             :         {
     161      121599 :             *right_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
     162      121599 :             *right_win = hTcxCfg->tcx_mdct_window_halfFB;
     163             :         }
     164      786864 :         else if ( right_mode == RECTANGULAR_OVERLAP )
     165             :         {
     166      133488 :             *right_overlap = 0;
     167      133488 :             *right_win = NULL;
     168             :         }
     169      653376 :         else if ( right_mode == FULL_OVERLAP )
     170             :         {
     171      653376 :             *right_overlap = hTcxCfg->tcx_mdct_window_delayFB;
     172      653376 :             *right_win = hTcxCfg->tcx_aldo_window_2_FB;
     173             :         }
     174             :         else
     175             :         {
     176           0 :             assert( !"Not supported overlap" );
     177             :         }
     178             :     }
     179             : 
     180     1333738 :     return;
     181             : }
     182             : 
     183             : /*-------------------------------------------------------------------*
     184             :  * tcx_windowing_analysis()
     185             :  *
     186             :  *
     187             :  *-------------------------------------------------------------------*/
     188             : 
     189     1333693 : 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   330738507 :     for ( w = 0; w < left_overlap; w++ )
     203             :     {
     204   329404814 :         *output++ = *signal++ * left_win[w];
     205             :     }
     206             : 
     207             :     /* Non overlapping region */
     208   471888769 :     for ( w = 0; w < L_frame - ( left_overlap + right_overlap ) / 2; w++ )
     209             :     {
     210   470555076 :         *output++ = *signal++;
     211             :     }
     212             : 
     213             :     /* Right overlap */
     214   326979639 :     for ( w = 0; w < right_overlap; w++ )
     215             :     {
     216   325645946 :         *output++ = *signal++ * right_win[right_overlap - 1 - w];
     217             :     }
     218             : 
     219     1333693 :     return;
     220             : }
     221             : 
     222             : 
     223             : /*-------------------------------------------------------------------*
     224             :  * WindowSignal()
     225             :  *
     226             :  *
     227             :  *-------------------------------------------------------------------*/
     228             : 
     229     1333693 : 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     1333693 :     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     1333693 :     if ( left_overlap_mode == TRANSITION_OVERLAP )
     257             :     {
     258             :         /* Increase frame size for 5ms */
     259       21356 :         if ( !fullband )
     260             :         {
     261         426 :             *L_frame += hTcxCfg->tcx5Size;
     262         426 :             offset = -hTcxCfg->tcx_mdct_window_trans_length / 2;
     263             :         }
     264             :         else
     265             :         {
     266       20930 :             *L_frame += hTcxCfg->tcx5SizeFB;
     267       20930 :             offset = -hTcxCfg->tcx_mdct_window_trans_lengthFB / 2;
     268             :         }
     269             :     }
     270             : 
     271             :     /*-----------------------------------------------------------*
     272             :      * Windowing                                                 *
     273             :      *-----------------------------------------------------------*/
     274             : 
     275     1333693 :     tcx_windowing_analysis( in - l / 2 + offset, *L_frame, l, left_win, r, right_win, out );
     276             : 
     277     1333693 :     if ( left_overlap_mode == FULL_OVERLAP && truncate_aldo )
     278             :     {
     279             :         /* fade truncated ALDO window to avoid discontinuities */
     280      774585 :         if ( !fullband )
     281             :         {
     282      203386 :             v_mult( out, hTcxCfg->tcx_mdct_window_minimum, out, hTcxCfg->tcx_mdct_window_min_length );
     283             :         }
     284             :         else
     285             :         {
     286      571199 :             v_mult( out, hTcxCfg->tcx_mdct_window_minimumFB, out, hTcxCfg->tcx_mdct_window_min_lengthFB );
     287             :         }
     288             :     }
     289             : 
     290     1333693 :     *left_overlap_length = l;
     291     1333693 :     *right_overlap_length = r;
     292             : 
     293     1333693 :     return;
     294             : }
     295             : 
     296             : 
     297             : /*-------------------------------------------------------------------*
     298             :  * tcx_windowing_synthesis_current_frame()
     299             :  *
     300             :  *
     301             :  *-------------------------------------------------------------------*/
     302             : 
     303     2640126 : 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     2640126 :     overlap = window_length >> 1;
     329             : 
     330             :     /* Past-frame is TCX concealed as CNG and current-frame is TCX */
     331     2640126 :     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     2640126 :     else if ( left_rect == 1 && last_core_bfi == ACELP_CORE ) /* Rectangular window (past-frame is ACELP) */
     351             :     {
     352    22184638 :         for ( i = 0; i < overlap - acelp_mem_len; i++ )
     353             :         {
     354    21948336 :             signal[i] = 0;
     355             :         }
     356             : 
     357      236302 :         if ( fullbandScale == 0 )
     358             :         {
     359             :             /*OLA with ACELP*/
     360     2574141 :             for ( i = 0; i < 2 * acelp_mem_len; i++ )
     361             :             {
     362             :                 /*window decoded TCX with aliasing*/
     363     2447072 :                 signal[i + overlap - acelp_mem_len] *= window_trans[i];
     364             :                 /*Time TDAC: 1)forward part of ACELP*/
     365     2447072 :                 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     2447072 :                 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     2160173 :             for ( i = 0; i < M; i++ )
     372             :             {
     373     2033104 :                 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      236302 :         acelp_zir_len = 64;
     379             : 
     380      236302 :         if ( !fullbandScale )
     381             :         {
     382      127069 :             set_zero( acelp_zir, acelp_zir_len );
     383      127069 :             syn_filt( A_zir, M, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0 );
     384             :         }
     385             :         else
     386             :         {
     387      109233 :             lerp( acelp_zir, tmp, acelp_zir_len * fullbandScale / FSCALE_DENOM, acelp_zir_len );
     388      109233 :             acelp_zir_len = acelp_zir_len * fullbandScale / FSCALE_DENOM;
     389      109233 :             acelp_zir = tmp;
     390             : 
     391      109233 :             if ( acelp_zir_len >= 2.0f * 64 )
     392             :             {
     393             :                 /* apply a simple low-pass to the ZIR, to avoid potentially unmasked HF content */
     394    14058108 :                 for ( i = 2; i < acelp_zir_len; i++ )
     395             :                 {
     396    13981688 :                     acelp_zir[i] = 0.25f * acelp_zir[i - 2] + 0.35f * acelp_zir[i - 1] + 0.40f * acelp_zir[i];
     397             :                 }
     398       76420 :                 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       76420 :                 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    14058108 :                 for ( i = acelp_zir_len - 3; i >= 0; i-- )
     401             :                 {
     402    13981688 :                     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    25014150 :         for ( i = 0; i < acelp_zir_len; i++ )
     408             :         {
     409             :             /*remove reconstructed ZIR and add ACELP ZIR*/
     410    24777848 :             signal[i + overlap + acelp_mem_len] -= acelp_zir[i] * (float) ( acelp_zir_len - i ) / (float) acelp_zir_len;
     411             :         }
     412             :     }
     413     2403824 :     else if ( left_rect == 1 && last_core_bfi != 0 ) /* Rectangular window (past-frame is TCX) */
     414             :     {
     415     3761946 :         for ( i = 0; i < overlap + acelp_mem_len; i++ )
     416             :         {
     417     3734496 :             signal[i] = 0;
     418             :         }
     419     6562818 :         for ( i = 0; i < window_length; i++ )
     420             :         {
     421     6535368 :             signal[i + overlap + acelp_mem_len] *= window[i];
     422             :         }
     423             :     }
     424     2376374 :     else if ( left_rect != 1 && last_core_bfi == 0 ) /* Normal window (past-frame is ACELP) */
     425             :     {
     426       47976 :         for ( i = 0; i < window_length; i++ )
     427             :         {
     428       47796 :             signal[i] *= window[i];
     429             :         }
     430             : 
     431       47976 :         for ( i = 0; i < window_length; i++ )
     432             :         {
     433       47796 :             signal[i] += syn_overl[i];
     434             :         }
     435             :     }
     436             :     else /* Normal window (past-frame is TCX) */
     437             :     {
     438     2376194 :         if ( left_mode == 2 )
     439             :         {
     440             :             /* min. overlap */
     441    66354925 :             for ( i = 0; i < ( window_length - window_min_length ) / 2; i++ )
     442             :             {
     443    64970392 :                 signal[i] = 0.0f;
     444             :             }
     445    53228225 :             for ( w = 0; w < window_min_length; i++, w++ )
     446             :             {
     447    51843692 :                 signal[i] *= window_min[w];
     448             :             }
     449             :         }
     450      991661 :         else if ( left_mode == 3 )
     451             :         {
     452             :             /* half OL */
     453     1863147 :             for ( i = 0; i < ( window_length - window_half_length ) / 2; i++ )
     454             :             {
     455     1620632 :                 signal[i] = 0.0f;
     456             :             }
     457    28083643 :             for ( w = 0; w < window_half_length; i++, w++ )
     458             :             {
     459    27841128 :                 signal[i] *= window_half[w];
     460             :             }
     461             :         }
     462             :         else
     463             :         {
     464             :             /* normal full/maximum overlap */
     465   195937594 :             for ( i = 0; i < window_length; i++ )
     466             :             {
     467   195188448 :                 signal[i] *= window[i];
     468             :             }
     469             :         }
     470             :     }
     471             : 
     472     2640126 :     return;
     473             : }
     474             : 
     475             : 
     476             : /*-------------------------------------------------------------------*
     477             :  * tcx_windowing_synthesis_past_frame()
     478             :  *
     479             :  *
     480             :  *-------------------------------------------------------------------*/
     481             : 
     482     2651630 : 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     2651630 :     if ( right_mode == MIN_OVERLAP )
     496             :     {
     497             :         /* min. overlap */
     498    54947248 :         for ( i = ( window_length - window_min_length ) / 2, w = 0; w < window_min_length; i++, w++ )
     499             :         {
     500    53514704 :             signal[i] *= window_min[window_min_length - 1 - w];
     501             :         }
     502    81203376 :         for ( ; i < window_length; i++ )
     503             :         {
     504    79770832 :             signal[i] = 0.0f;
     505             :         }
     506             :     }
     507     1219086 :     else if ( right_mode == HALF_OVERLAP )
     508             :     {
     509             :         /* half OL */
     510    48433064 :         for ( i = ( window_length - window_half_length ) / 2, w = 0; w < window_half_length; i++, w++ )
     511             :         {
     512    48007500 :             signal[i] *= window_half[window_half_length - 1 - w];
     513             :         }
     514    32430564 :         for ( ; i < window_length; i++ )
     515             :         {
     516    32005000 :             signal[i] = 0.0f;
     517             :         }
     518             :     }
     519      793522 :     else if ( right_mode == FULL_OVERLAP )
     520             :     {
     521             :         /* normal full/maximum overlap */
     522   198395598 :         for ( i = 0; i < window_length; i++ )
     523             :         {
     524   197602076 :             signal[i] *= window[window_length - 1 - i];
     525             :         }
     526             :     }
     527             : 
     528     2651630 :     return;
     529             : }
     530             : 
     531             : 
     532             : /*-------------------------------------------------------------------*
     533             :  * lpc2mdct()
     534             :  *
     535             :  *
     536             :  *-------------------------------------------------------------------*/
     537             : 
     538     4821851 : 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     4821851 :     assert( length <= FDNS_NPTS );
     550             : 
     551     4821851 :     sizeN = 2 * length;
     552             : 
     553             :     /* ODFT */
     554    86793318 :     for ( i = 0; i < lpcOrder + 1; i++ )
     555             :     {
     556    81971467 :         tmp = (float) ( ( (float) i ) * EVS_PI / (float) ( sizeN ) );
     557    81971467 :         RealData[i] = (float) ( lpcCoeffs[i] * cos( tmp ) );
     558    81971467 :         ImagData[i] = (float) ( -lpcCoeffs[i] * sin( tmp ) );
     559             :     }
     560             : 
     561   540047312 :     for ( ; i < sizeN; i++ )
     562             :     {
     563   535225461 :         RealData[i] = 0.f;
     564   535225461 :         ImagData[i] = 0.f;
     565             :     }
     566             : 
     567     4821851 :     DoFFT( RealData, ImagData, sizeN );
     568             : 
     569     4821851 :     if ( noInverse )
     570             :     {
     571           0 :         assert( !"not supported option in lpc2mdct()" );
     572             :     }
     573             :     else
     574             :     {
     575             :         /* Get amplitude */
     576   313420315 :         for ( i = 0; i < length; i++ )
     577             :         {
     578   308598464 :             mdct_gains[i] = (float) ( 1.0f / max( EPSILON, sqrt( RealData[i] * RealData[i] + ImagData[i] * ImagData[i] ) ) );
     579             :         }
     580             :     }
     581             : 
     582     4821851 :     return;
     583             : }
     584             : 
     585             : 
     586             : /*-------------------------------------------------------------------*
     587             :  * mdct_noiseShaping()
     588             :  *
     589             :  *
     590             :  *-------------------------------------------------------------------*/
     591             : 
     592     4851613 : void mdct_noiseShaping(
     593             :     float x[],
     594             :     const int16_t lg,
     595             :     const float gains[],
     596             :     const int16_t nBands )
     597             : {
     598             :     int16_t i, j, k, l;
     599             :     float g;
     600             :     int16_t m, n, k1, k2;
     601             : 
     602     4851613 :     j = 0;
     603     4851613 :     assert( nBands != 0 );
     604     4851613 :     k = lg / nBands;
     605     4851613 :     m = lg % nBands;
     606             : 
     607     4851613 :     if ( m )
     608             :     {
     609      109086 :         if ( m <= ( FDNS_NPTS / 2 ) )
     610             :         {
     611      109086 :             n = FDNS_NPTS / m;
     612      109086 :             k1 = k;
     613      109086 :             k2 = k + 1;
     614             :         }
     615             :         else
     616             :         {
     617           0 :             n = FDNS_NPTS / ( FDNS_NPTS - m );
     618           0 :             k1 = k + 1;
     619           0 :             k2 = k;
     620             :         }
     621             : 
     622     7090590 :         for ( i = 0; i < lg; )
     623             :         {
     624     6981504 :             if ( j % n )
     625             :             {
     626     4709632 :                 k = k1;
     627             :             }
     628             :             else
     629             :             {
     630     2271872 :                 k = k2;
     631             :             }
     632     6981504 :             g = gains[j++];
     633             : 
     634             :             /* Limit number of loops, if end is reached */
     635     6981504 :             k = min( k, lg - i );
     636             : 
     637    43600384 :             for ( l = 0; l < k; l++ )
     638             :             {
     639    36618880 :                 x[i++] *= g;
     640             :             }
     641             :         }
     642             :     }
     643             :     else
     644             :     {
     645   308264255 :         for ( i = 0; i < lg; )
     646             :         {
     647   303521728 :             g = gains[j++];
     648             : 
     649  2152036992 :             for ( l = 0; l < k; l++ )
     650             :             {
     651  1848515264 :                 x[i++] *= g;
     652             :             }
     653             :         }
     654             :     }
     655             : 
     656     4851613 :     return;
     657             : }
     658             : 
     659             : 
     660             : /*-------------------------------------------------------------------*
     661             :  * PsychAdaptLowFreqDeemph()
     662             :  *
     663             :  *
     664             :  *-------------------------------------------------------------------*/
     665             : 
     666      543301 : void PsychAdaptLowFreqDeemph(
     667             :     float x[],
     668             :     const float lpcGains[],
     669             :     float lf_deemph_factors[] )
     670             : {
     671             :     int16_t i;
     672             :     float max_val, fac, tmp;
     673             : 
     674      543301 :     max_val = tmp = lpcGains[0];
     675             : 
     676             :     /* find minimum (tmp) and maximum (max) of LPC gains in low frequencies */
     677     4889709 :     for ( i = 1; i < 9; i++ )
     678             :     {
     679     4346408 :         if ( tmp > lpcGains[i] )
     680             :         {
     681     2931994 :             tmp = lpcGains[i];
     682             :         }
     683     4346408 :         if ( max_val < lpcGains[i] )
     684             :         {
     685      893530 :             max_val = lpcGains[i];
     686             :         }
     687             :     }
     688             : 
     689      543301 :     tmp *= 32.0f;
     690             : 
     691      543301 :     if ( ( max_val < tmp ) && ( tmp > FLT_MIN ) )
     692             :     {
     693      543301 :         fac = tmp = (float) pow( max_val / tmp, 0.0078125f );
     694             : 
     695      543301 :         if ( lf_deemph_factors )
     696             :         {
     697             :             /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
     698     6592509 :             for ( i = 31; i >= 0; i-- )
     699             :             {
     700     6392736 :                 x[i] *= fac;
     701     6392736 :                 lf_deemph_factors[i] *= fac;
     702     6392736 :                 fac *= tmp;
     703             :             }
     704             :         }
     705             :         else
     706             :         {
     707             :             /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
     708    11336424 :             for ( i = 31; i >= 0; i-- )
     709             :             {
     710    10992896 :                 x[i] *= fac;
     711    10992896 :                 fac *= tmp;
     712             :             }
     713             :         }
     714             :     }
     715             : 
     716      543301 :     return;
     717             : }
     718             : 
     719             : 
     720             : /*-------------------------------------------------------------------*
     721             :  * AdaptLowFreqDeemph()
     722             :  *
     723             :  *
     724             :  *-------------------------------------------------------------------*/
     725             : 
     726     2214952 : void AdaptLowFreqDeemph(
     727             :     float x[],
     728             :     int16_t tcx_lpc_shaped_ari,
     729             :     const float lpcGains[],
     730             :     const int16_t lg,
     731             :     float lf_deemph_factors[] )
     732             : {
     733             :     int16_t i, i_max_old, i_max;
     734             : 
     735     2214952 :     if ( !tcx_lpc_shaped_ari )
     736             :     {
     737             :         /* 1. find first magnitude maximum in lower quarter of spectrum */
     738     2015179 :         i_max = -1;
     739             : 
     740     8500207 :         for ( i = 0; i < lg / 4; i++ )
     741             :         {
     742     8463738 :             if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
     743             :             {
     744     1978710 :                 x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
     745     1978710 :                 i_max = i;
     746     1978710 :                 break;
     747             :             }
     748             :         }
     749             :         /* 2. expand value range of all xi up to i_max: two extra steps */
     750             : 
     751     5688531 :         for ( i = 0; i < i_max; i++ )
     752             :         {
     753     3673352 :             x[i] *= 0.5f;
     754     3673352 :             lf_deemph_factors[i] *= 0.5f;
     755             :         }
     756             :         /* 3. find first magnitude maximum in lower quarter of spectrum */
     757     2015179 :         i_max_old = i_max;
     758             : 
     759     2015179 :         if ( i_max_old > -1 )
     760             :         {
     761     1978710 :             i_max = -1;
     762             : 
     763     8546652 :             for ( i = 0; i < lg / 4; i++ )
     764             :             {
     765     8546585 :                 if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
     766             :                 {
     767     1978643 :                     x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
     768     1978643 :                     i_max = i;
     769     1978643 :                     break;
     770             :                 }
     771             :             }
     772             :         }
     773             :         /* 4. expand value range of all xi up to i_max: two extra steps */
     774     8578017 :         for ( i = 0; i < i_max; i++ )
     775             :         {
     776     6562838 :             x[i] *= 0.5f;
     777     6562838 :             lf_deemph_factors[i] *= 0.5f;
     778             :         }
     779             :         /* 5. always expand two lines; lines could be at index 0 and 1! */
     780     2015179 :         if ( i_max < i_max_old )
     781             :         {
     782          67 :             i_max = i_max_old;
     783             :         }
     784     2015179 :         i = i_max + 1;
     785     2015179 :         if ( x[i] < 0.0f )
     786             :         {
     787      888099 :             if ( x[i] > -4.0f )
     788             :             {
     789      323789 :                 lf_deemph_factors[i] *= 0.5f;
     790             :             }
     791      888099 :             x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
     792             :         }
     793             :         else
     794             :         {
     795     1127080 :             if ( x[i] < 4.0f )
     796             :             {
     797      522631 :                 lf_deemph_factors[i] *= 0.5f;
     798             :             }
     799     1127080 :             x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
     800             :         }
     801     2015179 :         i++;
     802     2015179 :         if ( x[i] < 0.0f )
     803             :         {
     804      877879 :             if ( x[i] > -4.0f )
     805             :             {
     806      390414 :                 lf_deemph_factors[i] *= 0.5f;
     807             :             }
     808      877879 :             x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
     809             :         }
     810             :         else
     811             :         {
     812     1137300 :             if ( x[i] < 4.0f )
     813             :             {
     814      684123 :                 lf_deemph_factors[i] *= 0.5f;
     815             :             }
     816     1137300 :             x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
     817             :         }
     818             :     }
     819             :     else
     820             :     {
     821      199773 :         PsychAdaptLowFreqDeemph( x, lpcGains, lf_deemph_factors );
     822             :     }
     823             : 
     824     2214952 :     return;
     825             : }
     826             : 
     827             : 
     828             : /*-------------------------------------------------------------------*
     829             :  * tcx_noise_filling()
     830             :  *
     831             :  *
     832             :  *-------------------------------------------------------------------*/
     833             : 
     834    12723812 : void tcx_noise_filling(
     835             :     float *Q,
     836             :     const int16_t noiseFillSeed,
     837             :     const int16_t iFirstLine,
     838             :     const int16_t lowpassLine,
     839             :     const int16_t nTransWidth,
     840             :     const int16_t L_frame,
     841             :     const float tiltCompFactor,
     842             :     float fac_ns,
     843             :     uint8_t *infoTCXNoise,
     844             :     const int16_t element_mode /* i  : IVAS element mode                         */
     845             : )
     846             : {
     847             :     int16_t i, m, segmentOffset;
     848             :     int16_t win; /* window coefficient */
     849             :     Word16 seed;
     850             :     float tilt_factor, nrg, tmp1, tmp2;
     851             : 
     852             :     /* 16-bit random number generator seed for generating filled lines */
     853    12723812 :     seed = (Word16) noiseFillSeed;
     854             : 
     855    12723812 :     tilt_factor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / (float) L_frame );
     856    12723812 :     fac_ns /= (float) ( nTransWidth * nTransWidth );
     857             : 
     858             :     /* find last nonzero line below iFirstLine, use it as start offset */
     859    12723812 :     i = iFirstLine;
     860             : 
     861    12723812 :     if ( element_mode == IVAS_CPE_MDCT ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
     862             :     {
     863     9306666 :         segmentOffset = i;
     864             :     }
     865             :     else
     866             :     {
     867     9171325 :         for ( ; i > ( iFirstLine >> 1 ); i-- )
     868             :         {
     869     9151366 :             if ( Q[i] != 0.0f )
     870             :             {
     871     3397187 :                 break;
     872             :             }
     873             :         }
     874             : 
     875     3417146 :         fac_ns *= (float) pow( tilt_factor, (float) i );
     876     3417146 :         segmentOffset = ++i;
     877             :     }
     878             : 
     879    12723812 :     nrg = 1e-9f;
     880    12723812 :     win = 0;
     881             : 
     882  5100558654 :     for ( ; i < lowpassLine; i++ )
     883             :     {
     884  5087834842 :         fac_ns *= tilt_factor;
     885             : 
     886  5087834842 :         if ( Q[i] != 0.0f )
     887             :         {
     888  1197703065 :             if ( win > 0 )
     889             :             {
     890             :                 /* RMS-normalize current noise-filled segment */
     891   541026553 :                 tmp1 = (float) sqrt( ( i - segmentOffset ) / nrg );
     892   541026553 :                 tmp2 = tmp1 * (float) nTransWidth;
     893             : 
     894  1422060518 :                 for ( m = segmentOffset; m < i - win; m++ )
     895             :                 {
     896   881033965 :                     Q[m] *= tmp2;
     897             :                 }
     898             : 
     899  2133887167 :                 for ( ; win > 0; win-- )
     900             :                 {
     901  1592860614 :                     Q[m++] *= tmp1 * (float) win;
     902             :                 }
     903   541026553 :                 nrg = 1e-9f; /* start new segment: reset noise segment energy */
     904             :             }
     905  1197703065 :             segmentOffset = i + 1;
     906             :         }
     907             :         else
     908             :         {
     909             :             /* line is zero, so fill line and update window and energy */
     910  3890131777 :             if ( win < nTransWidth )
     911             :             {
     912  1672130970 :                 win++;
     913             :             }
     914  3890131777 :             tmp1 = (float) own_random( &seed );
     915  3890131777 :             nrg += tmp1 * tmp1; /* sum up energy of current noise segment */
     916  3890131777 :             Q[i] = tmp1 * (float) win * fac_ns;
     917             : 
     918  3890131777 :             if ( infoTCXNoise )
     919             :             {
     920             :                 /* set noiseflags for IGF */
     921  1925715993 :                 infoTCXNoise[i] = 1;
     922             :             }
     923             :         }
     924             :     }
     925             : 
     926    12723812 :     if ( win > 0 )
     927             :     {
     928             :         /* RMS-normalize uppermost noise-filled segment */
     929    11514598 :         tmp1 = (float) sqrt( ( lowpassLine - segmentOffset ) / nrg );
     930    11514598 :         tmp2 = tmp1 * (float) nTransWidth;
     931             : 
     932  1427751796 :         for ( m = segmentOffset; m < lowpassLine; m++ )
     933             :         {
     934  1416237198 :             Q[m] *= tmp2;
     935             :         }
     936             :     }
     937             : 
     938    12723812 :     return;
     939             : }
     940             : 
     941             : 
     942             : /*-------------------------------------------------------------------*
     943             :  * InitTnsConfigs()
     944             :  *
     945             :  *
     946             :  *-------------------------------------------------------------------*/
     947             : 
     948      422214 : void InitTnsConfigs(
     949             :     const int16_t bwidth,
     950             :     const int16_t L_frame,
     951             :     STnsConfig tnsConfig[2][2],
     952             :     const int16_t igfStopFreq,
     953             :     const int32_t total_brate,
     954             :     const int16_t element_mode,
     955             :     const int16_t MCT_flag )
     956             : {
     957      422214 :     if ( total_brate > ACELP_32k )
     958             :     {
     959      364276 :         InitTnsConfiguration( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
     960             :     }
     961             : 
     962      422214 :     InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
     963             : 
     964      422214 :     InitTnsConfiguration( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
     965             : 
     966      422214 :     return;
     967             : }
     968             : 
     969             : 
     970             : /*-------------------------------------------------------------------*
     971             :  *  SetAllowTnsOnWhite
     972             :  *
     973             :  *  set TNS config flag for possible application of TNS in the whitened domain
     974             :  *-------------------------------------------------------------------*/
     975             : 
     976      422214 : void SetAllowTnsOnWhite(
     977             :     STnsConfig tnsConfig[2][2],  /* o  : updated TNS configurations */
     978             :     const int8_t allowTnsOnWhite /* i  : flag for TNS in whiteded domain mode */
     979             : )
     980             : {
     981      422214 :     tnsConfig[0][0].allowTnsOnWhite = allowTnsOnWhite;
     982      422214 :     tnsConfig[0][1].allowTnsOnWhite = allowTnsOnWhite;
     983      422214 :     tnsConfig[1][0].allowTnsOnWhite = allowTnsOnWhite;
     984      422214 :     tnsConfig[1][1].allowTnsOnWhite = allowTnsOnWhite;
     985             : 
     986      422214 :     return;
     987             : }
     988             : 
     989             : 
     990             : /*-------------------------------------------------------------------*
     991             :  * SetTnsConfig()
     992             :  *
     993             :  *
     994             :  *-------------------------------------------------------------------*/
     995             : 
     996    16266992 : void SetTnsConfig(
     997             :     TCX_CONFIG_HANDLE hTcxCfg,
     998             :     const int16_t isTCX20,
     999             :     const int16_t isAfterACELP )
    1000             : {
    1001    16266992 :     hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[isTCX20][isAfterACELP];
    1002    16266992 :     assert( hTcxCfg->pCurrentTnsConfig != NULL );
    1003             : 
    1004    16266992 :     return;
    1005             : }

Generated by: LCOV version 1.14