LCOV - code coverage report
Current view: top level - lib_com - edct_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 391 478 81.8 %
Date: 2025-05-03 01:55:50 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdlib.h>
       6             : #include <assert.h>
       7             : #include "options.h" /* Compilation switches                   */
       8             : #include "cnst.h"    /* Common constants                       */
       9             : #include "rom_com.h" /* Static table prototypes                */
      10             : #include "prot_fx.h" /* Function prototypes                    */
      11             : #include "stl.h"
      12             : 
      13             : 
      14             : #include "math_32.h"
      15             : 
      16             : 
      17        1566 : static Word16 get_edxt_factor( Word16 length ) /* Returns value of sqrtf(2.f/length) in Q15 */
      18             : {
      19             :     Word16 factor; /*Q15*/
      20        1566 :     factor = 0;
      21        1566 :     move16();
      22        1566 :     IF( EQ_16( length, 512 ) )
      23             :     {
      24         262 :         factor = 2048; /*0.0625 in Q15*/
      25         262 :         move16();
      26             :     }
      27        1304 :     ELSE IF( EQ_16( length, 256 ) )
      28             :     {
      29           5 :         factor = 2896; /*0.0883 in Q15*/
      30           5 :         move16();
      31             :     }
      32        1299 :     ELSE IF( EQ_16( length, 128 ) )
      33             :     {
      34           7 :         factor = 4096; /*0.125 in Q15*/
      35           7 :         move16();
      36             :     }
      37        1292 :     ELSE IF( EQ_16( length, 640 ) )
      38             :     {
      39         369 :         factor = 1832; /*0.0559 in Q15*/
      40         369 :         move16();
      41             :     }
      42         923 :     ELSE IF( EQ_16( length, 320 ) )
      43             :     {
      44         634 :         factor = 2590; /*0.079 in Q15*/
      45         634 :         move16();
      46             :     }
      47         289 :     ELSE IF( EQ_16( length, 160 ) )
      48             :     {
      49          37 :         factor = 3663; /*0.1117 in Q15*/
      50          37 :         move16();
      51             :     }
      52         252 :     ELSE IF( EQ_16( length, 80 ) )
      53             :     {
      54          32 :         factor = 5181; /*0.1581 in Q15*/
      55          32 :         move16();
      56             :     }
      57         220 :     ELSE IF( EQ_16( length, 40 ) )
      58             :     {
      59           0 :         factor = 7327; /*0.223 in Q15*/
      60           0 :         move16();
      61             :     }
      62         220 :     ELSE IF( EQ_16( length, 960 ) )
      63             :     {
      64         220 :         factor = 1496; /*0.0456 in Q15*/
      65         220 :         move16();
      66             :     }
      67           0 :     ELSE IF( EQ_16( length, 480 ) )
      68             :     {
      69           0 :         factor = 2115; /*0.0645 in Q15*/
      70           0 :         move16();
      71             :     }
      72           0 :     ELSE IF( EQ_16( length, 240 ) )
      73             :     {
      74           0 :         factor = 2991; /*0.0912 in Q15*/
      75           0 :         move16();
      76             :     }
      77           0 :     ELSE IF( EQ_16( length, 120 ) )
      78             :     {
      79           0 :         factor = 4230; /*0.1290 in Q15*/
      80           0 :         move16();
      81             :     }
      82           0 :     ELSE IF( EQ_16( length, 1200 ) )
      83             :     {
      84           0 :         factor = 1338; /*0.040 in Q15*/
      85           0 :         move16();
      86             :     }
      87           0 :     ELSE IF( EQ_16( length, 800 ) )
      88             :     {
      89           0 :         factor = 1638; /*0.05 in Q15*/
      90           0 :         move16();
      91             :     }
      92           0 :     ELSE IF( EQ_16( length, 400 ) )
      93             :     {
      94           0 :         factor = 2317; /*0.070 in Q15*/
      95           0 :         move16();
      96             :     }
      97           0 :     ELSE IF( EQ_16( length, 200 ) )
      98             :     {
      99           0 :         factor = 3277; /*0.1 in Q15*/
     100           0 :         move16();
     101             :     }
     102        1566 :     return factor; /*Q15*/
     103             : }
     104             : 
     105     4108560 : static Word16 const *get_edct_table( Word16 length /*Q0*/, Word16 *q )
     106             : {
     107             :     Word16 const *edct_table;
     108     4108560 :     edct_table = NULL;
     109     4108560 :     SWITCH( length )
     110             :     {
     111       21035 :         case 1200:
     112       21035 :             edct_table = edct_table_600_fx; /*Q17*/
     113       21035 :             *q = add( *q, 2 );
     114       21035 :             move16();
     115       21035 :             BREAK;
     116     1812148 :         case 960:
     117     1812148 :             edct_table = edct_table_480_fx; /*Q16*/
     118     1812148 :             BREAK;
     119     1006218 :         case 640:
     120     1006218 :             edct_table = edct_table_320_fx; /*Q16*/
     121     1006218 :             BREAK;
     122      491283 :         case 320:
     123      491283 :             edct_table = edct_table_160_fx; /*Q16*/
     124      491283 :             BREAK;
     125      315383 :         case 256:
     126      315383 :             edct_table = edct_table_128_fx; /*Q16*/
     127      315383 :             BREAK;
     128       66504 :         case 240:
     129       66504 :             edct_table = edct_table_120_fx; /*Q16*/
     130       66504 :             BREAK;
     131           0 :         case 200:
     132           0 :             edct_table = edct_table_100_fx; /*Q16*/
     133           0 :             BREAK;
     134       81076 :         case 160:
     135       81076 :             edct_table = edct_table_80_fx; /*Q16*/
     136       81076 :             BREAK;
     137           0 :         case 40:
     138           0 :             edct_table = edct_table_20_fx; /*Q16*/
     139           0 :             BREAK;
     140        5721 :         case 800:
     141        5721 :             edct_table = edct_table_400_fx; /*Q17*/
     142        5721 :             *q = add( *q, 2 );
     143        5721 :             move16();
     144        5721 :             BREAK;
     145      230284 :         case 512:
     146      230284 :             edct_table = edct_table_256_fx; /*Q16*/
     147      230284 :             BREAK;
     148       28948 :         case 480:
     149       28948 :             edct_table = edct_table_240_fx; /*Q16*/
     150       28948 :             BREAK;
     151       24855 :         case 400:
     152       24855 :             edct_table = edct_table_200_fx; /*Q16*/
     153       24855 :             BREAK;
     154       12835 :         case 128:
     155       12835 :             edct_table = edct_table_64_fx; /*Q16*/
     156       12835 :             BREAK;
     157       12270 :         case 80:
     158       12270 :             edct_table = edct_table_40_fx; /*Q16*/
     159       12270 :             BREAK;
     160           0 :         default:
     161           0 :             BREAK;
     162             :     }
     163     4108560 :     return edct_table;
     164             : }
     165             : 
     166             : /*-------------------------------------------------------------------------*
     167             :  * FUNCTION : edct_fx()
     168             :  *
     169             :  * PURPOSE : DCT transform
     170             :  *
     171             :  * INPUT ARGUMENTS :
     172             :  * _ (Word16) length             : length
     173             :  * _ (Word16*) x                 : input signal                      Qx
     174             :  * _ (Word16*) edct_table_128_fx : edct table                       Q16
     175             :  *
     176             :  * OUTPUT ARGUMENTS :
     177             :  * _ (Word16[]) y                : output transform                  Qx
     178             :  *-------------------------------------------------------------------------*/
     179     2161799 : void edct_fx(
     180             :     const Word32 *x, /* i  : input signal        Qq         */
     181             :     Word32 *y,       /* o  : output transform    Qq         */
     182             :     Word16 length,   /* i  : length                         Q0*/
     183             :     Word16 *q        /* i  : Q value of input signal        */
     184             : )
     185             : {
     186             :     Word16 i;
     187             :     Word32 re;
     188             :     Word32 im;
     189             :     const Word16 *edct_table; /*Q16 */
     190             :     Word32 complex_buf[2 * ( L_FRAME48k / 2 + 240 )];
     191             :     Word32 L_tmp;
     192             :     Word16 tmp;
     193             :     Word16 len1;
     194             : 
     195     2161799 :     edct_table = get_edct_table( length, q ); /*q*/
     196     2161799 :     len1 = shr( length, 1 );                  /*Q0*/
     197             :     /* Twiddling and Pre-rotate */
     198   633870167 :     FOR( i = 0; i < len1; i++ )
     199             :     {
     200   631708368 :         L_tmp = Mult_32_16( x[2 * i], edct_table[i] );                                                                 /*Q(q+1) */
     201   631708368 :         complex_buf[2 * i] = Madd_32_16( L_tmp, x[( length - ( 1 + ( i * 2 ) ) )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
     202   631708368 :         move32();
     203             : 
     204   631708368 :         L_tmp = Mult_32_16( x[( length - ( 1 + ( i * 2 ) ) )], edct_table[i] ); /*Q(q+1) */
     205             : 
     206   631708368 :         complex_buf[( ( i * 2 ) + 1 )] = Msub_32_16( L_tmp, x[( i * 2 )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
     207   631708368 :         move32();
     208             :     }
     209             : 
     210     2161799 :     *q = sub( 15, *q );
     211     2161799 :     move16();
     212     2161799 :     BASOP_cfft( (cmplx *) complex_buf, len1, q, y );
     213             : 
     214     2161799 :     tmp = div_s( 1, length );                                                     /*Q15 */
     215     2161799 :     tmp = round_fx( L_shl( L_mult( tmp, 19302 /*0.75f * EVS_PI in Q13*/ ), 2 ) ); /*Q15 */
     216   633870167 :     FOR( i = 0; i < len1; i++ )
     217             :     {
     218   631708368 :         re = Msub_32_16( complex_buf[2 * i], complex_buf[( ( i * 2 ) + 1 )], tmp );                              /*Q(q+1) */
     219   631708368 :         im = Madd_32_16( complex_buf[( ( i * 2 ) + 1 )], complex_buf[2 * i], tmp );                              /*Q(q+1) */
     220   631708368 :         y[2 * i] = L_add( Mult_32_16( re, edct_table[i] ), Mult_32_16( im, edct_table[( len1 - ( 1 + i ) )] ) ); /*Q(q+2)*/
     221   631708368 :         move32();
     222   631708368 :         y[( length - ( 1 + ( i * 2 ) ) )] = L_sub( Mult_32_16( re, edct_table[( len1 - ( 1 + i ) )] ), Mult_32_16( im, edct_table[i] ) ); /*Q(q+2)*/
     223   631708368 :         move32();
     224             :     } /*Q(q-2) */
     225             : 
     226     2161799 :     *q = sub( 15 + 2, *q );
     227     2161799 :     move16();
     228     2161799 :     return;
     229             : }
     230             : 
     231     1060086 : void edct_ivas_fx(
     232             :     const Word32 *x, /* i  : input signal        Qq         */
     233             :     Word32 *y,       /* o  : output transform    Qq         */
     234             :     Word16 length,   /* i  : length                         Q0*/
     235             :     Word16 *q        /* i  : Q value of input signal        */
     236             : )
     237             : {
     238             :     Word16 i;
     239             :     const Word16 *edct_table; /*Q16 */
     240             :     Word32 re[L_FRAME_PLUS / 2];
     241             :     Word32 im[L_FRAME_PLUS / 2];
     242             :     Word32 L_tmp;
     243             :     Word16 tmp;
     244             :     Word16 len1;
     245             : 
     246     1060086 :     edct_table = get_edct_table( length, q ); /*q*/
     247     1060086 :     len1 = shr( length, 1 );                  /*Q0*/
     248             :                                               /* Twiddling and Pre-rotate */
     249   411049270 :     FOR( i = 0; i < len1; i++ )
     250             :     {
     251   409989184 :         L_tmp = Mult_32_16( x[2 * i], edct_table[i] );                                                    /*Q(q+1) */
     252   409989184 :         re[i] = Madd_32_16( L_tmp, x[( length - ( 1 + ( i * 2 ) ) )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
     253   409989184 :         move32();
     254             : 
     255   409989184 :         L_tmp = Mult_32_16( x[( length - ( 1 + ( i * 2 ) ) )], edct_table[i] );      /*Q(q+1) */
     256   409989184 :         im[i] = Msub_32_16( L_tmp, x[( i * 2 )], edct_table[( len1 - ( 1 + i ) )] ); /*Q(q+1) */
     257   409989184 :         move32();
     258             :     }
     259             : 
     260     1060086 :     *q = sub( 31, *q );
     261     1060086 :     move16();
     262     1060086 :     tmp = sub( s_min( getScaleFactor32( re, len1 ), getScaleFactor32( im, len1 ) ), find_guarded_bits_fx( len1 ) );
     263     1060086 :     scale_sig32( re, len1, tmp );
     264     1060086 :     scale_sig32( im, len1, tmp );
     265             : 
     266     1060086 :     fft_fx( re, im, len1, 1 );
     267     1060086 :     *q = sub( *q, tmp );
     268     1060086 :     move16();
     269             : 
     270     1060086 :     tmp = div_s( 4, length );                                         /*Q17 */
     271     1060086 :     tmp = round_fx( L_mult( tmp, 19302 /*0.75f * EVS_PI in Q13*/ ) ); /*Q15 */
     272   411049270 :     FOR( i = 0; i < len1; i++ )
     273             :     {
     274   409989184 :         L_tmp = Msub_32_16( re[i], im[i], tmp );
     275   409989184 :         im[i] = Madd_32_16( im[i], re[i], tmp ); /*Q(q+1) */
     276   409989184 :         re[i] = L_tmp;                           /*Q(q+1) */
     277   409989184 :         move32();
     278   409989184 :         move32();
     279             :     }
     280   411049270 :     FOR( i = 0; i < len1; i++ )
     281             :     {
     282   409989184 :         y[2 * i] = L_add( Mult_32_16( re[i], edct_table[i] ), Mult_32_16( im[i], edct_table[( len1 - ( 1 + i ) )] ) ); /*Q(q+2)*/
     283   409989184 :         move32();
     284   409989184 :         y[( length - ( 1 + ( i * 2 ) ) )] = L_sub( Mult_32_16( re[i], edct_table[( len1 - ( 1 + i ) )] ), Mult_32_16( im[i], edct_table[i] ) ); /*Q(q+2)*/
     285   409989184 :         move32();
     286             :     } /*Q(q-2) */
     287             : 
     288     1060086 :     *q = sub( 31 + 2, *q );
     289     1060086 :     move16();
     290     1060086 :     return;
     291             : }
     292             : /*-------------------------------------------------------------------------*
     293             :  * FUNCTION : edst_fx()
     294             :  *
     295             :  * PURPOSE : DST_IV transform
     296             :  *
     297             :  * INPUT ARGUMENTS :
     298             :  * _ (Word16) length             : length
     299             :  * _ (Word16*) x                 : input signal                      Qx
     300             :  * _ (Word16*) edct_table_128_fx : edct table                       Q16
     301             :  *
     302             :  * OUTPUT ARGUMENTS :
     303             :  * _ (Word16[]) y                : output transform                  Qx
     304             :  *-------------------------------------------------------------------------*/
     305      886675 : void edst_fx(
     306             :     const Word32 *x, /* i  : input signal        Qq         */
     307             :     Word32 *y,       /* o  : output transform    Qq         */
     308             :     Word16 length,   /* i  : length                         */
     309             :     Word16 *q        /* i  : Q value of input signal        */
     310             : )
     311             : {
     312             :     Word16 i;
     313             :     Word32 re;
     314             :     Word32 im;
     315             :     const Word16 *edct_table; /*Q16 */
     316             :     Word32 complex_buf[2 * ( L_FRAME48k / 2 + 240 )];
     317             :     Word32 L_tmp;
     318             :     Word16 tmp;
     319             :     Word16 len1;
     320             : 
     321      886675 :     edct_table = get_edct_table( length, q ); /*q*/
     322      886675 :     len1 = shr( length, 1 );                  /*Q0*/
     323             :     /* Twiddling and Pre-rotate */
     324   371543651 :     FOR( i = 0; i < len1; i++ )
     325             :     {
     326   370656976 :         L_tmp = Mult_32_16( x[( length - ( 1 + ( i * 2 ) ) )], edct_table[i] );               /*Qq+1*/
     327   370656976 :         complex_buf[2 * i] = Madd_32_16( L_tmp, x[2 * i], edct_table[( len1 - ( 1 + i ) )] ); /*Qq+1*/
     328   370656976 :         move32();
     329             : 
     330   370656976 :         L_tmp = Mult_32_16( x[2 * i], edct_table[i] );                                                                             /*Qq+1*/
     331   370656976 :         complex_buf[( ( i * 2 ) + 1 )] = Msub_32_16( L_tmp, x[( length - ( 1 + ( i * 2 ) ) )], edct_table[( len1 - ( 1 + i ) )] ); /*Qq+1*/
     332   370656976 :         move32();
     333             :     }
     334             : 
     335      886675 :     *q = sub( 15, *q );
     336      886675 :     move16();
     337      886675 :     BASOP_cfft( (cmplx *) complex_buf, len1, q, y );
     338             : 
     339      886675 :     tmp = div_s( 1, length );                                                     /*Q15 */
     340      886675 :     tmp = round_fx( L_shl( L_mult( tmp, 19302 /*0.75f * EVS_PI in Q13*/ ), 2 ) ); /*Q15 */
     341   371543651 :     FOR( i = 0; i < len1; i++ )
     342             :     {
     343   370656976 :         re = Msub_32_16( complex_buf[2 * i], complex_buf[( ( i * 2 ) + 1 )], tmp );                              /*Qq+1*/
     344   370656976 :         im = Madd_32_16( complex_buf[( ( i * 2 ) + 1 )], complex_buf[2 * i], tmp );                              /*Qq+1*/
     345   370656976 :         y[2 * i] = L_add( Mult_32_16( re, edct_table[i] ), Mult_32_16( im, edct_table[( len1 - ( 1 + i ) )] ) ); /*Qq+2*/
     346   370656976 :         move32();
     347   370656976 :         y[( length - ( 1 + ( i * 2 ) ) )] = L_sub( Mult_32_16( im, edct_table[i] ), Mult_32_16( re, edct_table[( len1 - ( 1 + i ) )] ) ); /*Qq+2*/
     348   370656976 :         move32();
     349             :     } /*Q(q) */
     350             : 
     351      886675 :     *q = sub( 15 + 2, *q );
     352      886675 :     move16();
     353             : 
     354      886675 :     return;
     355             : }
     356             : /*========================================================================*/
     357             : /* FUNCTION : edct_fx()                                                   */
     358             : /*------------------------------------------------------------------------*/
     359             : /* PURPOSE : DCT transform                                                */
     360             : /*------------------------------------------------------------------------*/
     361             : /* INPUT ARGUMENTS :                                                      */
     362             : /* _ (Word16) length             : length                                 */
     363             : /* _ (Word16*) x                 : input signal Qx                        */
     364             : /* _ (Word16*) edct_table_128_fx : edct table   Q15                       */
     365             : /*------------------------------------------------------------------------*/
     366             : /* INPUT/OUTPUT ARGUMENTS :                                               */
     367             : /*------------------------------------------------------------------------*/
     368             : /* OUTPUT ARGUMENTS :                                                     */
     369             : /* _ (Word16[]) y : output transform      Qx                              */
     370             : /*------------------------------------------------------------------------*/
     371             : 
     372             : /*------------------------------------------------------------------------*/
     373             : /* RETURN ARGUMENTS :                                                     */
     374             : /* _ None                                                                 */
     375             : /*========================================================================*/
     376      298375 : void edct_16fx(
     377             :     const Word16 *x, /* i  : input signal        Qx  */
     378             :     Word16 *y,       /* o  : output transform    Qx  */
     379             :     Word16 length,   /* i  : length  */
     380             :     Word16 bh,       /* bit-headroom */
     381             :     const Word16 element_mode
     382             : 
     383             : )
     384             : {
     385             :     Word16 i;
     386             :     Word16 re[L_FRAME48k / 2];
     387             :     Word16 im[L_FRAME48k / 2];
     388      298375 :     const Word16 *edct_table = NULL;
     389             :     Word16 re2[L_FRAME48k / 2];
     390             :     Word16 im2[L_FRAME48k / 2];
     391             : 
     392             :     Word32 L_tmp, Lacc, Lmax;
     393             :     Word16 tmp, fact;
     394             :     Word16 Q_edct;
     395             :     Word16 Len2, i2;
     396             :     const Word16 *px, *pt;
     397             :     Word16 *py;
     398             :     (void) element_mode;
     399             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     400             :     Flag Overflow;
     401      298375 :     Overflow = 0;
     402      298375 :     move32();
     403             : #endif
     404             :     /*COMPLETE: some eDCT sub function are missing */
     405             : 
     406      298375 :     IF( EQ_16( length, L_FRAME32k ) )
     407             :     {
     408       18626 :         edct_table = &edct_table_320_16fx[0]; /*Q15*/
     409             :     }
     410      279749 :     ELSE IF( EQ_16( length, L_FRAME ) )
     411             :     {
     412      193294 :         edct_table = &edct_table_128_16fx[0]; /*Q15*/
     413             :     }
     414       86455 :     ELSE IF( EQ_16( length, L_FRAME16k ) )
     415             :     {
     416       86455 :         edct_table = &edct_table_160_16fx[0]; /*Q15*/
     417             :     }
     418             :     ELSE
     419             :     {
     420             :     }
     421             : 
     422             :     /* Twiddling and Pre-rotate */
     423      298375 :     Lmax = L_deposit_l( 0 );
     424      298375 :     Len2 = shr( length, 1 );
     425      298375 :     px = x + sub( length, 1 );        /*Qx*/
     426      298375 :     pt = edct_table + sub( Len2, 1 ); /*Q16*/
     427    44833127 :     FOR( i = 0; i < Len2; i++ )
     428             :     {
     429    44534752 :         i2 = shl( i, 1 );
     430    44534752 :         L_tmp = L_mult( x[i2], edct_table[i] ); /*Q(Qx+16) */
     431             : 
     432    44534752 :         Lacc = L_mac( L_tmp, *px, *pt ); /*Q(Qx+16) */
     433             : 
     434    44534752 :         Lmax = L_max( Lmax, Lacc );
     435             : 
     436    44534752 :         L_tmp = L_mult( *px, edct_table[i] ); /*Q(Qx+16) */
     437    44534752 :         Lacc = L_msu( L_tmp, x[i2], *pt );    /*Q(Qx+16) */
     438    44534752 :         Lmax = L_max( Lmax, Lacc );
     439             : 
     440    44534752 :         px -= 2;
     441    44534752 :         pt--;
     442             :     }
     443             : 
     444      298375 :     tmp = 31;
     445      298375 :     move16();
     446      298375 :     if ( Lmax != 0 )
     447             :     {
     448      281968 :         tmp = norm_l( Lmax );
     449             :     }
     450      298375 :     Q_edct = sub( tmp, bh ); /*creating a bit-headroom */
     451             : 
     452      298375 :     px = x + sub( length, 1 );        /*Qx*/
     453      298375 :     pt = edct_table + sub( Len2, 1 ); /*Q15*/
     454    44833127 :     FOR( i = 0; i < Len2; i++ )
     455             :     {
     456    44534752 :         i2 = shl( i, 1 );
     457             : 
     458    44534752 :         L_tmp = L_mult( x[i2], edct_table[i] );                               /*Q(Qx+16) */
     459    44534752 :         Lacc = L_mac_o( L_tmp, *px, *pt, &Overflow );                         /*Q(Qx+16) */
     460    44534752 :         re2[i] = round_fx_o( L_shl_o( Lacc, Q_edct, &Overflow ), &Overflow ); /* Q(Qx+Q_edct) */
     461    44534752 :         move16();
     462    44534752 :         L_tmp = L_mult( *px, edct_table[i] );                                 /*Q(Qx+16) */
     463    44534752 :         Lacc = L_msu_o( L_tmp, x[i2], *pt, &Overflow );                       /*Q(Qx+16) */
     464    44534752 :         im2[i] = round_fx_o( L_shl_o( Lacc, Q_edct, &Overflow ), &Overflow ); /* Q(Qx+Q_edct) */
     465    44534752 :         move16();
     466    44534752 :         px -= 2;
     467    44534752 :         pt--;
     468             :     }
     469      298375 :     IF( EQ_16( length, L_FRAME32k ) )
     470             :     {
     471       18626 :         DoRTFT320_16fx( re2, im2 );
     472             :     }
     473      279749 :     ELSE IF( EQ_16( length, L_FRAME ) )
     474             :     {
     475      193294 :         DoRTFT128_16fx( re2, im2 );
     476             :     }
     477       86455 :     ELSE IF( EQ_16( length, L_FRAME16k ) )
     478             :     {
     479       86455 :         DoRTFT160_16fx( re2, im2 );
     480             :     }
     481             :     ELSE
     482             :     {
     483             :     }
     484      298375 :     tmp = div_s( 1, length );             /*Q15 */
     485      298375 :     L_tmp = L_mult( tmp, 19302 );         /*Q29, (3*PI/4) in Q13 */
     486      298375 :     fact = round_fx( L_shl( L_tmp, 2 ) ); /*Q15 */
     487    44833127 :     FOR( i = 0; i < shr( length, 1 ); i++ )
     488             :     {
     489    44534752 :         tmp = mult_r( im2[i], fact );            /*Q(Qx+Q_edct) */
     490    44534752 :         re[i] = sub_o( re2[i], tmp, &Overflow ); /*Q(Qx+Q_edct) */
     491    44534752 :         move16();
     492             : 
     493    44534752 :         tmp = mult_r( re2[i], fact );            /*Q(Qx+Q_edct) */
     494    44534752 :         im[i] = add_o( im2[i], tmp, &Overflow ); /*Q(Qx+Q_edct) */
     495    44534752 :         move16();
     496             :     }
     497             : 
     498             :     /* Post-rotate and obtain the output data */
     499      298375 :     py = y + sub( length, 1 );        /*Qx*/
     500      298375 :     pt = edct_table + sub( Len2, 1 ); /*Q15*/
     501    44833127 :     FOR( i = 0; i < Len2; i++ )
     502             :     {
     503    44534752 :         i2 = shl( i, 1 );
     504             : 
     505    44534752 :         L_tmp = L_mult( re[i], edct_table[i] );                              /*Q(Qx+Q_edct+16) */
     506    44534752 :         Lacc = L_mac_o( L_tmp, im[i], *pt, &Overflow );                      /*Q(Qx+Q_edct+16) */
     507    44534752 :         y[i2] = round_fx_o( L_shr_o( Lacc, Q_edct, &Overflow ), &Overflow ); /* Q(Qx) */
     508    44534752 :         move16();
     509             : 
     510    44534752 :         L_tmp = L_mult( re[i], edct_table[sub( shr( length, 1 ), add( 1, i ) )] ); /*Q(Qx+Q_edct+16) */
     511    44534752 :         Lacc = L_msu( L_tmp, im[i], edct_table[i] );                               /*Q(Qx+Q_edct+16) */
     512    44534752 :         *py = round_fx_o( L_shr_o( Lacc, Q_edct, &Overflow ), &Overflow );         /* Q(Qx) */
     513    44534752 :         move16();
     514             : 
     515    44534752 :         py -= 2;
     516    44534752 :         pt--;
     517             :     }
     518      298375 :     return;
     519             : }
     520             : 
     521             : 
     522             : /*-----------------------------------------------------------------*
     523             :  * iedct_short_fx()
     524             :  *
     525             :  * Inverse EDCT for short frames
     526             :  *-----------------------------------------------------------------*/
     527             : 
     528        6052 : void iedct_short_fx(
     529             :     const Word32 *in,           /* i  : input vector     Q*/
     530             :     Word16 *Q,                  /* i/o: Q value of input */
     531             :     Word32 *out,                /* o  : output vector    Q*/
     532             :     const Word16 segment_length /* i  : length           Q0*/
     533             : )
     534             : {
     535             :     Word32 alias[MAX_SEGMENT_LENGTH];
     536             :     Word16 seg_len_div2, seg_len_div4, seg_len_3mul_div4;
     537             :     Word16 i;
     538             :     Word16 qtmp, tmp;
     539             : 
     540        6052 :     qtmp = *Q;
     541        6052 :     move16();
     542        6052 :     tmp = 0;
     543        6052 :     move16();
     544        6052 :     seg_len_div2 = shr( segment_length, 1 ); /*Q0*/
     545        6052 :     seg_len_div4 = shr( segment_length, 2 ); /*Q0*/
     546        6052 :     seg_len_3mul_div4 = add( seg_len_div2, seg_len_div4 );
     547             : 
     548        6052 :     edct_fx( in, alias, seg_len_div2, Q );
     549        9095 :     FOR( i = 0; i < seg_len_div2; i++ )
     550             :     {
     551        9057 :         IF( alias[i] != 0 )
     552             :         {
     553        6014 :             tmp = 1;
     554        6014 :             move16();
     555        6014 :             BREAK;
     556             :         }
     557             :     }
     558        6052 :     if ( tmp == 0 )
     559             :     {
     560          38 :         *Q = qtmp;
     561          38 :         move16();
     562             :     }
     563      411972 :     FOR( i = 0; i < seg_len_div4; i++ )
     564             :     {
     565      405920 :         out[i] = alias[( seg_len_div4 + i )]; /*Q*/
     566      405920 :         move32();
     567      405920 :         out[( seg_len_div4 + i )] = L_negate( alias[( ( seg_len_div2 - 1 ) - i )] ); /*Q*/
     568      405920 :         move32();
     569      405920 :         out[( seg_len_div2 + i )] = L_negate( alias[( ( seg_len_div4 - 1 ) - i )] ); /*Q*/
     570      405920 :         move32();
     571      405920 :         out[( seg_len_3mul_div4 + i )] = L_negate( alias[i] ); /*Q*/
     572      405920 :         move32();
     573             :     }
     574             : 
     575        6052 :     return;
     576             : }
     577             : 
     578             : #define FAST_EDXT /* optimized FFT-based DCT/DST algorithm */
     579             : /*-------------------------------------------------------------------------*
     580             :  * edxt_fx()
     581             :  *
     582             :  * DCT/DST-II or III transform (currently also calculates DCT-IV and DST-IV)
     583             :  *-------------------------------------------------------------------------*/
     584             : 
     585        1566 : void edxt_fx(
     586             :     const Word32 *x,          /* i  : input signal        Qx*/
     587             :     Word32 *y,                /* o  : output transform    Qx*/
     588             :     const Word16 length,      /* i  : length              Q0*/
     589             :     const UWord16 kernelType, /* i  : kernel type (0 - 3) Q0*/
     590             :     const UWord16 synthesis   /* i  : nonzero for inverse Q0*/
     591             : )
     592             : {
     593        1566 :     Word16 k, m, fac, hdrm, tmp = 0;
     594             :     const Word16 *cosPtr, *sinPtr;
     595             :     Word16 n;
     596        1566 :     n = 0;
     597        1566 :     move16();
     598        1566 :     move16();
     599        1566 :     cosPtr = NULL;
     600        1566 :     sinPtr = NULL;
     601        1566 :     IF( EQ_16( length, 512 ) )
     602             :     {
     603         262 :         cosPtr = cos_scale_tbl_512; /*Q15*/
     604         262 :         sinPtr = sin_scale_tbl_512; /*Q15*/
     605         262 :         n = 1;
     606         262 :         move16();
     607             :     }
     608        1304 :     ELSE IF( EQ_16( length, 256 ) )
     609             :     {
     610           5 :         cosPtr = cos_scale_tbl_512; /*Q15*/
     611           5 :         sinPtr = sin_scale_tbl_512; /*Q15*/
     612           5 :         n = 2;
     613           5 :         move16();
     614             :     }
     615        1299 :     ELSE IF( EQ_16( length, 128 ) )
     616             :     {
     617           7 :         cosPtr = cos_scale_tbl_512; /*Q15*/
     618           7 :         sinPtr = sin_scale_tbl_512; /*Q15*/
     619           7 :         n = 4;
     620           7 :         move16();
     621             :     }
     622        1292 :     ELSE IF( EQ_16( length, 640 ) )
     623             :     {
     624         369 :         cosPtr = cos_scale_tbl_640; /*Q15*/
     625         369 :         sinPtr = sin_scale_tbl_640; /*Q15*/
     626         369 :         n = 1;
     627         369 :         move16();
     628             :     }
     629         923 :     ELSE IF( EQ_16( length, 320 ) )
     630             :     {
     631         634 :         cosPtr = cos_scale_tbl_640; /*Q15*/
     632         634 :         sinPtr = sin_scale_tbl_640; /*Q15*/
     633         634 :         n = 2;
     634         634 :         move16();
     635             :     }
     636         289 :     ELSE IF( EQ_16( length, 160 ) )
     637             :     {
     638          37 :         cosPtr = cos_scale_tbl_640; /*Q15*/
     639          37 :         sinPtr = sin_scale_tbl_640; /*Q15*/
     640          37 :         n = 4;
     641          37 :         move16();
     642             :     }
     643         252 :     ELSE IF( EQ_16( length, 80 ) )
     644             :     {
     645          32 :         cosPtr = cos_scale_tbl_640; /*Q15*/
     646          32 :         sinPtr = sin_scale_tbl_640; /*Q15*/
     647          32 :         n = 8;
     648          32 :         move16();
     649             :     }
     650         220 :     ELSE IF( EQ_16( length, 40 ) )
     651             :     {
     652           0 :         cosPtr = cos_scale_tbl_640; /*Q15*/
     653           0 :         sinPtr = sin_scale_tbl_640; /*Q15*/
     654           0 :         n = 16;
     655           0 :         move16();
     656             :     }
     657         220 :     ELSE IF( EQ_16( length, 960 ) )
     658             :     {
     659         220 :         cosPtr = cos_scale_tbl_960; /*Q15*/
     660         220 :         sinPtr = sin_scale_tbl_960; /*Q15*/
     661         220 :         n = 1;
     662         220 :         move16();
     663             :     }
     664           0 :     ELSE IF( EQ_16( length, 480 ) )
     665             :     {
     666           0 :         cosPtr = cos_scale_tbl_960; /*Q15*/
     667           0 :         sinPtr = sin_scale_tbl_960; /*Q15*/
     668           0 :         n = 2;
     669           0 :         move16();
     670             :     }
     671           0 :     ELSE IF( EQ_16( length, 240 ) )
     672             :     {
     673           0 :         cosPtr = cos_scale_tbl_960; /*Q15*/
     674           0 :         sinPtr = sin_scale_tbl_960; /*Q15*/
     675           0 :         n = 4;
     676           0 :         move16();
     677             :     }
     678           0 :     ELSE IF( EQ_16( length, 120 ) )
     679             :     {
     680           0 :         cosPtr = cos_scale_tbl_960; /*Q15*/
     681           0 :         sinPtr = sin_scale_tbl_960; /*Q15*/
     682           0 :         n = 8;
     683           0 :         move16();
     684             :     }
     685           0 :     ELSE IF( EQ_16( length, 1200 ) )
     686             :     {
     687           0 :         cosPtr = cos_scale_tbl_1200; /*Q15*/
     688           0 :         sinPtr = sin_scale_tbl_1200; /*Q15*/
     689           0 :         n = 1;
     690           0 :         move16();
     691             :     }
     692           0 :     ELSE IF( EQ_16( length, 800 ) )
     693             :     {
     694           0 :         cosPtr = cos_scale_tbl_800; /*Q15*/
     695           0 :         sinPtr = sin_scale_tbl_800; /*Q15*/
     696           0 :         n = 1;
     697           0 :         move16();
     698             :     }
     699           0 :     ELSE IF( EQ_16( length, 400 ) )
     700             :     {
     701           0 :         cosPtr = cos_scale_tbl_800; /*Q15*/
     702           0 :         sinPtr = sin_scale_tbl_800; /*Q15*/
     703           0 :         n = 2;
     704           0 :         move16();
     705             :     }
     706           0 :     ELSE IF( EQ_16( length, 200 ) )
     707             :     {
     708           0 :         cosPtr = cos_scale_tbl_800; /*Q15*/
     709           0 :         sinPtr = sin_scale_tbl_800; /*Q15*/
     710           0 :         n = 4;
     711           0 :         move16();
     712             :     }
     713             : 
     714             : #ifdef FAST_EDXT
     715        1566 :     test();
     716        1566 :     IF( EQ_16( kernelType, MDST_II ) || EQ_16( kernelType, MDCT_II ) )
     717             :     {
     718        1566 :         const Word16 Nm1 = sub( length, 1 );
     719        1566 :         const Word16 xSign = sub( imult1616( 2, shr( kernelType, 1 ) ), 1 ); /*Q0*/
     720             :         Word32 re[L_FRAME_PLUS];
     721             :         Word32 im[L_FRAME_PLUS];
     722             : 
     723        1566 :         IF( !synthesis )
     724             :         {
     725      148366 :             FOR( k = ( Nm1 / 2 ); k >= 0; k-- ) /* pre-modulation of audio input */
     726             :             {
     727      147840 :                 re[k] = x[2 * k];                                                            /*Qx*/
     728      147840 :                 re[( Nm1 - k )] = Mpy_32_16_1( x[( ( k * 2 ) + 1 )], shl_sat( xSign, 15 ) ); /*Qx*/
     729      147840 :                 im[k] = im[( Nm1 - k )] = 0;
     730      147840 :                 move32();
     731      147840 :                 move32();
     732      147840 :                 move32();
     733             :             }
     734             : 
     735         526 :             IF( EQ_16( length, 512 ) )
     736             :             {
     737             :                 /* Scaling down re and im buffers to avoid overflow in DoRTFTn_fx if the minimum headroom is less than 4 bits */
     738           0 :                 hdrm = s_min( L_norm_arr( re, 512 ), L_norm_arr( im, 512 ) );
     739           0 :                 IF( LT_16( hdrm, 4 ) )
     740             :                 {
     741           0 :                     tmp = sub( hdrm, 4 );
     742           0 :                     scale_sig32( re, 512, tmp );
     743           0 :                     scale_sig32( im, 512, tmp );
     744             :                 }
     745             : 
     746           0 :                 DoRTFTn_fx( re, im, 512 );
     747             : 
     748           0 :                 IF( LT_16( hdrm, 4 ) )
     749             :                 {
     750           0 :                     tmp = negate( tmp );
     751           0 :                     scale_sig32( re, 512, tmp );
     752           0 :                     scale_sig32( im, 512, tmp );
     753             :                 }
     754             :             }
     755             :             ELSE /* fft() doesn't support 512 */
     756             :             {
     757         526 :                 fft_fx( re, im, length, 1 );
     758             :             }
     759             : 
     760         526 :             IF( shr( kernelType, 1 ) )
     761             :             {
     762       72400 :                 FOR( k = ( Nm1 / 2 ); k > 0; k-- )
     763             :                 {
     764             :                     // const float wRe = cosf( scale * k );
     765             :                     // const float wIm = sinf( scale * k );
     766       72138 :                     const Word16 wRe = cosPtr[( k * n )]; /*Q15*/
     767       72138 :                     const Word16 wIm = sinPtr[( k * n )]; /*Q15*/
     768             : 
     769       72138 :                     y[k] /*pt 1*/ = L_add( Mpy_32_16_1( re[k], wRe ), Mpy_32_16_1( im[k], wIm ) );     /*Qx*/
     770       72138 :                     y[( length - k )] = L_sub( Mpy_32_16_1( re[k], wIm ), Mpy_32_16_1( im[k], wRe ) ); /*Qx*/
     771       72138 :                     move32();
     772       72138 :                     move32();
     773             :                 }
     774         262 :                 y[( length / 2 )] = Mpy_32_16_1( re[( length / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
     775         262 :                 move32();
     776             :             }
     777             :             ELSE /* forw. DST-II */
     778             :             {
     779       75440 :                 FOR( k = ( Nm1 / 2 ); k > 0; k-- )
     780             :                 {
     781             :                     // const float wRe = cosf( scale * k );
     782             :                     // const float wIm = sinf( scale * k );
     783       75176 :                     const Word16 wRe = cosPtr[( k * n )]; /*Q15*/
     784       75176 :                     const Word16 wIm = sinPtr[( k * n )]; /*Q15*/
     785             : 
     786       75176 :                     y[( Nm1 - k )] = L_add( Mpy_32_16_1( re[k], wRe ), Mpy_32_16_1( im[k], wIm ) ); /*Qx*/
     787       75176 :                     y[k - 1] = L_sub( Mpy_32_16_1( re[k], wIm ), Mpy_32_16_1( im[k], wRe ) );       /*Qx*/
     788       75176 :                     move32();
     789       75176 :                     move32();
     790             :                 }
     791         264 :                 y[( Nm1 / 2 )] = Mpy_32_16_1( re[( length / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
     792         264 :                 move32();
     793             :             }
     794             : 
     795         526 :             y[( Nm1 - ( Nm1 * ( kernelType / 2 ) ) )] = L_shr( re[0], 1 ); /*Qx*/
     796         526 :             move32();
     797             :         }
     798             :         ELSE /* inverse II = III */
     799             :         {
     800        1040 :             IF( shr( kernelType, 1 ) )
     801             :             {
     802      121152 :                 FOR( k = ( Nm1 / 2 ); k > 0; k-- )
     803             :                 {
     804             :                     // const float wRe = cosf( scale * k ) * 0.5f;
     805             :                     // const float wIm = sinf( scale * k ) * 0.5f;
     806      120638 :                     const Word16 wRe = shr( cosPtr[imult1616( k, n )], 1 );
     807      120638 :                     const Word16 wIm = shr( sinPtr[imult1616( k, n )], 1 );
     808             : 
     809      120638 :                     re[k] = L_add( Mpy_32_16_1( x[k], wRe ), Mpy_32_16_1( x[( length - k )], wIm ) ); /*Qx*/
     810      120638 :                     im[k] = L_sub( Mpy_32_16_1( x[( length - k )], wRe ), Mpy_32_16_1( x[k], wIm ) ); /*Qx*/
     811      120638 :                     move32();
     812      120638 :                     move32();
     813             :                 }
     814         514 :                 re[( length / 2 )] = Mpy_32_16_1( x[( length / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
     815         514 :                 move32();
     816             :             }
     817             :             ELSE /* DST type III */
     818             :             {
     819      128528 :                 FOR( k = ( Nm1 / 2 ); k > 0; k-- )
     820             :                 {
     821             :                     // const float wRe = cosf( scale * k ) * 0.5f;
     822             :                     // const float wIm = sinf( scale * k ) * 0.5f;
     823      128002 :                     const Word16 wRe = shr( cosPtr[( k * n )], 1 ); /*Q15*/
     824      128002 :                     const Word16 wIm = shr( sinPtr[( k * n )], 1 ); /*Q15*/
     825             : 
     826      128002 :                     re[k] = L_add( Mpy_32_16_1( x[( Nm1 - k )], wRe ), Mpy_32_16_1( x[( k - 1 )], wIm ) ); /*Qx*/
     827      128002 :                     im[k] = L_sub( Mpy_32_16_1( x[( k - 1 )], wRe ), Mpy_32_16_1( x[( Nm1 - k )], wIm ) ); /*Qx*/
     828      128002 :                     move32();
     829      128002 :                     move32();
     830             :                 }
     831         526 :                 re[( length / 2 )] = Mpy_32_16_1( x[( Nm1 / 2 )], INV_SQRT_2_Q15 ); /*Qx*/
     832         526 :                 move32();
     833             :             }
     834             : 
     835        1040 :             re[0] = x[( Nm1 - ( Nm1 * ( kernelType / 2 ) ) )]; /*Qx*/
     836        1040 :             im[0] = im[( length / 2 )] = 0;
     837        1040 :             move32();
     838        1040 :             move32();
     839      249680 :             FOR( k = ( Nm1 / 2 ); k > 0; k-- )
     840             :             {
     841      248640 :                 re[( length - k )] = re[k];             /*Qx*/
     842      248640 :                 im[( length - k )] = L_negate( im[k] ); /*Qx*/
     843      248640 :                 move32();
     844      248640 :                 move32();
     845             :             }
     846             : 
     847        1040 :             IF( EQ_16( length, 512 ) )
     848             :             {
     849             :                 /* Scaling down re and im buffers to avoid overflow in DoRTFTn_fx if the minimum headroom is less than 4 bits */
     850         262 :                 hdrm = s_min( L_norm_arr( re, 512 ), L_norm_arr( im, 512 ) );
     851         262 :                 IF( LT_16( hdrm, 4 ) )
     852             :                 {
     853           0 :                     tmp = sub( hdrm, 4 );
     854           0 :                     scale_sig32( re, 512, tmp );
     855           0 :                     scale_sig32( im, 512, tmp );
     856             :                 }
     857             : 
     858         262 :                 DoRTFTn_fx( re, im, 512 );
     859             : 
     860         262 :                 IF( LT_16( hdrm, 4 ) )
     861             :                 {
     862           0 :                     tmp = negate( tmp );
     863           0 :                     scale_sig32( re, 512, tmp );
     864           0 :                     scale_sig32( im, 512, tmp );
     865             :                 }
     866             :             }
     867             :             ELSE /* fft() doesn't support 512 */
     868             :             {
     869         778 :                 fft_fx( re, im, length, 1 );
     870             :             }
     871             : 
     872      250720 :             FOR( k = ( Nm1 / 2 ); k >= 0; k-- ) /* post-modulation of FFT output */
     873             :             {
     874      249680 :                 y[2 * k] = re[k]; /*Qx*/
     875      249680 :                 move32();
     876      249680 :                 IF( xSign != 0 )
     877             :                 {
     878      249680 :                     y[( ( k * 2 ) + 1 )] = Mpy_32_16_1( re[( Nm1 - k )], shl_sat( xSign, 15 ) ); /*Qx*/
     879             :                 }
     880             :                 ELSE
     881             :                 {
     882           0 :                     y[( ( k * 2 ) + 1 )] = 0; /*Qx*/
     883             :                 }
     884      249680 :                 move32();
     885             :             }
     886             :         }
     887             :     }
     888             : #endif
     889             : #ifdef IVAS_FLOAT_FIXED_TO_BE_DONE
     890             :     ELSE
     891             :     /* TODO: below IF and ELSE blocks are unreachable, verified on code coverage report */
     892             :     IF( s_and( kernelType, 1 ) ) /* DST */
     893             :     {
     894             :         const float offK = ( kernelType == MDST_II && synthesis ? 0.5f : 1.0f - 0.5f * ( kernelType >> 1 ) );
     895             :         const float offM = ( kernelType == MDST_II && synthesis ? 1.0f : 0.5f );
     896             : 
     897             :         FOR( k = 0; k < length; k++ )
     898             :         {
     899             :             y[k] = 0.f;
     900             :             FOR( m = 0; m < length; m++ )
     901             :             {
     902             :                 y[k] += x[m] * sinf( pi_len * ( m + offM ) * ( k + offK ) );
     903             :             }
     904             :         }
     905             :         IF( offK == 1.f )
     906             :         {
     907             :             y[length - 1] *= 0.5f; /* scale Nyquist sample */
     908             :         }
     909             :     }
     910             :     ELSE /* kernelType 0, 2: DCT */
     911             :     {
     912             :         const float offK = ( EQ_16( kernelType, MDCT_II ) && synthesis ? 0.5f : 0.5f - shr( shr( kernelType, 1 ), 1 ) );
     913             :         const float offM = ( EQ_16( kernelType, MDCT_II ) && synthesis ? 0.0f : 0.5f );
     914             : 
     915             :         FOR( k = 0; k < length; k++ )
     916             :         {
     917             :             y[k] = 0.f;
     918             :             FOR( m = 0; m < length; m++ )
     919             :             {
     920             :                 y[k] += x[m] * cosf( pi_len * ( m + offM ) * ( k + offK ) );
     921             :             }
     922             :         }
     923             :         IF( offK == 0.f )
     924             :         {
     925             :             y[0] *= 0.5f; /* scale lowest (i.e. DC) sample */
     926             :         }
     927             :     }
     928             : #endif // IVAS_FLOAT_FIXED_TO_BE_DONE
     929             :     /*v_multc(y, (kernelType == MDCT_II ? -1.f : 1.f) * sqrtf(2.f / length), y, length);*/
     930        1566 :     fac = get_edxt_factor( length ); /* Q15 */
     931        1566 :     if ( EQ_16( kernelType, MDCT_II ) )
     932             :     {
     933         776 :         fac = negate( fac );
     934             :     }
     935             : 
     936      796606 :     FOR( m = 0; m < length; m++ )
     937             :     {
     938      795040 :         y[m] = Mpy_32_16_1( y[m], fac ); /*Qx*/
     939      795040 :         move32();
     940             :     }
     941        1566 :     return;
     942             : }

Generated by: LCOV version 1.14