LCOV - code coverage report
Current view: top level - lib_com - wi.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 604 0.0 %
Date: 2025-05-23 08:37:30 Functions: 0 27 0.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 <stdint.h>
      38             : #include "options.h"
      39             : #include <math.h>
      40             : #include "cnst.h"
      41             : #include "prot.h"
      42             : #include "rom_com.h"
      43             : #include "wmc_auto.h"
      44             : 
      45             : /*-------------------------------------------------------------------*
      46             :  * Local constants
      47             :  *-------------------------------------------------------------------*/
      48             : 
      49             : #define WARP_OS_RATE   8
      50             : #define LL             256
      51             : #define LL_OS          ( WARP_OS_RATE * LL )
      52             : #define OSLENGTH       12
      53             : #define WI_THRESHLD    0.8
      54             : #define WI_SAMPLE_THLD 20
      55             : #define ERB_CBSIZE1    64
      56             : #define ERB_CBSIZE2    64
      57             : 
      58             : #define _POLY1( x, c ) ( ( c )[0] * ( x ) + ( c )[1] )
      59             : #define _POLY2( x, c ) ( _POLY1( ( x ), ( c ) ) * ( x ) + ( c )[2] )
      60             : #define _POLY3( x, c ) ( _POLY2( ( x ), ( c ) ) * ( x ) + ( c )[3] )
      61             : 
      62             : 
      63             : /*-------------------------------------------------------------------*
      64             :  * DTFS_new()
      65             :  *
      66             :  * DTFS structure initialization.
      67             :  *-------------------------------------------------------------------*/
      68             : 
      69             : /*! r: DTFS structure  */
      70           0 : ivas_error DTFS_new(
      71             :     DTFS_STRUCTURE **dtfs_out )
      72             : {
      73             :     int16_t i;
      74           0 :     DTFS_STRUCTURE *dtfs = NULL;
      75             : 
      76           0 :     if ( ( dtfs = (DTFS_STRUCTURE *) malloc( sizeof( DTFS_STRUCTURE ) ) ) == NULL )
      77             :     {
      78           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTFS (SC-VBR) structure\n" ) );
      79             :     }
      80             : 
      81             : #define WMC_TOOL_SKIP
      82             :     MOVE( 2 );
      83             :     LOOP( 1 );
      84             :     MOVE( 2 );
      85           0 :     dtfs->lag = 0;
      86           0 :     dtfs->nH = 0;
      87           0 :     dtfs->nH_4kHz = 0;
      88           0 :     dtfs->upper_cut_off_freq_of_interest = 3300.0;
      89           0 :     dtfs->upper_cut_off_freq = 4000.0;
      90             : 
      91           0 :     for ( i = 0; i < MAXLAG_WI; i++ )
      92             :     {
      93           0 :         dtfs->a[i] = dtfs->b[i] = 0.0;
      94             :     }
      95             : 
      96           0 :     dtfs->sampling_rate = -1;
      97             : 
      98           0 :     *dtfs_out = dtfs;
      99             : #undef WMC_TOOL_SKIP
     100             : 
     101           0 :     return IVAS_ERR_OK;
     102             : }
     103             : 
     104             : 
     105             : /*-------------------------------------------------------------------*
     106             :  * DTFS_copy()
     107             :  *
     108             :  * Copy from one DTFS STRUCTURE to another.
     109             :  *-------------------------------------------------------------------*/
     110             : 
     111           0 : void DTFS_copy(
     112             :     DTFS_STRUCTURE *Xout, /* o  : DTFS structure  */
     113             :     DTFS_STRUCTURE Xinp   /* i  : DTFS structure  */
     114             : )
     115             : {
     116             :     int16_t k;
     117             : 
     118             : #define WMC_TOOL_SKIP
     119             :     LOOP( 1 );
     120           0 :     for ( k = 0; k < MAXLAG_WI; k++ )
     121             :     {
     122             :         MOVE( 1 );
     123           0 :         Xout->a[k] = Xinp.a[k];
     124             :     }
     125             :     LOOP( 1 );
     126           0 :     for ( k = 0; k < MAXLAG_WI; k++ )
     127             :     {
     128             :         MOVE( 1 );
     129           0 :         Xout->b[k] = Xinp.b[k];
     130             :     }
     131             :     MOVE( 1 );
     132           0 :     Xout->lag = Xinp.lag;
     133           0 :     Xout->nH = Xinp.nH;
     134           0 :     Xout->nH_4kHz = Xinp.nH_4kHz;
     135           0 :     Xout->upper_cut_off_freq_of_interest = Xinp.upper_cut_off_freq_of_interest;
     136           0 :     Xout->upper_cut_off_freq = Xinp.upper_cut_off_freq;
     137             : #undef WMC_TOOL_SKIP
     138             : 
     139           0 :     return;
     140             : }
     141             : 
     142             : 
     143             : /*-------------------------------------------------------------------*
     144             :  * DTFS_sub()
     145             :  *
     146             :  * Difference of A and B coefficients in cartesian domain.
     147             :  * Equivalent to time domain subtraction.
     148             :  *-------------------------------------------------------------------*/
     149             : 
     150           0 : void DTFS_sub(
     151             :     DTFS_STRUCTURE *tmp, /* o  : output DFTS  */
     152             :     DTFS_STRUCTURE X1,   /* i  : DTFS input 1 */
     153             :     DTFS_STRUCTURE X2    /* i  : DTFS input 2 */
     154             : )
     155             : {
     156             :     int16_t i;
     157             : 
     158             : #define WMC_TOOL_SKIP
     159             :     MULT( 1 );
     160             :     LOOP( 1 );
     161           0 :     for ( i = 0; i <= X1.lag / 2; i++ )
     162             :     {
     163             :         MOVE( 1 );
     164             :         MULT( 1 );
     165           0 :         tmp->a[i] = X1.a[i];
     166             :         MOVE( 1 );
     167           0 :         tmp->b[i] = X1.b[i];
     168             :     }
     169             :     MULT( 1 );
     170             :     LOOP( 1 );
     171           0 :     for ( i = 0; i <= X2.lag / 2; i++ )
     172             :     {
     173             :         MAC( 1 );
     174           0 :         tmp->a[i] -= X2.a[i];
     175             :         ADD( 1 );
     176           0 :         tmp->b[i] -= X2.b[i];
     177             :     }
     178             :     MOVE( 1 );
     179           0 :     tmp->lag = max( X1.lag, X2.lag );
     180           0 :     tmp->nH = max( X1.nH, X2.nH );
     181           0 :     tmp->nH_4kHz = max( X1.nH_4kHz, X2.nH_4kHz );
     182           0 :     tmp->upper_cut_off_freq_of_interest = X1.upper_cut_off_freq_of_interest;
     183           0 :     tmp->upper_cut_off_freq = X1.upper_cut_off_freq;
     184             : #undef WMC_TOOL_SKIP
     185             : 
     186           0 :     return;
     187             : }
     188             : 
     189             : /*-------------------------------------------------------------------*
     190             :  * DTFS_fast_fs_inv()
     191             :  *
     192             :  * DTFS inverse.
     193             :  *-------------------------------------------------------------------*/
     194             : 
     195           0 : static void DTFS_fast_fs_inv(
     196             :     DTFS_STRUCTURE *X1_DTFS, /* i  : DTFS                     */
     197             :     float *out,              /* o  : time domain output       */
     198             :     int16_t N                /* i  : number of output samples */
     199             : )
     200             : {
     201           0 :     uint16_t i, M_2 = (uint16_t) min( X1_DTFS->lag >> 1, X1_DTFS->nH ), N_2 = (uint16_t) N >> 1;
     202             :     float dbuf[256 + 1]; /* N can't be > 256 */
     203             : 
     204           0 :     if ( N < X1_DTFS->lag )
     205             :     {
     206           0 :         N = X1_DTFS->lag;
     207             :     }
     208             : 
     209             : #define WMC_TOOL_SKIP
     210             :     /* Populate the dbuf array */
     211           0 :     dbuf[1] = X1_DTFS->a[0];
     212           0 :     dbuf[2] = 0.0;
     213           0 :     for ( i = 1; i < M_2; i++ )
     214             :     {
     215             :         MAC( 1 );
     216           0 :         dbuf[2 * i + 1] = X1_DTFS->a[i] * N_2;
     217             :         MAC( 1 );
     218           0 :         dbuf[2 * i + 2] = X1_DTFS->b[i] * N_2;
     219             :     }
     220             : 
     221           0 :     if ( N_2 != M_2 )
     222             :     {
     223           0 :         dbuf[2 * i + 1] = X1_DTFS->a[i] * N_2;
     224           0 :         dbuf[2 * i + 2] = X1_DTFS->b[i] * N_2;
     225           0 :         i++;
     226             :     }
     227             : 
     228             :     /* Zero-padding in the frequency domain */
     229           0 :     for ( ; i < N_2; i++ )
     230             :     {
     231             :         MOVE( 1 );
     232             :         MAC( 2 );
     233           0 :         dbuf[2 * i + 1] = dbuf[2 * i + 2] = 0.0;
     234             :     }
     235             : 
     236             :     FUNC( 3 );
     237           0 :     realft( dbuf, N_2, -1 );
     238             : 
     239           0 :     for ( i = 1; i <= N; i++ )
     240             :     {
     241             :         MULT( 1 );
     242             :         ADD( 1 );
     243           0 :         out[i - 1] = dbuf[i] / N_2;
     244             :     }
     245             : #undef WMC_TOOL_SKIP
     246             : 
     247           0 :     return;
     248             : }
     249             : 
     250             : 
     251             : /*-------------------------------------------------------------------*
     252             :  * DTFS_alignment_weight()
     253             :  *
     254             :  * Estimate the shift to find the best match between the reference
     255             :  * DTFS and the test DTFS.
     256             :  *-------------------------------------------------------------------*/
     257             : 
     258             : /*! r: shift value to shift X2_DTFS by */
     259           0 : static float DTFS_alignment_weight(
     260             :     DTFS_STRUCTURE refX1_DTFS, /* i  : X1 the reference DTFS to keep fixed          */
     261             :     DTFS_STRUCTURE X2_DTFS,    /* i  : X2 the test DTFS to shift to find best match */
     262             :     float Eshift,              /* i  : Expected shift - coarse value                */
     263             :     const float *LPC1,         /* i  : LPC to filter to find correlation in spch    */
     264             :     const float *LPC2          /* i  : LPC to filter to find correlation in spch    */
     265             : )
     266             : {
     267             :     /* Eshift is w.r.t  X2 */
     268             :     int16_t k;
     269             :     float maxcorr, corr, Adiff, diff, tmp, tmp1, fshift, n, wcorr;
     270           0 :     float pwf = 0.7f, tmplpc[M + 1];
     271             :     DTFS_STRUCTURE X1_DTFS;
     272             : 
     273             : #define WMC_TOOL_SKIP
     274             :     FUNC( 2 );
     275           0 :     DTFS_copy( &X1_DTFS, refX1_DTFS );
     276             :     FUNC( 2 );
     277           0 :     DTFS_adjustLag( &X1_DTFS, X2_DTFS.lag );
     278             :     FUNC( 3 );
     279             :     ADD( 1 );
     280           0 :     DTFS_poleFilter( &X1_DTFS, LPC1, M + 1 );
     281             :     MOVE( 1 );
     282           0 :     tmp = 1.0;
     283             :     LOOP( 1 );
     284           0 :     for ( k = 0, tmp = 1.0; k < M + 1; k++ )
     285             :     {
     286             :         MOVE( 1 );
     287             :         MULT( 2 );
     288           0 :         tmplpc[k] = LPC1[k] * ( tmp *= pwf );
     289             :     }
     290             : 
     291             :     FUNC( 3 );
     292           0 :     DTFS_zeroFilter( &X1_DTFS, tmplpc, M + 1 );
     293             :     FUNC( 3 );
     294           0 :     DTFS_poleFilter( &X2_DTFS, LPC2, M + 1 );
     295             :     MOVE( 1 );
     296             :     LOOP( 1 );
     297           0 :     for ( k = 0, tmp = 1.0; k < M + 1; k++ )
     298             :     {
     299             :         /* can be stored as a table */
     300             :         MULT( 1 );
     301           0 :         tmplpc[k] = LPC2[k] * ( tmp *= pwf );
     302             :     }
     303             :     FUNC( 3 );
     304           0 :     DTFS_zeroFilter( &X2_DTFS, tmplpc, M + 1 );
     305             :     MOVE( 1 );
     306             :     ADD( 1 );
     307           0 :     maxcorr = (float) -HUGE_VAL;
     308             :     MOVE( 1 );
     309           0 :     fshift = Eshift;
     310             :     MOVE( 1 );
     311             :     MULT( 1 );
     312           0 :     Adiff = max( 6, 0.15f * X2_DTFS.lag );
     313             :     LOGIC( 1 );
     314           0 :     if ( X2_DTFS.lag < 60 )
     315             :     {
     316             :         MOVE( 1 );
     317           0 :         diff = 0.25;
     318             :     }
     319             :     else
     320             :     {
     321             :         MOVE( 1 );
     322           0 :         diff = 0.5;
     323             :     }
     324             :     ADD( 1 );
     325             :     ADD( 1 );
     326             :     LOOP( 1 );
     327           0 :     for ( n = Eshift - Adiff; n <= Eshift + Adiff; n += diff )
     328             :     {
     329             :         MOVE( 2 );
     330             :         ADD( 1 );
     331           0 :         corr = tmp = 0.0f;
     332             :         /* bit-exact optimization - PI2/X2_DTFS.lag should be counted as a single divide */
     333             :         MULT( 1 );
     334           0 :         tmp1 = (float) ( PI2 * n / X2_DTFS.lag );
     335             :         ADD( 1 );
     336             :         LOOP( 1 );
     337           0 :         for ( k = 0; k <= min( X2_DTFS.lag >> 1, X2_DTFS.nH_4kHz ); k++, tmp += tmp1 )
     338             :         {
     339             :             /* Not counting math function cos and sin since they will be implemented as look-up tables */
     340             :             MAC( 1 );
     341             :             ADD( 1 );
     342           0 :             corr += (float) ( ( X1_DTFS.a[k] * X2_DTFS.a[k] + X1_DTFS.b[k] * X2_DTFS.b[k] ) * cos( tmp ) );
     343             :             MAC( 1 );
     344             :             ADD( 1 );
     345           0 :             corr += (float) ( ( X1_DTFS.b[k] * X2_DTFS.a[k] - X1_DTFS.a[k] * X2_DTFS.b[k] ) * sin( tmp ) );
     346             :         }
     347             :         MOVE( 1 );
     348             :         MAC( 2 );
     349             :         ABS( 1 );
     350           0 :         wcorr = (float) ( corr * ( 1.0f - 0.01f * fabs( n - Eshift ) ) );
     351             :         LOGIC( 1 );
     352           0 :         if ( wcorr > maxcorr )
     353             :         {
     354             :             MOVE( 1 );
     355           0 :             fshift = n;
     356             :             MOVE( 1 );
     357           0 :             maxcorr = wcorr;
     358             :         }
     359             :     }
     360             : #undef WMC_TOOL_SKIP
     361             : 
     362           0 :     return fshift;
     363             : }
     364             : 
     365             : 
     366             : /*-------------------------------------------------------------------*
     367             :  * DTFS_alignment_full()
     368             :  *
     369             :  *  Shift value for DTFS full alignment.
     370             :  *-------------------------------------------------------------------*/
     371             : 
     372           0 : float DTFS_alignment_full(
     373             :     DTFS_STRUCTURE X1_DTFS, /* i  : reference DTFS     */
     374             :     DTFS_STRUCTURE X2_DTFS, /* i  : DTFS to shift      */
     375             :     const int16_t num_steps /* i  : resolution         */
     376             : )
     377             : {
     378             :     int16_t k;
     379             :     float maxcorr, corr, tmp, tmp1, fshift, n, diff;
     380             : 
     381             : #define WMC_TOOL_SKIP
     382             :     LOGIC( 1 );
     383           0 :     if ( X1_DTFS.lag < X2_DTFS.lag )
     384             :     {
     385             :         FUNC( 2 );
     386           0 :         DTFS_zeroPadd( X2_DTFS.lag, &X1_DTFS );
     387             :     }
     388             : 
     389             :     MOVE( 1 );
     390             :     ADD( 1 );
     391           0 :     maxcorr = (float) -HUGE_VAL;
     392             :     /* bit-exact optimization - 1/num_steps can be constant => should be counted as a multiply */
     393             :     MOVE( 1 );
     394             :     MULT( 1 );
     395           0 :     diff = (float) X2_DTFS.lag / num_steps;
     396             : 
     397             :     LOOP( 1 );
     398           0 :     for ( fshift = n = 0.0; n < (float) X2_DTFS.lag; n += diff )
     399             :     {
     400             :         MOVE( 2 );
     401           0 :         corr = tmp = 0.0f;
     402             :         MOVE( 1 );
     403             :         MULT( 2 );
     404           0 :         tmp1 = (float) ( PI2 * n / X2_DTFS.lag );
     405             :         ADD( 1 );
     406             : 
     407             :         LOOP( 1 );
     408           0 :         for ( k = 0; k <= min( X2_DTFS.lag >> 1, X2_DTFS.nH_4kHz ); k++, tmp += tmp1 )
     409             : 
     410             :         {
     411             :             MAC( 1 );
     412             :             ADD( 2 );
     413           0 :             corr += (float) ( ( X1_DTFS.a[k] * X2_DTFS.a[k] + X1_DTFS.b[k] * X2_DTFS.b[k] ) * cos( tmp ) );
     414             :             MAC( 1 );
     415             :             ADD( 1 );
     416           0 :             corr += (float) ( ( X1_DTFS.b[k] * X2_DTFS.a[k] - X1_DTFS.a[k] * X2_DTFS.b[k] ) * sin( tmp ) );
     417             :         }
     418             :         LOGIC( 1 );
     419           0 :         if ( corr > maxcorr )
     420             :         {
     421             :             MOVE( 1 );
     422           0 :             fshift = n;
     423             :             MOVE( 1 );
     424           0 :             maxcorr = corr;
     425             :         }
     426             :     }
     427             : #undef WMC_TOOL_SKIP
     428             : 
     429           0 :     return fshift;
     430             : }
     431             : 
     432             : 
     433             : /*-------------------------------------------------------------------*
     434             :  * DTFS_phaseShift()
     435             :  *
     436             :  *  Phase shift the DTFS coefficients.
     437             :  *  ph is the amount of phase shift (between 0 and 2pi), where positive
     438             :  *  value indicates a shift to right, and a negative ph value indicates a
     439             :  *  left shift.
     440             :  *-------------------------------------------------------------------*/
     441             : 
     442           0 : void DTFS_phaseShift(
     443             :     DTFS_STRUCTURE *X, /* i/o: DTFS to shift    */
     444             :     float ph           /* i  : phase to shift   */
     445             : )
     446             : {
     447             :     int16_t k;
     448           0 :     float tmp, tmp2 = 0.0f;
     449             : 
     450             : #define WMC_TOOL_SKIP
     451             :     ADD( 1 );
     452             :     LOOP( 1 );
     453           0 :     for ( k = 0; k <= min( X->lag >> 1, X->nH ); k++, tmp2 += ph )
     454             :     {
     455             :         MOVE( 1 );
     456             :         ADD( 1 );
     457           0 :         tmp = X->a[k];
     458             :         MOVE( 1 );
     459             :         MAC( 1 );
     460           0 :         X->a[k] = (float) ( tmp * cos( tmp2 ) - X->b[k] * sin( tmp2 ) );
     461             :         MOVE( 1 );
     462             :         MAC( 1 );
     463           0 :         X->b[k] = (float) ( tmp * sin( tmp2 ) + X->b[k] * cos( tmp2 ) );
     464             :     }
     465             : #undef WMC_TOOL_SKIP
     466             : 
     467           0 :     return;
     468             : }
     469             : 
     470             : 
     471             : /*-------------------------------------------------------------------*
     472             :  * DTFS_zeroPadd()
     473             :  *
     474             :  *  Zero-pad the DTFS coefficients.
     475             :  *-------------------------------------------------------------------*/
     476             : 
     477           0 : void DTFS_zeroPadd(
     478             :     const int16_t N,  /* i  : Target lag    */
     479             :     DTFS_STRUCTURE *X /* i/o: DTFS          */
     480             : )
     481             : {
     482             :     int16_t i;
     483             :     float diff;
     484             : 
     485             : #define WMC_TOOL_SKIP
     486             :     LOGIC( 1 );
     487           0 :     if ( N == X->lag )
     488             :     {
     489             : #undef WMC_TOOL_SKIP
     490           0 :         return;
     491             : #define WMC_TOOL_SKIP
     492             :     }
     493             :     ADD( 1 );
     494             :     LOOP( 1 );
     495           0 :     for ( i = ( X->lag >> 1 ) + 1; i <= N >> 1; i++ )
     496             :     {
     497             :         MOVE( 2 );
     498           0 :         X->a[i] = X->b[i] = 0.0;
     499             :     }
     500             :     MOVE( 1 );
     501           0 :     X->lag = N;
     502             :     /* recompute nH for new lag */
     503           0 :     X->nH = (int16_t) floor( X->upper_cut_off_freq / ( 12800.0 / X->lag ) );
     504             :     MOVE( 1 );
     505             :     MULT( 1 );
     506           0 :     diff = 12800.0f / X->lag;
     507             :     MULT( 1 );
     508             :     ADD( 1 );
     509             :     LOGIC( 1 );
     510           0 :     if ( X->upper_cut_off_freq - ( diff * X->nH ) >= diff )
     511             :     {
     512           0 :         X->nH++;
     513             :     }
     514             : #undef WMC_TOOL_SKIP
     515             : 
     516           0 :     return;
     517             : }
     518             : 
     519             : 
     520             : /*-------------------------------------------------------------------*
     521             :  * DTFS_to_fs()
     522             :  *
     523             :  * DTFS to Fs conversion.
     524             :  *-------------------------------------------------------------------*/
     525             : 
     526           0 : void DTFS_to_fs(
     527             :     const float *x,              /* i  : time domain signal               */
     528             :     const int16_t N,             /* i  : Length of input vector           */
     529             :     DTFS_STRUCTURE *X,           /* o  : DTFS structure with a, b, lag    */
     530             :     const int32_t sampling_rate, /* i  : sampling rate                    */
     531             :     const int16_t FR_flag        /* i  : FR flag                          */
     532             : )
     533             : {
     534             :     int16_t n;
     535             :     int16_t nH, k, nH_band, nH_4kHz;
     536             :     float sum, tmp, diff;
     537             : 
     538           0 :     if ( !FR_flag )
     539             :     {
     540           0 :         if ( sampling_rate == 16000 )
     541             :         {
     542           0 :             X->upper_cut_off_freq_of_interest = 4000.0;
     543           0 :             X->upper_cut_off_freq = 6400.0;
     544           0 :             X->sampling_rate = INT_FS_12k8;
     545             :         }
     546           0 :         else if ( sampling_rate == 8000 )
     547             :         {
     548           0 :             X->upper_cut_off_freq_of_interest = 3300.0;
     549           0 :             X->upper_cut_off_freq = 4000.0;
     550           0 :             X->sampling_rate = INT_FS_12k8;
     551             :         }
     552             :     }
     553             :     else
     554             :     {
     555           0 :         X->upper_cut_off_freq_of_interest = 8000.0;
     556           0 :         X->upper_cut_off_freq = 8000.0;
     557           0 :         X->sampling_rate = INT_FS_16k;
     558             :     }
     559             : 
     560             : #define WMC_TOOL_SKIP
     561           0 :     X->lag = N;
     562             :     MOVE( 1 );
     563             :     MULT( 1 );
     564           0 :     nH_band = (int16_t) floor( X->upper_cut_off_freq / ( 12800.0 / X->lag ) );
     565             : 
     566           0 :     nH_4kHz = (int16_t) floor( 4000 / ( 12800.0 / X->lag ) );
     567             :     MOVE( 1 );
     568             :     MULT( 1 );
     569           0 :     diff = 12800.0f / X->lag;
     570             :     MULT( 1 );
     571             :     ADD( 1 );
     572             :     LOGIC( 1 );
     573           0 :     if ( X->upper_cut_off_freq - ( diff * nH_band ) >= diff )
     574             :     {
     575           0 :         nH_band++;
     576             :     }
     577           0 :     if ( 4000 - ( diff * nH_4kHz ) >= diff )
     578             :     {
     579           0 :         nH_4kHz++;
     580             :     }
     581             :     /* Number of harmonics excluding the ones at 0 and at pi */
     582             :     MOVE( 1 );
     583             :     MULT( 1 );
     584             :     ADD( 1 );
     585           0 :     nH = ( N - 1 ) >> 1;
     586             :     /* The DC component */
     587           0 :     X->a[0] = 0.0;
     588           0 :     X->b[0] = 0.0;
     589             :     LOOP( 1 );
     590           0 :     for ( n = 0; n < N; n++ )
     591             :     {
     592             :         ADD( 1 );
     593           0 :         X->a[0] += x[n];
     594             :     }
     595             :     MULT( 1 );
     596           0 :     X->a[0] /= N;
     597             : 
     598             :     /* Strictly set the DC componet to zero */
     599             :     MOVE( 1 );
     600           0 :     X->a[0] = 0.0;
     601             : 
     602             :     /* The harmonics excluding the one at pi */
     603             :     LOOP( 1 );
     604           0 :     for ( k = 1; k <= nH; k++ )
     605             :     {
     606           0 :         X->a[k] = x[0];
     607           0 :         X->b[k] = 0.0;
     608             :         MOVE( 2 );
     609             :         MULT( 1 );
     610           0 :         sum = tmp = (float) ( PI2 * k / N );
     611             :         LOOP( 1 );
     612           0 :         for ( n = 1; n < N; n++, sum += tmp )
     613             :         {
     614             :             ADD( 1 );
     615           0 :             X->a[k] += (float) ( x[n] * cos( sum ) );
     616             :             ADD( 1 );
     617           0 :             X->b[k] += (float) ( x[n] * sin( sum ) );
     618             :         }
     619             :         MULT( 2 );
     620           0 :         X->a[k] *= ( 2.0f / N );
     621             :         MULT( 2 );
     622           0 :         X->b[k] *= ( 2.0f / N );
     623             :     }
     624             : 
     625             :     /* The harmonic at 'pi' */
     626             :     LOGIC( 1 );
     627           0 :     if ( N % 2 == 0 )
     628             :     {
     629             :         MOVE( 1 );
     630           0 :         X->a[k] = 0.0;
     631             :         MOVE( 1 );
     632           0 :         tmp = 1.0;
     633             :         LOOP( 1 );
     634           0 :         for ( n = 0; n < N; n++, tmp *= -1.0 )
     635             :         {
     636             :             ADD( 1 );
     637           0 :             X->a[k] += x[n] * tmp;
     638             :         }
     639             :         MULT( 1 );
     640           0 :         X->a[k] /= N;
     641             :         MOVE( 1 );
     642           0 :         X->b[k] = 0.0;
     643             :     }
     644             :     ADD( 1 );
     645             :     LOOP( 1 );
     646           0 :     for ( k = nH_band + 1; k <= min( ( X->lag >> 1 ), ( MAXLAG_WI - 1 ) ); k++ )
     647             :     {
     648             :         MOVE( 1 );
     649           0 :         X->a[k] = 0.0;
     650             :         MOVE( 1 );
     651           0 :         X->b[k] = 0.0;
     652             :     }
     653           0 :     X->nH = nH_band;
     654           0 :     X->nH_4kHz = nH_4kHz;
     655             : #undef WMC_TOOL_SKIP
     656             : 
     657           0 :     return;
     658             : }
     659             : 
     660             : 
     661             : /*-------------------------------------------------------------------*
     662             :  * DTFS_fs_inv()
     663             :  *
     664             :  *  DTFS Inverse
     665             :  *-------------------------------------------------------------------*/
     666             : 
     667           0 : void DTFS_fs_inv(
     668             :     DTFS_STRUCTURE *X, /* i  : DTFS input                         */
     669             :     float *x,          /* o  : time domain sig                    */
     670             :     const int16_t N,   /* i  : Output length                      */
     671             :     float ph0          /* i  : phase shift applied to the output  */
     672             : )
     673             : {
     674             :     float phase, tmp;
     675             :     int16_t k, n;
     676             : 
     677             : #define WMC_TOOL_SKIP
     678             :     LOOP( 1 );
     679           0 :     for ( n = 0; n < N; n++ )
     680             :     {
     681             :         MOVE( 1 );
     682           0 :         x[n] = X->a[0];
     683             :         MOVE( 2 );
     684             :         MAC( 1 );
     685           0 :         tmp = phase = (float) ( PI2 * n / X->lag + ph0 );
     686             :         ADD( 1 );
     687             :         LOOP( 1 );
     688           0 :         for ( k = 1; k <= min( X->lag >> 1, X->nH ); k++, tmp += phase )
     689             :         {
     690             :             MAC( 1 );
     691             :             ADD( 1 );
     692           0 :             x[n] += (float) ( X->a[k] * cos( tmp ) + X->b[k] * sin( tmp ) );
     693             :         }
     694             :     }
     695             : #undef WMC_TOOL_SKIP
     696             : 
     697           0 :     return;
     698             : }
     699             : 
     700             : 
     701             : /*-------------------------------------------------------------------*
     702             :  * DTFS_transform()
     703             :  *
     704             :  *  DTFS transform.
     705             :  *-------------------------------------------------------------------*/
     706             : 
     707           0 : static void DTFS_transform(
     708             :     DTFS_STRUCTURE X,     /* i  : Starting DTFS to use in WI    */
     709             :     DTFS_STRUCTURE X2,    /* i  : Ending DTFS to use in WI      */
     710             :     const float *phase,   /* i  : Phase contour                 */
     711             :     float *out,           /* o  : Output time domain waveform   */
     712             :     int16_t N,            /* i  : Number of samples to generate */
     713             :     const int16_t FR_flag /* i  : Flag to indicate called in FR context */
     714             : )
     715             : {
     716             :     int16_t i, j, j1;
     717             :     float w, tmp;
     718             :     float x1_256[256], x2_256[256];
     719             :     float sum1, sum2;
     720             :     int16_t m, l1, k;
     721             :     int16_t N1;
     722           0 :     float nrg_flag = 0;
     723             :     float x_r_fx[L_FRAME];
     724             :     float temp_w;
     725             :     ivas_error error;
     726             : 
     727             :     DTFS_STRUCTURE *tmp1_dtfs;
     728             :     DTFS_STRUCTURE *tmp2_dtfs;
     729             :     DTFS_STRUCTURE *tmp3_dtfs;
     730             : 
     731           0 :     error = IVAS_ERR_OK;
     732             : 
     733           0 :     if ( ( error = DTFS_new( &tmp1_dtfs ) ) != IVAS_ERR_OK )
     734             :     {
     735           0 :         IVAS_ERROR( error, "Error creating DTFS structure 1" );
     736             :     }
     737           0 :     if ( ( error = DTFS_new( &tmp2_dtfs ) ) != IVAS_ERR_OK )
     738             :     {
     739           0 :         IVAS_ERROR( error, "Error creating DTFS structure 2" );
     740             :     }
     741           0 :     if ( ( error = DTFS_new( &tmp3_dtfs ) ) != IVAS_ERR_OK )
     742             :     {
     743           0 :         IVAS_ERROR( error, "Error creating DTFS structure 3" );
     744             :     }
     745             : 
     746             : #define WMC_TOOL_SKIP
     747             :     FUNC( 2 );
     748           0 :     DTFS_copy( tmp1_dtfs, X );
     749             :     FUNC( 2 );
     750           0 :     DTFS_copy( tmp2_dtfs, X2 );
     751             :     FUNC( 3 );
     752           0 :     DTFS_fast_fs_inv( tmp1_dtfs, x1_256, 256 );
     753             :     FUNC( 3 );
     754           0 :     DTFS_fast_fs_inv( tmp2_dtfs, x2_256, 256 );
     755             :     MOVE( 1 );
     756             :     MAC( 1 );
     757             :     ADD( 1 );
     758             :     LOG( 1 );
     759           0 :     tmp = (float) ( log( 1.0 - WI_THRESHLD ) / ( X.lag - N ) );
     760             :     LOOP( 1 );
     761           0 :     for ( i = 0; i < N; i++ )
     762             :     {
     763           0 :         if ( FR_flag == 0 )
     764             :         {
     765             :             /* should not be counted inside the loop */
     766           0 :             if ( N - WI_SAMPLE_THLD > X.lag )
     767             :             {
     768             :                 /* pre-computed and stored in a table */
     769             :                 MOVE( 1 );
     770           0 :                 w = (float) ( 1.0 - exp( -( i + 1 ) * tmp ) );
     771             :             }
     772             :             else
     773             :             {
     774             :                 /* can be a look-up table */
     775             :                 MOVE( 1 );
     776           0 :                 w = (float) ( i + 1 ) / N;
     777             :             }
     778             :         }
     779             :         else
     780             :         {
     781           0 :             if ( nrg_flag )
     782             :             {
     783           0 :                 w = (float) ( i + 1 ) / N;
     784             :             }
     785             :             else
     786             :             {
     787           0 :                 if ( N <= tmp2_dtfs->lag )
     788             :                 {
     789           0 :                     N = tmp2_dtfs->lag + 1;
     790             :                 }
     791             : 
     792           0 :                 N1 = N - tmp2_dtfs->lag;
     793           0 :                 if ( i < N1 )
     794             :                 {
     795           0 :                     w = (float) ( i + 1 ) / N1;
     796             :                 }
     797             :                 else
     798           0 :                     w = 1.0;
     799             :             }
     800             :         }
     801             : 
     802             :         /* add sinc interpolation of two time domain waveforms at
     803             :         appropriate phase position */
     804             :         MULT( 1 );
     805             :         DIV( 1 );
     806             :         FUNC( 1 );
     807             :         ADD( 1 );
     808           0 :         j = ( LL_OS * 10 + (int) rint_new( phase[i] * LL_OS / PI2 ) ) % LL_OS;
     809             : 
     810           0 :         if ( j < 0 )
     811             :         {
     812           0 :             j = 0;
     813             :         }
     814             : 
     815             :         MOVE( 1 );
     816             :         DIV( 1 );
     817           0 :         k = j % WARP_OS_RATE;
     818             :         MOVE( 1 );
     819             :         MULT( 1 );
     820           0 :         l1 = j / WARP_OS_RATE;
     821             :         MOVE( 2 );
     822             : 
     823           0 :         set_f( x_r_fx, 0.0f, L_FRAME );
     824             : 
     825           0 :         temp_w = ( 1 - w );
     826             : 
     827           0 :         for ( j1 = 0; j1 < 12; j1++ )
     828             :         {
     829           0 :             m = ( 1000 * LL + l1 - OSLENGTH / 2 + j1 ) % LL;
     830             : 
     831           0 :             if ( m < 0 )
     832             :             {
     833           0 :                 m = 0;
     834             :             }
     835             : 
     836           0 :             x_r_fx[m] = x1_256[m] * temp_w + x2_256[m] * w;
     837             :         }
     838             : 
     839             :         LOOP( 1 );
     840           0 :         for ( j1 = 0, sum1 = sum2 = 0.0; j1 < OSLENGTH; j1++ )
     841             :         {
     842             :             /* mult or div by constants should be done once outside the loop */
     843             :             DIV( 1 );
     844             :             ADD( 1 );
     845           0 :             m = ( 1000 * LL + l1 - OSLENGTH / 2 + j1 ) % LL;
     846             : 
     847           0 :             if ( m < 0 )
     848             :             {
     849           0 :                 m = 0;
     850             :             }
     851             : 
     852           0 :             sum1 += x_r_fx[m] * sinc[k][j1];
     853             :         }
     854             : 
     855           0 :         out[i] = sum1;
     856             :     }
     857             : #undef WMC_TOOL_SKIP
     858             : 
     859           0 :     free( tmp1_dtfs );
     860           0 :     free( tmp2_dtfs );
     861           0 :     free( tmp3_dtfs );
     862             : 
     863           0 :     return;
     864             : }
     865             : 
     866             : 
     867             : /*-------------------------------------------------------------------*
     868             :  * DTFS_zeroFilter()
     869             :  *
     870             :  *  DTFS zero filter response.
     871             :  *-------------------------------------------------------------------*/
     872             : 
     873           0 : void DTFS_zeroFilter(
     874             :     DTFS_STRUCTURE *X, /* i/o: DTFS to zeroFilter inplace  */
     875             :     const float *LPC,  /* i  : LPCs                        */
     876             :     const int16_t N    /* i  : LPC order                   */
     877             : )
     878             : {
     879             :     float tmp, tmp1, tmp2, sum1, sum2;
     880             :     int16_t k, n;
     881             : 
     882             : #define WMC_TOOL_SKIP
     883             :     MOVE( 1 );
     884             :     MULT( 1 );
     885           0 :     tmp1 = (float) ( PI2 / X->lag );
     886             :     LOOP( 1 );
     887           0 :     for ( k = 0; k <= min( X->lag >> 1, X->nH ); k++ )
     888             :     {
     889             :         MOVE( 2 );
     890             :         MULT( 1 );
     891           0 :         tmp = tmp2 = k * tmp1;
     892             :         /* Calculate sum1 and sum2 */
     893             :         MOVE( 1 );
     894           0 :         sum1 = 1.0;
     895             :         MOVE( 1 );
     896           0 :         sum2 = 0.0;
     897             :         ADD( 1 );
     898             :         LOOP( 1 );
     899           0 :         for ( n = 0; n < N; n++, tmp2 += tmp )
     900             :         {
     901             :             MULT( 1 );
     902             :             ADD( 2 );
     903           0 :             sum1 += (float) ( LPC[n] * cos( tmp2 ) );
     904             :             MULT( 1 );
     905             :             ADD( 1 );
     906           0 :             sum2 += (float) ( LPC[n] * sin( tmp2 ) );
     907             :         }
     908             :         /* Calculate the circular convolution */
     909             :         MOVE( 1 );
     910           0 :         tmp = X->a[k];
     911             :         MOVE( 1 );
     912             :         MAC( 1 );
     913           0 :         X->a[k] = tmp * sum1 - X->b[k] * sum2;
     914             :         MOVE( 1 );
     915             :         MAC( 1 );
     916           0 :         X->b[k] = X->b[k] * sum1 + tmp * sum2;
     917             :     }
     918             : #undef WMC_TOOL_SKIP
     919             : 
     920           0 :     return;
     921             : }
     922             : 
     923             : 
     924             : /*-------------------------------------------------------------------*
     925             :  * DTFS_poleFilter()
     926             :  *
     927             :  *  DTFS pole filter response.
     928             :  *-------------------------------------------------------------------*/
     929             : 
     930           0 : void DTFS_poleFilter(
     931             :     DTFS_STRUCTURE *X, /* i/o: DTFS to poleFilter inplace */
     932             :     const float *LPC,  /* i  : LPCs                       */
     933             :     const int16_t N    /* i  : LPC order                  */
     934             : )
     935             : {
     936             :     float tmp, tmp1, tmp2, sum1, sum2;
     937             :     int16_t k, n;
     938             : 
     939             : #define WMC_TOOL_SKIP
     940             :     MOVE( 1 );
     941             :     MULT( 1 );
     942           0 :     tmp1 = (float) ( PI2 / X->lag );
     943             :     LOOP( 1 );
     944           0 :     for ( k = 0; k <= min( X->lag >> 1, X->nH ); k++ )
     945             :     {
     946             :         MOVE( 2 );
     947             :         MULT( 1 );
     948           0 :         tmp = tmp2 = k * tmp1;
     949             :         /* Calculate sum1 and sum2 */
     950             :         MOVE( 1 );
     951           0 :         sum1 = 1.0;
     952             :         MOVE( 1 );
     953           0 :         sum2 = 0.0;
     954             :         ADD( 1 );
     955             :         LOOP( 1 );
     956           0 :         for ( n = 0; n < N; n++, tmp2 += tmp )
     957             :         {
     958             :             MULT( 1 );
     959             :             ADD( 2 );
     960           0 :             sum1 += (float) ( LPC[n] * cos( tmp2 ) );
     961             :             MULT( 1 );
     962             :             ADD( 1 );
     963           0 :             sum2 += (float) ( LPC[n] * sin( tmp2 ) );
     964             :         }
     965             :         /* Calculate the circular convolution */
     966             :         MOVE( 1 );
     967           0 :         tmp = X->a[k];
     968             :         MAC( 1 );
     969           0 :         tmp2 = sum1 * sum1 + sum2 * sum2;
     970             :         MAC( 1 );
     971             :         DIV( 1 );
     972           0 :         X->a[k] = ( tmp * sum1 + X->b[k] * sum2 ) / tmp2;
     973             :         MAC( 1 );
     974             :         ADD( 1 );
     975           0 :         X->b[k] = ( -tmp * sum2 + X->b[k] * sum1 ) / tmp2;
     976             :     }
     977             : #undef WMC_TOOL_SKIP
     978             : 
     979           0 :     return;
     980             : }
     981             : 
     982             : 
     983             : /*-------------------------------------------------------------------*
     984             :  * DTFS_setEngy()
     985             :  *
     986             :  *  Set DTFS energy.
     987             :  *-------------------------------------------------------------------*/
     988             : 
     989           0 : static float DTFS_setEngy(
     990             :     DTFS_STRUCTURE *X_DTFS, /* i/o: DTFS structure to set engy */
     991             :     float en2               /* i  : Energy to set to           */
     992             : )
     993             : {
     994             :     int16_t k;
     995             :     float en1, tmp;
     996             : 
     997             : #define WMC_TOOL_SKIP
     998             :     FUNC( 1 );
     999             :     MOVE( 1 );
    1000           0 :     en1 = DTFS_getEngy( *X_DTFS );
    1001             :     LOGIC( 1 );
    1002           0 :     if ( en1 == 0.0 )
    1003             :     {
    1004             : #undef WMC_TOOL_SKIP
    1005           0 :         return 0.0;
    1006             : #define WMC_TOOL_SKIP
    1007             :     }
    1008             :     MOVE( 1 );
    1009             :     DIV( 1 );
    1010             :     SQRT( 1 );
    1011           0 :     tmp = (float) sqrt( en2 / en1 );
    1012             :     LOOP( 1 );
    1013           0 :     for ( k = 0; k <= min( X_DTFS->lag >> 1, X_DTFS->nH ); k++ )
    1014             :     {
    1015             :         MULT( 1 );
    1016           0 :         X_DTFS->a[k] *= tmp;
    1017             :         MULT( 1 );
    1018           0 :         X_DTFS->b[k] *= tmp;
    1019             :     }
    1020             : #undef WMC_TOOL_SKIP
    1021             : 
    1022           0 :     return en1;
    1023             : }
    1024             : 
    1025             : 
    1026             : /*-------------------------------------------------------------------*
    1027             :  * DTFS_adjustLag()
    1028             :  *
    1029             :  *  Adjust DTFS lag based on a target lag.
    1030             :  *-------------------------------------------------------------------*/
    1031             : 
    1032           0 : void DTFS_adjustLag(
    1033             :     DTFS_STRUCTURE *X_DTFS, /* i/o: DTFS to adjust lag for */
    1034             :     const int16_t N         /* i  : Target lag             */
    1035             : )
    1036             : {
    1037             :     int16_t k;
    1038             :     float en, diff;
    1039             : 
    1040             : #define WMC_TOOL_SKIP
    1041             :     LOGIC( 1 );
    1042           0 :     if ( N == X_DTFS->lag )
    1043             :     {
    1044             : #undef WMC_TOOL_SKIP
    1045           0 :         return;
    1046             : #define WMC_TOOL_SKIP
    1047             :     }
    1048             : 
    1049             :     LOGIC( 1 );
    1050           0 :     if ( N > X_DTFS->lag )
    1051             :     {
    1052             : 
    1053             :         FUNC( 2 );
    1054           0 :         DTFS_zeroPadd( N, X_DTFS );
    1055             :     }
    1056             :     else
    1057             :     {
    1058             :         FUNC( 1 );
    1059             :         MOVE( 1 );
    1060           0 :         en = DTFS_getEngy( *X_DTFS );
    1061             :         ADD( 1 );
    1062             :         LOOP( 1 );
    1063           0 :         for ( k = ( N >> 1 ) + 1; k <= min( X_DTFS->lag >> 1, X_DTFS->nH ); k++ )
    1064             :         {
    1065             :             MOVE( 1 );
    1066           0 :             X_DTFS->a[k] = 0.0;
    1067             :             MOVE( 1 );
    1068           0 :             X_DTFS->b[k] = 0.0;
    1069             :         }
    1070             :         FUNC( 2 );
    1071           0 :         DTFS_setEngy( X_DTFS, en );
    1072             :         MOVE( 1 );
    1073           0 :         X_DTFS->lag = N;
    1074             :         /* recompute nH for new lag */
    1075           0 :         X_DTFS->nH = (int16_t) floor( X_DTFS->upper_cut_off_freq / ( 12800.0 / X_DTFS->lag ) );
    1076             : 
    1077           0 :         X_DTFS->nH_4kHz = (int16_t) floor( 4000.0 / ( 12800.0 / X_DTFS->lag ) );
    1078             :         MOVE( 1 );
    1079             :         MULT( 1 );
    1080           0 :         diff = 12800.0f / X_DTFS->lag;
    1081             :         MULT( 1 );
    1082             :         ADD( 1 );
    1083             :         LOGIC( 1 );
    1084           0 :         if ( X_DTFS->upper_cut_off_freq - ( diff * X_DTFS->nH ) >= diff )
    1085             :         {
    1086           0 :             X_DTFS->nH++;
    1087             :         }
    1088           0 :         if ( 4000.0 - ( diff * X_DTFS->nH_4kHz ) >= diff )
    1089             :         {
    1090           0 :             X_DTFS->nH_4kHz++;
    1091             :         }
    1092             :     }
    1093             : #undef WMC_TOOL_SKIP
    1094             : 
    1095           0 :     return;
    1096             : }
    1097             : 
    1098             : 
    1099             : /*-------------------------------------------------------------------*
    1100             :  * DTFS_getEngy()
    1101             :  *
    1102             :  *  Get DTFS energy.
    1103             :  *-------------------------------------------------------------------*/
    1104             : 
    1105           0 : float DTFS_getEngy(
    1106             :     DTFS_STRUCTURE X /* i  : DTFS to compute energy of */
    1107             : )
    1108             : {
    1109             :     int16_t k;
    1110             :     float en;
    1111             : 
    1112           0 :     en = 0.0f;
    1113             : #define WMC_TOOL_SKIP
    1114             :     LOOP( 1 );
    1115           0 :     for ( k = 1; k <= min( ( X.lag - 1 ) >> 1, X.nH ); k++ )
    1116             :     {
    1117             :         MAC( 1 );
    1118             :         ADD( 1 );
    1119           0 :         en += X.a[k] * X.a[k] + X.b[k] * X.b[k];
    1120             :     }
    1121             :     MULT( 1 );
    1122           0 :     en /= 2.0;
    1123             :     MULT( 1 );
    1124             :     ADD( 1 );
    1125           0 :     en += X.a[0] * X.a[0];
    1126             :     LOGIC( 1 );
    1127           0 :     if ( X.lag % 2 == 0 )
    1128             :     {
    1129             :         MAC( 1 );
    1130             :         ADD( 1 );
    1131           0 :         en += X.a[k] * X.a[k] + X.b[k] * X.b[k];
    1132             :     }
    1133             : #undef WMC_TOOL_SKIP
    1134             : 
    1135           0 :     return en;
    1136             : }
    1137             : 
    1138             : 
    1139             : /*-------------------------------------------------------------------*
    1140             :  * DTFS_car2pol()
    1141             :  *
    1142             :  *  DTFS cartesian to polar co-ordinates conversion.
    1143             :  *-------------------------------------------------------------------*/
    1144             : 
    1145           0 : void DTFS_car2pol(
    1146             :     DTFS_STRUCTURE *X /* i/o: DTFS structure a, b, lag  */
    1147             : )
    1148             : {
    1149             :     int16_t k;
    1150             :     float tmp;
    1151             : 
    1152             : #define WMC_TOOL_SKIP
    1153             :     LOOP( 1 );
    1154           0 :     for ( k = 1; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++ )
    1155             :     {
    1156             :         MOVE( 1 );
    1157           0 :         tmp = X->a[k];
    1158             :         MOVE( 1 );
    1159             :         FUNC( 2 );
    1160             :         MULT( 1 );
    1161           0 :         X->a[k] = (float) ( 0.5f * sqrt( tmp * tmp + X->b[k] * X->b[k] ) );
    1162             :         MOVE( 1 );
    1163           0 :         X->b[k] = (float) atan2( X->b[k], tmp );
    1164             :     }
    1165             :     LOGIC( 1 );
    1166           0 :     if ( X->lag % 2 == 0 )
    1167             :     {
    1168             :         MOVE( 1 );
    1169           0 :         tmp = X->a[k];
    1170             :         FUNC( 2 );
    1171             :         MOVE( 1 );
    1172           0 :         X->a[k] = (float) sqrt( tmp * tmp + X->b[k] * X->b[k] );
    1173             :         MOVE( 1 );
    1174           0 :         X->b[k] = (float) atan2( X->b[k], tmp );
    1175             :     }
    1176             : #undef WMC_TOOL_SKIP
    1177             : 
    1178           0 :     return;
    1179             : }
    1180             : 
    1181             : 
    1182             : /*-------------------------------------------------------------------*
    1183             :  * DTFS_pol2car()
    1184             :  *
    1185             :  *  DTFS polar to cartesian co-ordinates conversion.
    1186             :  *-------------------------------------------------------------------*/
    1187             : 
    1188           0 : void DTFS_pol2car(
    1189             :     DTFS_STRUCTURE *X /* i/o: DTFS structure a, b, lag  */
    1190             : )
    1191             : {
    1192             :     int16_t k;
    1193             :     float tmp;
    1194             : 
    1195             : #define WMC_TOOL_SKIP
    1196             :     LOOP( 1 );
    1197           0 :     for ( k = 1; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++ )
    1198             :     {
    1199             :         MOVE( 1 );
    1200           0 :         tmp = X->b[k];
    1201             :         MOVE( 1 );
    1202             :         MULT( 2 );
    1203           0 :         X->b[k] = (float) ( 2.0f * X->a[k] * sin( tmp ) );
    1204             :         MOVE( 1 );
    1205             :         MULT( 2 );
    1206           0 :         X->a[k] = (float) ( 2.0f * X->a[k] * cos( tmp ) );
    1207             :     }
    1208             :     LOGIC( 1 );
    1209           0 :     if ( X->lag % 2 == 0 )
    1210             :     {
    1211             :         MOVE( 1 );
    1212           0 :         tmp = X->b[k];
    1213             :         MOVE( 1 );
    1214             :         MULT( 1 );
    1215           0 :         X->b[k] = (float) ( X->a[k] * sin( tmp ) );
    1216             :         MOVE( 1 );
    1217             :         MULT( 1 );
    1218           0 :         X->a[k] = (float) ( X->a[k] * cos( tmp ) );
    1219             :     }
    1220             : #undef WMC_TOOL_SKIP
    1221             : 
    1222           0 :     return;
    1223             : }
    1224             : 
    1225             : 
    1226             : /*-------------------------------------------------------------------*
    1227             :  * DTFS_setEngyHarm()
    1228             :  *
    1229             :  *  Adjust DTFS energy based on the input target energy.
    1230             :  *-------------------------------------------------------------------*/
    1231             : 
    1232             : /*! r: Input RMS between f1 and f2 before scaling  */
    1233           0 : float DTFS_setEngyHarm(
    1234             :     float f1,         /* i  : lower band freq of input to control energy   */
    1235             :     float f2,         /* i  : upper band freq of input to control energy   */
    1236             :     float g1,         /* i  : lower band freq of output to control energy  */
    1237             :     float g2,         /* i  : upper band freq of output to control energy  */
    1238             :     float en2,        /* i  : Target Energy to set the DTFS to             */
    1239             :     DTFS_STRUCTURE *X /* i/o: DTFS to adjust the energy of                 */
    1240             : )
    1241             : {
    1242             :     int16_t k, count;
    1243             :     float en1, tmp, factor, diff;
    1244             : 
    1245           0 :     diff = (float) INT_FS_12k8 / X->lag;
    1246             : 
    1247           0 :     en1 = 0.0f;
    1248           0 :     count = 0;
    1249             : 
    1250             : #define WMC_TOOL_SKIP
    1251             :     LOGIC( 1 );
    1252           0 :     if ( f1 == 0.0 )
    1253             :     {
    1254             :         MULT( 1 );
    1255             :         ADD( 1 );
    1256           0 :         en1 += X->a[0] * X->a[0];
    1257           0 :         count++;
    1258             :     }
    1259             :     MOVE( 1 );
    1260             :     ADD( 1 );
    1261             :     ADD( 1 );
    1262             :     LOOP( 1 );
    1263           0 :     for ( k = 1, tmp = diff; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++, tmp += diff )
    1264             :     {
    1265           0 :         if ( X->a[k] < EPSILON )
    1266             :         {
    1267           0 :             X->a[k] = 0;
    1268             :         }
    1269             : 
    1270             :         LOGIC( 1 );
    1271           0 :         if ( tmp > f1 && tmp <= f2 )
    1272             :         {
    1273             :             MULT( 1 );
    1274             :             ADD( 1 );
    1275           0 :             en1 += X->a[k] * X->a[k];
    1276           0 :             count++;
    1277             :         }
    1278             :     }
    1279             : 
    1280           0 :     if ( count <= 0.0 )
    1281             :     {
    1282           0 :         count = 1;
    1283             :     }
    1284             : 
    1285             : 
    1286             :     DIV( 1 );
    1287           0 :     en1 /= count;
    1288             : 
    1289           0 :     if ( en2 < 0.0 )
    1290             :     {
    1291           0 :         en2 = 0.0;
    1292             :     }
    1293             : 
    1294             :     LOGIC( 1 );
    1295           0 :     if ( en1 > 0.0 )
    1296             :     {
    1297             :         MOVE( 1 );
    1298             :         DIV( 1 );
    1299             :         SQRT( 1 );
    1300           0 :         factor = (float) sqrt( en2 / en1 );
    1301             :     }
    1302             :     else
    1303             :     {
    1304             :         MOVE( 1 );
    1305           0 :         factor = 0.0f;
    1306             :     }
    1307             :     LOGIC( 1 );
    1308           0 :     if ( g1 == 0.0 )
    1309             :     {
    1310             :         MULT( 1 );
    1311           0 :         X->a[k] *= factor;
    1312             :     }
    1313             :     MOVE( 1 );
    1314             :     ADD( 1 );
    1315             :     ADD( 1 );
    1316             :     LOOP( 1 );
    1317           0 :     for ( k = 1, tmp = diff; k <= min( ( X->lag - 1 ) >> 1, X->nH ); k++, tmp += diff )
    1318             :     {
    1319             :         ADD( 1 );
    1320             :         ADD( 1 );
    1321             :         LOGIC( 1 );
    1322           0 :         if ( tmp > g1 && tmp <= g2 )
    1323             :         {
    1324             :             MULT( 1 );
    1325           0 :             X->a[k] *= factor;
    1326             :         }
    1327             :     }
    1328             : #undef WMC_TOOL_SKIP
    1329             : 
    1330           0 :     return (float) ( en1 + 1e-20 );
    1331             : }
    1332             : 
    1333             : 
    1334             : /*-------------------------------------------------------------------*
    1335             :  * cubicPhase()
    1336             :  *
    1337             :  * Compute coefficients of cubic phase function
    1338             :  *-------------------------------------------------------------------*/
    1339             : 
    1340           0 : static void cubicPhase(
    1341             :     float ph1,      /* i  : phase offset       */
    1342             :     float ph2,      /* i  : phase 2            */
    1343             :     const float L1, /* i  : previous lag       */
    1344             :     const float L2, /* i  : current lag        */
    1345             :     int16_t N,      /* i  : input length       */
    1346             :     float *phOut    /* o  : cubic phase output */
    1347             : )
    1348             : {
    1349             :     float coef[4], f1, f2, c1, c2, factor;
    1350             :     int16_t n;
    1351             :     double diff;
    1352             : 
    1353             : #define WMC_TOOL_SKIP
    1354             :     ADD( 1 );
    1355           0 :     N -= (int16_t) L2;
    1356             : 
    1357           0 :     if ( N <= 0 )
    1358             :     {
    1359           0 :         N = 1;
    1360             :     }
    1361             : 
    1362             :     /* Computation of the coefficients of the cubic phase function */
    1363             :     MOVE( 1 );
    1364             :     DIV( 1 );
    1365           0 :     f1 = (float) ( PI2 / L1 );
    1366             :     MOVE( 1 );
    1367             :     DIV( 1 );
    1368           0 :     f2 = (float) ( PI2 / L2 );
    1369             :     MOVE( 1 );
    1370             :     DIV( 1 );
    1371           0 :     ph1 = (float) fmod( (double) ( ph1 ), PI2 );
    1372             :     MOVE( 1 );
    1373             :     DIV( 1 );
    1374           0 :     ph2 = (float) fmod( (double) ( ph2 ), PI2 );
    1375             :     MOVE( 1 );
    1376           0 :     coef[3] = ph1;
    1377             :     MOVE( 1 );
    1378           0 :     coef[2] = f1;
    1379             :     MOVE( 1 );
    1380             :     MAC( 1 );
    1381             :     ADD( 1 );
    1382             :     FUNC( 1 );
    1383             :     ADD( 1 );
    1384           0 :     factor = (float) ( anint( ( ph1 - ph2 + 0.5 * N * ( f2 + f1 ) ) / PI2 ) );
    1385             :     MOVE( 1 );
    1386             :     ADD( 1 );
    1387           0 :     c1 = f2 - f1;
    1388             :     MOVE( 1 );
    1389             :     MAC( 1 );
    1390             :     ADD( 2 );
    1391           0 :     c2 = (float) ( ph2 - ph1 - N * f1 + PI2 * factor );
    1392             :     MOVE( 1 );
    1393             :     MAC( 1 );
    1394             :     DIV( 1 );
    1395           0 :     coef[0] = ( N * c1 - 2 * c2 ) / ( N * N * N );
    1396             :     MOVE( 1 );
    1397             :     MULT( 4 );
    1398             :     DIV( 1 );
    1399             :     ADD( 1 );
    1400           0 :     coef[1] = ( c1 - 3 * N * N * coef[0] ) / ( 2 * N );
    1401             :     /* Computation of the phase value at each sample point */
    1402             :     MOVE( 1 );
    1403           0 :     phOut[0] = ph1;
    1404             :     LOOP( 1 );
    1405           0 :     for ( n = 1; n < N; n++ )
    1406             :     {
    1407             :         MOVE( 1 );
    1408           0 :         phOut[n] = _POLY3( n, coef );
    1409             :     }
    1410             :     MOVE( 1 );
    1411             :     MULT( 1 );
    1412           0 :     diff = (float) ( PI2 / L2 );
    1413             :     ADD( 1 );
    1414             :     LOOP( 1 );
    1415           0 :     for ( ; n < N + (int) L2; n++ )
    1416             :     {
    1417             :         MOVE( 1 );
    1418             :         ADD( 2 );
    1419           0 :         phOut[n] = (float) ( phOut[n - 1] + diff );
    1420             :     }
    1421             : #undef WMC_TOOL_SKIP
    1422             : 
    1423           0 :     return;
    1424             : }
    1425             : 
    1426             : 
    1427             : /*-------------------------------------------------------------------*
    1428             :  * DTFS_to_erb()
    1429             :  *
    1430             :  * DTFS to ERB conversion
    1431             :  *-------------------------------------------------------------------*/
    1432             : 
    1433           0 : void DTFS_to_erb(
    1434             :     DTFS_STRUCTURE X, /* i  : DTFS input       */
    1435             :     float *out        /* o  : ERB output       */
    1436             : )
    1437             : {
    1438             :     int16_t num_erb;
    1439             :     uint16_t i, j, count[NUM_ERB_WB];
    1440             :     float freq, diff;
    1441             : 
    1442           0 :     const float *erb = NULL;
    1443           0 :     num_erb = NUM_ERB_NB;
    1444           0 :     if ( X.upper_cut_off_freq == 4000.0 )
    1445             :     {
    1446           0 :         num_erb = NUM_ERB_NB;
    1447           0 :         erb = &( erb_NB[0] );
    1448             :     }
    1449           0 :     else if ( X.upper_cut_off_freq == 6400.0 )
    1450             :     {
    1451           0 :         num_erb = NUM_ERB_WB;
    1452           0 :         erb = &( erb_WB[0] );
    1453             :     }
    1454             : 
    1455             : #define WMC_TOOL_SKIP
    1456             :     LOOP( 1 );
    1457           0 :     for ( i = 0; i < num_erb; i++ )
    1458             :     {
    1459             :         MOVE( 1 );
    1460           0 :         count[i] = 0;
    1461             :         MOVE( 1 );
    1462           0 :         out[i] = 0.0;
    1463             :     }
    1464             :     MOVE( 1 );
    1465             :     MULT( 1 );
    1466           0 :     diff = 12800.0f / X.lag;
    1467             :     MOVE( 2 );
    1468             :     ADD( 1 );
    1469             :     LOOP( 1 );
    1470           0 :     for ( i = j = 0, freq = 0.0; i <= min( X.lag >> 1, X.nH ); i++, freq += diff )
    1471             :     {
    1472           0 :         if ( !( freq <= erb[num_erb] ) )
    1473             :         {
    1474           0 :             freq = erb[num_erb];
    1475             :         }
    1476             : 
    1477             :         LOOP( 1 );
    1478           0 :         for ( ; j < num_erb; j++ )
    1479             :         {
    1480             :             LOGIC( 1 );
    1481           0 :             if ( freq < erb[j + 1] )
    1482             :             {
    1483           0 :                 if ( X.a[i] < 0.0f )
    1484             :                 {
    1485           0 :                     X.a[i] = 0.0f;
    1486             :                 }
    1487             : 
    1488             :                 ADD( 1 );
    1489           0 :                 out[j] += X.a[i];
    1490           0 :                 count[j]++;
    1491           0 :                 break;
    1492             :             }
    1493             :         }
    1494             :     }
    1495             :     LOOP( 1 );
    1496           0 :     for ( i = 0; i < num_erb; i++ )
    1497             :     {
    1498             :         LOGIC( 1 );
    1499           0 :         if ( count[i] > 1 )
    1500             :         {
    1501             :             DIV( 1 );
    1502           0 :             out[i] /= count[i];
    1503             :         }
    1504             :     }
    1505             : #undef WMC_TOOL_SKIP
    1506             : 
    1507           0 :     return;
    1508             : }
    1509             : 
    1510             : 
    1511             : /*-------------------------------------------------------------------*
    1512             :  * erb_slot()
    1513             :  *
    1514             :  * Estimation of ERB slots.
    1515             :  *-------------------------------------------------------------------*/
    1516             : 
    1517           0 : void erb_slot(
    1518             :     int16_t lag,    /* i  : input lag          */
    1519             :     int16_t *out,   /* o  : ERB slots          */
    1520             :     float *mfreq,   /* i  : ERB frequencies    */
    1521             :     int16_t num_erb /* i  : number of ERBs     */
    1522             : )
    1523             : {
    1524             :     uint16_t i, j;
    1525             :     float freq, diff;
    1526             :     int16_t upper_cut_off_freq;
    1527           0 :     const float *erb = NULL;
    1528             :     int16_t nH_band;
    1529             : 
    1530           0 :     upper_cut_off_freq = 4000;
    1531           0 :     if ( num_erb == NUM_ERB_NB )
    1532             :     {
    1533           0 :         upper_cut_off_freq = 4000;
    1534           0 :         erb = &( erb_NB[0] );
    1535             :     }
    1536           0 :     else if ( num_erb == NUM_ERB_WB )
    1537             :     {
    1538           0 :         upper_cut_off_freq = 6400;
    1539           0 :         erb = &( erb_WB[0] );
    1540             :     }
    1541             : 
    1542             : #define WMC_TOOL_SKIP
    1543             :     MOVE( 1 );
    1544             :     MULT( 1 );
    1545           0 :     nH_band = (int16_t) floor( upper_cut_off_freq / ( 12800.0 / lag ) );
    1546             : 
    1547             :     LOOP( 1 );
    1548           0 :     for ( i = 0; i < num_erb; i++ )
    1549             :     {
    1550             :         MOVE( 1 );
    1551           0 :         out[i] = 0;
    1552             :         MOVE( 1 );
    1553           0 :         mfreq[i] = 0.0;
    1554             :     }
    1555             :     MOVE( 1 );
    1556             :     MULT( 1 );
    1557           0 :     diff = 12800.0f / lag;
    1558             :     MULT( 1 );
    1559             :     ADD( 1 );
    1560             :     LOGIC( 1 );
    1561           0 :     if ( upper_cut_off_freq - ( diff * nH_band ) >= diff )
    1562             :     {
    1563           0 :         nH_band++;
    1564             :     }
    1565             :     MOVE( 2 );
    1566             :     ADD( 1 );
    1567             :     LOOP( 1 );
    1568           0 :     for ( i = j = 0, freq = 0.0; i <= min( lag >> 1, nH_band ); i++, freq += diff )
    1569             :     {
    1570             : 
    1571           0 :         if ( !( freq <= erb[num_erb] ) )
    1572             :         {
    1573           0 :             freq = erb[num_erb];
    1574             :         }
    1575             : 
    1576             :         MOVE( 1 );
    1577           0 :         freq = min( freq, upper_cut_off_freq );
    1578             : 
    1579             :         LOOP( 1 );
    1580           0 :         for ( ; j < num_erb; j++ )
    1581             :         {
    1582             :             LOGIC( 1 );
    1583           0 :             if ( freq < erb[j + 1] )
    1584             :             {
    1585             :                 ADD( 1 );
    1586           0 :                 mfreq[j] += freq;
    1587           0 :                 out[j]++;
    1588           0 :                 break;
    1589             :             }
    1590             :         }
    1591             :     }
    1592             :     LOOP( 1 );
    1593           0 :     for ( j = 0; j < num_erb; j++ )
    1594             :     {
    1595             :         LOGIC( 1 );
    1596           0 :         if ( out[j] > 1 )
    1597             :         {
    1598             :             DIV( 1 );
    1599           0 :             mfreq[j] /= out[j];
    1600             :         }
    1601             :     }
    1602             : #undef WMC_TOOL_SKIP
    1603             : 
    1604           0 :     return;
    1605             : }
    1606             : 
    1607             : 
    1608             : /*-------------------------------------------------------------------*
    1609             :  * DTFS_erb_inv()
    1610             :  *
    1611             :  * .DTFS after ERB inverse
    1612             :  *-------------------------------------------------------------------*/
    1613             : 
    1614           0 : void DTFS_erb_inv(
    1615             :     float *in,            /* i  : ERB inpt                      */
    1616             :     int16_t *slot,        /* i  : ERB slots filled based on lag */
    1617             :     float *mfreq,         /* i  : erb frequence edges           */
    1618             :     DTFS_STRUCTURE *X,    /* o  : DTFS after erb-inv            */
    1619             :     const int16_t num_erb /* i  : Number of ERB bands           */
    1620             : )
    1621             : {
    1622           0 :     int16_t i, j, m = 0;
    1623             :     float diff;
    1624             :     float freq, f[NUM_ERB_WB + 2], amp[NUM_ERB_WB + 2];
    1625           0 :     int16_t upper_cut_off_freq = 0;
    1626             : 
    1627           0 :     const float *erb = NULL;
    1628             : 
    1629           0 :     if ( num_erb == NUM_ERB_NB )
    1630             :     {
    1631           0 :         upper_cut_off_freq = 4000;
    1632           0 :         erb = &( erb_NB[0] );
    1633             :     }
    1634           0 :     else if ( num_erb == NUM_ERB_WB )
    1635             :     {
    1636           0 :         upper_cut_off_freq = 6400;
    1637           0 :         erb = &( erb_WB[0] );
    1638             :     }
    1639             : 
    1640             : #define WMC_TOOL_SKIP
    1641             :     MOVE( 1 );
    1642           0 :     f[m] = 0.0;
    1643             :     MOVE( 1 );
    1644           0 :     amp[m] = 0.0;
    1645           0 :     m++;
    1646             :     LOOP( 1 );
    1647           0 :     for ( i = 0; i < num_erb; i++ )
    1648             :     {
    1649             :         LOGIC( 1 );
    1650           0 :         if ( slot[i] != 0 )
    1651             :         {
    1652             :             MOVE( 1 );
    1653           0 :             f[m] = mfreq[i];
    1654             :             MOVE( 1 );
    1655           0 :             amp[m] = in[i];
    1656           0 :             m++;
    1657             :         }
    1658             :     }
    1659             :     MOVE( 1 );
    1660           0 :     f[m] = upper_cut_off_freq;
    1661             :     MOVE( 1 );
    1662           0 :     amp[m] = 0.0;
    1663           0 :     m++;
    1664             : 
    1665             :     MOVE( 1 );
    1666             :     MULT( 1 );
    1667           0 :     diff = 12800.0f / X->lag;
    1668             : 
    1669             :     MOVE( 2 );
    1670             :     ADD( 1 );
    1671             :     LOOP( 1 );
    1672           0 :     for ( i = 0, j = 1, freq = 0.0; i <= min( X->lag >> 1, X->nH ); i++, freq += diff )
    1673             :     {
    1674           0 :         if ( !( freq <= erb[num_erb] ) )
    1675             :         {
    1676           0 :             freq = erb[num_erb];
    1677             :         }
    1678             : 
    1679           0 :         if ( !( m <= num_erb + 2 ) )
    1680             :         {
    1681           0 :             m = num_erb + 2;
    1682             :         }
    1683             : 
    1684             :         LOGIC( 1 );
    1685           0 :         if ( freq > upper_cut_off_freq )
    1686             :         {
    1687             :             MOVE( 1 );
    1688           0 :             freq = upper_cut_off_freq;
    1689             :         }
    1690             :         LOOP( 1 );
    1691           0 :         for ( ; j < m; j++ )
    1692             :         {
    1693             :             LOGIC( 1 );
    1694           0 :             if ( freq <= f[j] )
    1695             :             {
    1696             :                 MOVE( 1 );
    1697             :                 MAC( 2 );
    1698             :                 ADD( 1 );
    1699           0 :                 X->a[i] = amp[j] * ( freq - f[j - 1] ) + amp[j - 1] * ( f[j] - freq );
    1700             :                 LOGIC( 1 );
    1701           0 :                 if ( f[j] != f[j - 1] )
    1702             :                 {
    1703             :                     DIV( 1 );
    1704             :                     ADD( 1 );
    1705           0 :                     X->a[i] /= ( f[j] - f[j - 1] );
    1706             :                 }
    1707           0 :                 break;
    1708             :             }
    1709             :         }
    1710             : 
    1711           0 :         X->a[0] = 0.0f;
    1712             :     }
    1713             : #undef WMC_TOOL_SKIP
    1714             : 
    1715           0 :     return;
    1716             : }
    1717             : 
    1718             : 
    1719             : /*-------------------------------------------------------------------*
    1720             :  * LPCPowSpect()
    1721             :  *
    1722             :  *  LPC power spectrum
    1723             :  *-------------------------------------------------------------------*/
    1724             : 
    1725           0 : static void LPCPowSpect(
    1726             :     const float *freq, /* i  : ERB frequencies    */
    1727             :     const int16_t Nf,  /* i  : Number of ERBs     */
    1728             :     const float *LPC,  /* i  : LPC coefficients   */
    1729             :     const int16_t Np,  /* i  : Number of LPCs     */
    1730             :     float *out         /* o  : LPC power spectrum */
    1731             : )
    1732             : {
    1733             :     float w, tmp, Re, Im;
    1734             :     int16_t i, k;
    1735             : 
    1736             : #define WMC_TOOL_SKIP
    1737             :     LOOP( 1 );
    1738           0 :     for ( k = 0; k < Nf; k++ )
    1739             :     {
    1740             :         MOVE( 1 );
    1741           0 :         Re = 1.0;
    1742             :         MOVE( 1 );
    1743           0 :         Im = 0.0;
    1744             :         /* Note that freq ranges between [0 UPPER_CUT_OFF_FREQ] */
    1745             :         MOVE( 1 );
    1746             :         MULT( 2 );
    1747           0 :         tmp = (float) ( freq[k] / 12800.0f * PI2 );
    1748             :         MOVE( 1 );
    1749             :         ADD( 1 );
    1750             :         LOOP( 1 );
    1751           0 :         for ( i = 0, w = tmp; i < Np; i++, w += tmp )
    1752             :         {
    1753             :             MULT( 1 );
    1754             :             ADD( 2 );
    1755           0 :             Re += (float) ( LPC[i] * cos( w ) );
    1756             :             MULT( 1 );
    1757             :             ADD( 1 );
    1758           0 :             Im -= (float) ( LPC[i] * sin( w ) );
    1759             :         }
    1760             :         MOVE( 1 );
    1761             :         MAC( 1 );
    1762             :         DIV( 1 );
    1763           0 :         out[k] = 1.0f / ( Re * Re + Im * Im );
    1764             :     }
    1765             : #undef WMC_TOOL_SKIP
    1766             : 
    1767           0 :     return;
    1768             : }
    1769             : 
    1770             : 
    1771             : /*-------------------------------------------------------------------*
    1772             :  * erb_diff()
    1773             :  *
    1774             :  * ERB difference
    1775             :  *-------------------------------------------------------------------*/
    1776             : 
    1777           0 : void erb_diff(
    1778             :     const float *prev_erb, /* i  : previous ERB              */
    1779             :     const int16_t pl,      /* i  : previous lag              */
    1780             :     const float *curr_erb, /* i  : current ERB               */
    1781             :     const int16_t l,       /* i  : current lag               */
    1782             :     const float *curr_lsp, /* i  : current LSP coefficients  */
    1783             :     float *out,            /* o  : ERB difference            */
    1784             :     int16_t *index,        /* i  : ERB index                 */
    1785             :     const int16_t num_erb  /* i  : Number of ERBs            */
    1786             : )
    1787             : {
    1788             :     int16_t i, j;
    1789             :     int16_t pslot[NUM_ERB_WB], cslot[NUM_ERB_WB], mmseindex;
    1790             :     float tmp, tmp1, t_prev_erb[NUM_ERB_WB], LPC[M + 1], mfreq[NUM_ERB_WB], PowSpect[NUM_ERB_WB], mmse;
    1791           0 :     const float( *AmpCB1 )[10] = 0;
    1792             : 
    1793           0 :     if ( num_erb == NUM_ERB_NB )
    1794             :     {
    1795           0 :         AmpCB1 = AmpCB1_NB;
    1796             :     }
    1797           0 :     else if ( num_erb == NUM_ERB_WB )
    1798             :     {
    1799           0 :         AmpCB1 = AmpCB1_WB;
    1800             :     }
    1801             : 
    1802             : #define WMC_TOOL_SKIP
    1803             :     FUNC( 3 );
    1804           0 :     erb_slot( l, cslot, mfreq, num_erb );
    1805             :     FUNC( 3 );
    1806           0 :     erb_slot( pl, pslot, t_prev_erb, num_erb );
    1807             :     MOVE( 1 );
    1808             :     ADD( 1 );
    1809             :     LOOP( 1 );
    1810           0 :     for ( i = 0, tmp = 1.0f; i < M + 1; i++ )
    1811             :     {
    1812             :         MOVE( 1 );
    1813             :         MULT( 2 );
    1814             :         ADD( 1 );
    1815           0 :         LPC[i] = curr_lsp[i] * ( tmp *= 0.78f );
    1816             :     }
    1817             :     FUNC( 5 );
    1818             :     ADD( 1 );
    1819           0 :     LPCPowSpect( mfreq, num_erb, LPC, M + 1, PowSpect );
    1820             : 
    1821             :     LOOP( 1 );
    1822           0 :     for ( i = 0; i < num_erb; i++ )
    1823             :     {
    1824             :         MOVE( 1 );
    1825           0 :         t_prev_erb[i] = prev_erb[i];
    1826             :     }
    1827             : 
    1828             :     LOGIC( 1 );
    1829           0 :     if ( pl > l )
    1830             :     {
    1831             :         MOVE( 1 );
    1832           0 :         tmp = t_prev_erb[0];
    1833             :         LOOP( 1 );
    1834           0 :         for ( i = 0; i < num_erb; i++ )
    1835             :         {
    1836           0 :             if ( pslot[i] < 0 )
    1837             :             {
    1838           0 :                 pslot[i] = 0;
    1839             :             }
    1840             : 
    1841             :             LOGIC( 1 );
    1842           0 :             if ( pslot[i] != 0 )
    1843             :             {
    1844             :                 MOVE( 1 );
    1845           0 :                 tmp = t_prev_erb[i];
    1846             :             }
    1847             :             else
    1848             :             {
    1849             :                 MOVE( 1 );
    1850           0 :                 t_prev_erb[i] = tmp;
    1851             :             }
    1852             :         }
    1853             :     }
    1854           0 :     else if ( l > pl )
    1855             :     {
    1856             :         MOVE( 1 );
    1857           0 :         tmp = t_prev_erb[num_erb - 1];
    1858             :         ADD( 1 );
    1859             :         LOOP( 1 );
    1860           0 :         for ( i = num_erb - 1; i >= 0; i-- )
    1861             :         {
    1862             :             LOGIC( 1 );
    1863           0 :             if ( pslot[i] != 0 )
    1864             :             {
    1865             :                 MOVE( 1 );
    1866           0 :                 tmp = t_prev_erb[i];
    1867             :             }
    1868             :             else
    1869             :             {
    1870             :                 MOVE( 1 );
    1871           0 :                 t_prev_erb[i] = tmp;
    1872             :             }
    1873             :         }
    1874             :     }
    1875             : 
    1876             :     LOOP( 1 );
    1877           0 :     for ( i = 0; i < num_erb; i++ )
    1878             :     {
    1879             :         MOVE( 1 );
    1880             :         ADD( 1 );
    1881           0 :         out[i] = curr_erb[i] - t_prev_erb[i];
    1882             :     }
    1883             : 
    1884             :     /* First Band Amplitude Search */
    1885             :     MOVE( 1 );
    1886           0 :     mmse = (float) HUGE_VAL;
    1887             :     MOVE( 1 );
    1888           0 :     mmseindex = -1;
    1889             :     LOOP( 1 );
    1890           0 :     for ( j = 0; j < ERB_CBSIZE1; j++ )
    1891             :     {
    1892             :         MOVE( 1 );
    1893           0 :         tmp = 0.0;
    1894             :         LOOP( 1 );
    1895           0 :         for ( i = 1; i < 11; i++ )
    1896             :         {
    1897             :             LOGIC( 1 );
    1898           0 :             if ( cslot[i] != 0 )
    1899             :             {
    1900             :                 ADD( 1 );
    1901             :                 LOGIC( 1 );
    1902           0 :                 if ( AmpCB1[j][i - 1] < -t_prev_erb[i] )
    1903             :                 {
    1904             :                     MOVE( 1 );
    1905             :                     MULT( 1 );
    1906             :                     MULT( 1 );
    1907           0 :                     tmp1 = PowSpect[i] * SQR( curr_erb[i] );
    1908             :                 }
    1909             :                 else
    1910             :                 {
    1911             :                     MOVE( 1 );
    1912             :                     MAC( 1 );
    1913             :                     MULT( 1 );
    1914           0 :                     tmp1 = (float) ( PowSpect[i] * SQR( out[i] - AmpCB1[j][i - 1] ) );
    1915             :                 }
    1916             :                 LOGIC( 1 );
    1917           0 :                 if ( AmpCB1[j][i - 1] < out[i] )
    1918             :                 {
    1919             :                     MULT( 1 );
    1920           0 :                     tmp1 *= 0.9f;
    1921             :                 }
    1922             :                 ADD( 1 );
    1923           0 :                 tmp += tmp1;
    1924             :             }
    1925             :         }
    1926             : 
    1927             :         LOGIC( 1 );
    1928           0 :         if ( tmp < mmse )
    1929             :         {
    1930             :             MOVE( 1 );
    1931           0 :             mmse = tmp;
    1932             :             MOVE( 1 );
    1933           0 :             mmseindex = j;
    1934             :         }
    1935             :     }
    1936             : 
    1937           0 :     if ( !( mmseindex < ERB_CBSIZE1 && mmseindex >= 0 ) )
    1938             :     {
    1939           0 :         mmseindex = 0;
    1940             :     }
    1941             : 
    1942             :     MOVE( 1 );
    1943           0 :     index[0] = mmseindex;
    1944             : 
    1945             :     /* Second Band Amplitude Search */
    1946             :     MOVE( 1 );
    1947           0 :     mmse = (float) HUGE_VAL;
    1948             :     MOVE( 1 );
    1949           0 :     mmseindex = -1;
    1950             :     LOOP( 1 );
    1951           0 :     for ( j = 0; j < ERB_CBSIZE2; j++ )
    1952             :     {
    1953             :         MOVE( 1 );
    1954           0 :         tmp = 0.0;
    1955           0 :         for ( i = 11; i < num_erb; i++ )
    1956             :         {
    1957           0 :             if ( num_erb == NUM_ERB_NB )
    1958             :             {
    1959             :                 LOGIC( 1 );
    1960           0 :                 if ( cslot[i] != 0 )
    1961             :                 {
    1962             :                     ADD( 1 );
    1963             :                     LOGIC( 1 );
    1964           0 :                     if ( AmpCB2_NB[j][i - 11] < -t_prev_erb[i] )
    1965             :                     {
    1966             :                         MOVE( 1 );
    1967             :                         MULT( 1 );
    1968             :                         MULT( 1 );
    1969           0 :                         tmp1 = PowSpect[i] * SQR( curr_erb[i] );
    1970             :                     }
    1971             :                     else
    1972             :                     {
    1973             :                         MOVE( 1 );
    1974             :                         MAC( 1 );
    1975             :                         MULT( 1 );
    1976           0 :                         tmp1 = (float) ( PowSpect[i] * SQR( out[i] - AmpCB2_NB[j][i - 11] ) );
    1977             :                     }
    1978             : 
    1979             :                     LOGIC( 1 );
    1980           0 :                     if ( AmpCB2_NB[j][i - 11] < out[i] )
    1981             :                     {
    1982             :                         MULT( 1 );
    1983           0 :                         tmp1 *= 0.9f;
    1984             :                     }
    1985             :                     ADD( 1 );
    1986           0 :                     tmp += tmp1;
    1987             :                 }
    1988             :             }
    1989           0 :             else if ( num_erb == NUM_ERB_WB )
    1990             :             {
    1991           0 :                 if ( cslot[i] != 0 )
    1992             :                 {
    1993             :                     ADD( 1 );
    1994             :                     LOGIC( 1 );
    1995           0 :                     if ( AmpCB2_WB[j][i - 11] < -t_prev_erb[i] )
    1996             :                     {
    1997             :                         MOVE( 1 );
    1998             :                         MULT( 1 );
    1999             :                         MULT( 1 );
    2000           0 :                         tmp1 = PowSpect[i] * SQR( curr_erb[i] );
    2001             :                     }
    2002             :                     else
    2003             :                     {
    2004             :                         MOVE( 1 );
    2005             :                         MAC( 1 );
    2006             :                         MULT( 1 );
    2007           0 :                         tmp1 = (float) ( PowSpect[i] * SQR( out[i] - AmpCB2_WB[j][i - 11] ) );
    2008             :                     }
    2009             : 
    2010             :                     LOGIC( 1 );
    2011           0 :                     if ( AmpCB2_WB[j][i - 11] < out[i] )
    2012             :                     {
    2013             :                         MULT( 1 );
    2014           0 :                         tmp1 *= 0.9f;
    2015             :                     }
    2016             :                     ADD( 1 );
    2017           0 :                     tmp += tmp1;
    2018             :                 }
    2019             :             }
    2020             :         }
    2021             : 
    2022             :         LOGIC( 1 );
    2023           0 :         if ( tmp < mmse )
    2024             :         {
    2025             :             MOVE( 1 );
    2026           0 :             mmse = tmp;
    2027             :             MOVE( 1 );
    2028           0 :             mmseindex = j;
    2029             :         }
    2030             :     }
    2031             : 
    2032           0 :     if ( !( mmseindex < ERB_CBSIZE2 && mmseindex >= 0 ) )
    2033             :     {
    2034           0 :         mmseindex = 0;
    2035             :     }
    2036             : 
    2037             :     MOVE( 1 );
    2038           0 :     index[1] = mmseindex;
    2039             : #undef WMC_TOOL_SKIP
    2040             : 
    2041           0 :     return;
    2042             : }
    2043             : 
    2044             : /*-------------------------------------------------------------------*
    2045             :  * erb_add()
    2046             :  *
    2047             :  * Add current and past ERB
    2048             :  *-------------------------------------------------------------------*/
    2049             : 
    2050           0 : void erb_add(
    2051             :     float *curr_erb,       /* i/o:  current ERB    */
    2052             :     const int16_t l,       /* i  :  current lag    */
    2053             :     const float *prev_erb, /* i  :  previous ERB   */
    2054             :     const int16_t pl,      /* i  :  previous lag   */
    2055             :     const int16_t *index,  /* i  :  ERB index      */
    2056             :     const int16_t num_erb  /* i  :  number of ERBs */
    2057             : )
    2058             : {
    2059             :     int16_t i, pslot[NUM_ERB_WB], cslot[NUM_ERB_WB];
    2060             :     float tmp, t_prev_erb[NUM_ERB_WB];
    2061           0 :     const float( *AmpCB1 )[10] = 0;
    2062             : 
    2063           0 :     if ( num_erb == NUM_ERB_NB )
    2064             :     {
    2065           0 :         AmpCB1 = AmpCB1_NB;
    2066             :     }
    2067           0 :     else if ( num_erb == NUM_ERB_WB )
    2068             :     {
    2069           0 :         AmpCB1 = AmpCB1_WB;
    2070             :     }
    2071             : 
    2072             : #define WMC_TOOL_SKIP
    2073             :     FUNC( 3 );
    2074           0 :     erb_slot( l, cslot, t_prev_erb, num_erb );
    2075             :     FUNC( 3 );
    2076           0 :     erb_slot( pl, pslot, t_prev_erb, num_erb );
    2077             : 
    2078             :     LOOP( 1 );
    2079           0 :     for ( i = 0; i < num_erb; i++ )
    2080             :     {
    2081             :         MOVE( 1 );
    2082           0 :         t_prev_erb[i] = prev_erb[i];
    2083             :     }
    2084             : 
    2085             :     LOGIC( 1 );
    2086           0 :     if ( pl > l )
    2087             :     {
    2088             :         MOVE( 1 );
    2089           0 :         tmp = t_prev_erb[0];
    2090             :         LOOP( 1 );
    2091           0 :         for ( i = 0; i < num_erb; i++ )
    2092             :         {
    2093           0 :             if ( !( pslot[i] >= 0 ) )
    2094             :             {
    2095           0 :                 pslot[i] = 0;
    2096             :             }
    2097             : 
    2098             :             LOGIC( 1 );
    2099           0 :             if ( pslot[i] != 0 )
    2100             :             {
    2101             :                 MOVE( 1 );
    2102           0 :                 tmp = t_prev_erb[i];
    2103             :             }
    2104             :             else
    2105             :             {
    2106             :                 MOVE( 1 );
    2107           0 :                 t_prev_erb[i] = tmp;
    2108             :             }
    2109             :         }
    2110             :     }
    2111           0 :     else if ( l > pl )
    2112             :     {
    2113             :         MOVE( 1 );
    2114           0 :         tmp = t_prev_erb[num_erb - 1];
    2115             :         ADD( 1 );
    2116             :         LOOP( 1 );
    2117           0 :         for ( i = num_erb - 1; i >= 0; i-- )
    2118             :         {
    2119             :             LOGIC( 1 );
    2120           0 :             if ( pslot[i] != 0 )
    2121             :             {
    2122             :                 MOVE( 1 );
    2123           0 :                 tmp = t_prev_erb[i];
    2124             :             }
    2125             :             else
    2126             :             {
    2127             :                 MOVE( 1 );
    2128           0 :                 t_prev_erb[i] = tmp;
    2129             :             }
    2130             :         }
    2131             :     }
    2132             : 
    2133             :     LOOP( 1 );
    2134           0 :     for ( i = 1; i < 11; i++ )
    2135             :     {
    2136             :         LOGIC( 1 );
    2137           0 :         if ( cslot[i] != 0 )
    2138             :         {
    2139             :             MOVE( 1 );
    2140             :             ADD( 1 );
    2141           0 :             curr_erb[i] = (float) ( AmpCB1[index[0]][i - 1] + t_prev_erb[i] );
    2142             :             MOVE( 1 );
    2143           0 :             curr_erb[i] = max( 0.0f, curr_erb[i] );
    2144             :         }
    2145             :         else
    2146             :         {
    2147             :             MOVE( 1 );
    2148           0 :             curr_erb[i] = 0.0;
    2149             :         }
    2150             :     }
    2151             :     LOOP( 1 );
    2152           0 :     for ( i = 11; i < ( num_erb - 2 ); i++ )
    2153             :     {
    2154             :         LOGIC( 1 );
    2155           0 :         if ( cslot[i] != 0 )
    2156             :         {
    2157             :             MOVE( 1 );
    2158           0 :             if ( num_erb == NUM_ERB_NB )
    2159             :             {
    2160             :                 ADD( 1 );
    2161           0 :                 curr_erb[i] = (float) ( AmpCB2_NB[index[1]][i - 11] + t_prev_erb[i] );
    2162             :                 MOVE( 1 );
    2163           0 :                 curr_erb[i] = max( 0.0f, curr_erb[i] );
    2164             :             }
    2165           0 :             else if ( num_erb == NUM_ERB_WB )
    2166             :             {
    2167             :                 ADD( 1 );
    2168           0 :                 curr_erb[i] = (float) ( AmpCB2_WB[index[1]][i - 11] + t_prev_erb[i] );
    2169             :                 MOVE( 1 );
    2170           0 :                 curr_erb[i] = max( 0.0f, curr_erb[i] );
    2171             :             }
    2172             :         }
    2173             :         else
    2174             :         {
    2175             :             MOVE( 1 );
    2176           0 :             curr_erb[i] = 0.0f;
    2177             :         }
    2178             :     }
    2179             : #undef WMC_TOOL_SKIP
    2180             : 
    2181           0 :     return;
    2182             : }
    2183             : 
    2184             : 
    2185             : /*-------------------------------------------------------------------*
    2186             :  * WIsyn()
    2187             :  *
    2188             :  * Synthesis using waveform interpolation
    2189             :  *-------------------------------------------------------------------*/
    2190             : 
    2191           0 : ivas_error WIsyn(
    2192             :     DTFS_STRUCTURE PREVCW,           /* i  : Prev frame DTFS                                */
    2193             :     DTFS_STRUCTURE *CURRCW_DTFS_out, /* i/o: Curr frame DTFS                                */
    2194             :     const float *curr_lpc,           /* i  : LPC                                            */
    2195             :     float *ph_offset,                /* i/o: Phase offset to line up at end of frame        */
    2196             :     float *out,                      /* o  : Waveform Interpolated time domain signal       */
    2197             :     const int16_t N,                 /* i  : Number of output samples to generate           */
    2198             :     const int16_t FR_flag            /* i  : called for post-smoothing in FR                */
    2199             : )
    2200             : {
    2201             :     DTFS_STRUCTURE *CURRCW_DTFS;
    2202           0 :     uint16_t I = 1, flag = 0;
    2203             :     float alignment, tmp, *phase;
    2204             :     ivas_error error;
    2205             : 
    2206           0 :     error = IVAS_ERR_OK;
    2207             : 
    2208           0 :     if ( ( phase = (float *) malloc( N * sizeof( float ) ) ) == NULL )
    2209             :     {
    2210           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for WI structure\n" ) );
    2211             :     }
    2212             : 
    2213           0 :     if ( ( error = DTFS_new( &CURRCW_DTFS ) ) != IVAS_ERR_OK )
    2214             :     {
    2215           0 :         return IVAS_ERROR( error, "Error creating new DTFS structure\n" );
    2216             :     }
    2217             : 
    2218             : #define WMC_TOOL_SKIP
    2219             :     FUNC( 2 );
    2220           0 :     DTFS_copy( CURRCW_DTFS, *CURRCW_DTFS_out );
    2221             : 
    2222             :     /* Calculating the expected alignment shift */
    2223             :     MOVE( 1 );
    2224             :     MULT( 2 );
    2225             :     INDIRECT( 1 );
    2226             :     INDIRECT( 1 );
    2227           0 :     alignment = (float) ( *ph_offset / PI2 * PREVCW.lag );
    2228             :     LOGIC( 1 );
    2229           0 :     if ( flag == 1 )
    2230             :     {
    2231             :         MULT( 1 );
    2232           0 :         alignment *= I;
    2233             :     }
    2234             :     /* Calculating the expected alignment shift */
    2235             :     MOVE( 1 );
    2236             :     DIV( 1 );
    2237             :     ADD( 2 );
    2238             :     DIV( 1 );
    2239           0 :     tmp = (float) fmod( ( N % ( ( PREVCW.lag + CURRCW_DTFS->lag ) >> 1 ) + alignment ), CURRCW_DTFS->lag );
    2240             : 
    2241             :     /* Compute the alignment shift */
    2242           0 :     if ( FR_flag == 0 )
    2243             :     {
    2244             :         FUNC( 5 );
    2245             :         MOVE( 1 );
    2246           0 :         alignment = DTFS_alignment_weight( PREVCW, *CURRCW_DTFS, tmp, curr_lpc, curr_lpc );
    2247             :     }
    2248             :     else /* FR case */
    2249             :     {
    2250             :         FUNC( 5 );
    2251             :         MOVE( 1 );
    2252           0 :         alignment = DTFS_alignment_full( PREVCW, *CURRCW_DTFS, CURRCW_DTFS->lag * 2 );
    2253             :     }
    2254             : 
    2255             :     MOVE( 1 );
    2256             :     MULT( 2 );
    2257           0 :     tmp = (float) ( PI2 * alignment / CURRCW_DTFS->lag );
    2258             :     FUNC( 2 );
    2259           0 :     DTFS_phaseShift( CURRCW_DTFS, tmp );
    2260             :     FUNC( 2 );
    2261             :     MULT( 2 );
    2262           0 :     DTFS_phaseShift( CURRCW_DTFS_out, (float) ( PI2 * alignment / CURRCW_DTFS->lag ) );
    2263             : 
    2264             :     /* Compute the cubic phase track and transform to 1-D signal */
    2265             :     FUNC( 6 );
    2266           0 :     cubicPhase( *ph_offset, tmp, (float) PREVCW.lag, (float) CURRCW_DTFS->lag, N, phase );
    2267             : 
    2268           0 :     if ( FR_flag == 0 )
    2269             :     {
    2270             :         FUNC( 6 );
    2271           0 :         DTFS_transform( PREVCW, *CURRCW_DTFS, phase, out, N, 0 );
    2272             :     }
    2273             :     else
    2274             :     {
    2275             :         FUNC( 6 );
    2276           0 :         DTFS_transform( PREVCW, *CURRCW_DTFS, phase, out, N, 1 );
    2277             :     }
    2278             : 
    2279             :     /* Adjust the phase offset and wrap it between 0 and 2pi */
    2280             :     LOGIC( 1 );
    2281           0 :     if ( flag == 2 )
    2282             :     {
    2283             :         MULT( 1 );
    2284           0 :         tmp *= I;
    2285             :     }
    2286             :     MOVE( 1 );
    2287             :     DIV( 1 );
    2288           0 :     *ph_offset = (float) fmod( (double) ( tmp ), PI2 );
    2289             : #undef WMC_TOOL_SKIP
    2290             : 
    2291           0 :     free( phase );
    2292           0 :     free( CURRCW_DTFS );
    2293             : 
    2294           0 :     return error;
    2295             : }

Generated by: LCOV version 1.14