LCOV - code coverage report
Current view: top level - lib_com - cldfb_evs_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 547 741 73.8 %
Date: 2025-08-23 01:22:27 Functions: 16 21 76.2 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : /*!
       5             :   \file
       6             :   \brief  Complex cldfb analysis/synthesis, $Revision: 1214 $
       7             :   This module contains the cldfb filterbank for analysis [ cplxAnalysisCldfbFiltering() ] and
       8             :   synthesis [ cplxSynthesisCldfbFiltering() ]. It is a polyphase implementation of a complex
       9             :   exponential modulated filter bank. The analysis part usually runs at half the sample rate
      10             :   than the synthesis part. (So called "dual-rate" mode.)
      11             : 
      12             :   \anchor PolyphaseFiltering <h2>About polyphase filtering</h2>
      13             :   The polyphase implementation of a filterbank requires filtering at the input and output.
      14             :   This is implemented as part of cplxAnalysisCldfbFiltering() and cplxSynthesisCldfbFiltering().
      15             : 
      16             : */
      17             : 
      18             : #include "stl.h"
      19             : #include "cnst.h"
      20             : #include "stat_com.h"
      21             : #include "rom_com.h"
      22             : #include "basop_util.h"
      23             : #include "prot_fx.h"
      24             : #include <assert.h>
      25             : 
      26             : #define STATE_BUFFER_SIZE ( 9 + 16 )
      27             : 
      28             : #define CLDFB_NO_POLY       ( 5 )
      29             : #define SYN_FILTER_HEADROOM ( 1 )
      30             : 
      31             : #define CLDFB_LDCLDFB_PFT_SCALE     ( 0 )
      32             : #define CLDFB_CLDFB80_O24_PFT_SCALE ( 1 )
      33             : #define CLDFB_CLDFB80_O5_PFT_SCALE  ( 1 )
      34             : #define CLDFB_CLDFB80_PFT_SCALE     ( 1 )
      35             : 
      36             : 
      37             : #define SYN_FILTER_HEADROOM_1MS   ( 2 )
      38             : #define SYN_FILTER_HEADROOM_2MS   ( 2 )
      39             : #define SYN_FILTER_HEADROOM_2_5MS ( 2 )
      40             : #define SYN_FILTER_HEADROOM_8MS   ( 1 )
      41             : 
      42             : #define N8  ( 4 )
      43             : #define N10 ( 5 )
      44             : #define N16 ( 8 )
      45             : #define N20 ( 10 )
      46             : #define N30 ( 15 )
      47             : #define N32 ( 16 )
      48             : #define N40 ( 20 )
      49             : #define N60 ( 30 )
      50             : 
      51             : static void
      52             : cldfb_init_proto_and_twiddles( HANDLE_CLDFB_FILTER_BANK hs );
      53             : 
      54             : #define cplxMpyS( yr, yi, xr, xi, cr, ci, syr, syi, sxr, sxi, CL_x, CL_z, C_c ) \
      55             :     CL_x = CL_form( *xr, *xi );                                                 \
      56             :     C_c = C_form( *cr, *ci );                                                   \
      57             :     CL_z = CL_mult_32x16( CL_x, C_c );                                          \
      58             :     *yr = CL_Extract_real( CL_z );                                              \
      59             :     *yi = CL_Extract_imag( CL_z );                                              \
      60             :     yr += syr, yi += syi, xr += sxr, xi += sxi, cr++, ci++
      61             : 
      62             : #define cplxMpy( ryr, ryi, iyr, iyi, rxr, rxi, ixr, ixi, cr, ci, g, sx, sr, CL_x, CL_ry, CL_iy, C_c ) \
      63             :     CL_x = CL_form( *rxr, *rxi );                                                                     \
      64             :     C_c = C_form( *cr, *ci );                                                                         \
      65             :     CL_ry = CL_mult_32x16( CL_x, C_c );                                                               \
      66             :     CL_x = CL_form( *ixr, *ixi );                                                                     \
      67             :     CL_iy = CL_mult_32x16( CL_x, C_c );                                                               \
      68             :     CL_ry = CL_scale_t( CL_ry, g );                                                                   \
      69             :     CL_iy = CL_scale_t( CL_iy, g );                                                                   \
      70             :     ryr = CL_Extract_real( CL_ry );                                                                   \
      71             :     ryi = CL_Extract_imag( CL_ry );                                                                   \
      72             :     iyr = CL_Extract_real( CL_iy );                                                                   \
      73             :     iyi = CL_Extract_imag( CL_iy );                                                                   \
      74             :     rxr += sx, rxi += sx, ixr += sx, ixi += sx, cr += sr, ci += sr
      75             : 
      76             : #define add1( y1, y2, y3, y4, rr12, ri12, ir12, ii12, s )                      \
      77             :     *y1 = round_fx_sat( L_shl_sat( L_negate( L_add_sat( rr12, ii12 ) ), s ) ); \
      78             :     *y2 = round_fx_sat( L_shl_sat( L_negate( L_add_sat( ri12, ir12 ) ), s ) ); \
      79             :     *y3 = round_fx_sat( L_shl_sat( L_sub_sat( rr12, ii12 ), s ) );             \
      80             :     *y4 = round_fx_sat( L_shl_sat( L_sub_sat( ir12, ri12 ), s ) );             \
      81             :     y1 += 2, y2 -= 2, y3 -= 2, y4 += 2
      82             : 
      83             : #define add2( y1, y2, y3, y4, rr12, ri12, ir12, ii12, s )          \
      84             :     *y1 = round_fx_sat( L_shl_sat( L_add_sat( ri12, ir12 ), s ) ); \
      85             :     *y2 = round_fx_sat( L_shl_sat( L_add_sat( rr12, ii12 ), s ) ); \
      86             :     *y3 = round_fx_sat( L_shl_sat( L_sub_sat( ir12, ri12 ), s ) ); \
      87             :     *y4 = round_fx_sat( L_shl_sat( L_sub_sat( rr12, ii12 ), s ) ); \
      88             :     y1 += 2, y2 -= 2, y3 -= 2, y4 += 2
      89             : 
      90             : 
      91             : #define ptrUpdate16( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 ) \
      92             :     y11 += 2 * N8, y12 -= 2 * N8, y13 -= 2 * N8, y14 += 2 * N8, r11 -= 1 * N8;                                            \
      93             :     x11 -= 2 * N8, x12 -= 2 * N8, x13 -= 2 * N8, x14 -= 2 * N8, r12 -= 1 * N8;                                            \
      94             :     y21 += 2 * N8, y22 -= 2 * N8, y23 -= 2 * N8, y24 += 2 * N8, r21 += 1 * N8;                                            \
      95             :     x21 += 2 * N8, x22 += 2 * N8, x23 += 2 * N8, x24 += 2 * N8, r22 += 1 * N8
      96             : 
      97             : #define ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 ) \
      98             :     y11 += 2 * N10, y12 -= 2 * N10, y13 -= 2 * N10, y14 += 2 * N10, r11 -= 1 * N10;                                       \
      99             :     x11 -= 2 * N10, x12 -= 2 * N10, x13 -= 2 * N10, x14 -= 2 * N10, r12 -= 1 * N10;                                       \
     100             :     y21 += 2 * N10, y22 -= 2 * N10, y23 -= 2 * N10, y24 += 2 * N10, r21 += 1 * N10;                                       \
     101             :     x21 += 2 * N10, x22 += 2 * N10, x23 += 2 * N10, x24 += 2 * N10, r22 += 1 * N10
     102             : 
     103             : 
     104           0 : static void cplxMultAdd10_1( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
     105             : {
     106             :     Word32 rr12, ri12, ir12, ii12;
     107             :     cmplx CL_x, CL_ry, CL_iy;
     108             :     cmplx_s C_c;
     109             : 
     110           0 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     111           0 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     112           0 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     113           0 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     114           0 : }
     115             : 
     116           0 : static void cplxMultAdd10_2( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
     117             : {
     118             :     Word32 rr12, ri12, ir12, ii12;
     119             :     cmplx CL_x, CL_ry, CL_iy;
     120             :     cmplx_s C_c;
     121             : 
     122           0 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     123           0 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     124           0 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     125           0 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     126           0 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     127           0 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     128           0 : }
     129             : 
     130             : 
     131      111844 : static void cplxMultAdd20_1( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
     132             : {
     133             :     Word32 rr12, ri12, ir12, ii12;
     134             :     cmplx CL_x, CL_ry, CL_iy;
     135             :     cmplx_s C_c;
     136             : 
     137      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     138      111844 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     139      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     140      111844 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     141      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     142      111844 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     143      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     144      111844 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     145      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     146      111844 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     147      111844 : }
     148             : 
     149      111844 : static void cplxMultAdd20_2( Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, Word16 sx, Word16 sr )
     150             : {
     151             :     Word32 rr12, ri12, ir12, ii12;
     152             :     cmplx CL_x, CL_ry, CL_iy;
     153             :     cmplx_s C_c;
     154             : 
     155      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     156      111844 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     157      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     158      111844 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     159      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     160      111844 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     161      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     162      111844 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     163      111844 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     164      111844 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     165      111844 : }
     166             : 
     167             : /* calcModulation
     168             : 
     169             :    Parameters:
     170             :      *rYR              O: pointer to real output samples (DST)
     171             :      *rYI              O: pointer to imaginary output samples (DST)
     172             :      *rXR              I: pointer to real input samples (DST)
     173             :      *rXI              I: pointer to imaginary input samples (DST)
     174             :      srYR              I: offset for update of pointer to real output samples (DST)
     175             :      srYI              I: offset for update of pointer to imaginary output samples (DST)
     176             :      srXR              I: offset for update of pointer to real input samples (DST)
     177             :      srXI              I: offset for update of pointer to imaginary input samples (DST)
     178             :      *iYR              O: pointer to real output samples (DCT)
     179             :      *iYI              O: pointer to imaginary output samples (DCT)
     180             :      *iXR              I: pointer to real input samples (DCT)
     181             :      *iXI              I: pointer to imaginary input samples (DCT)
     182             :      siYR              I: offset for update of pointer to real output samples (DCT)
     183             :      siYI              I: offset for update of pointer to imaginary output samples (DCT)
     184             :      siXR              I: offset for update of pointer to real input samples (DCT)
     185             :      siXI              I: offset for update of pointer to imaginary input samples (DCT)
     186             :      m                 I: processed cldfb bands
     187             : 
     188             :    Function:
     189             :      The function applies for each cldfb length a unrolled complex modulation
     190             : 
     191             :    Returns:
     192             :       void
     193             : */
     194      212406 : static void calcModulation( Word32 *rYR,
     195             :                             Word32 *rYI,
     196             :                             Word32 *rXR,
     197             :                             Word32 *rXI,
     198             :                             Word16 srYR,
     199             :                             Word16 srYI,
     200             :                             Word16 srXR,
     201             :                             Word16 srXI,
     202             :                             Word32 *iYR,
     203             :                             Word32 *iYI,
     204             :                             Word32 *iXR,
     205             :                             Word32 *iXI,
     206             :                             Word16 siYR,
     207             :                             Word16 siYI,
     208             :                             Word16 siXR,
     209             :                             Word16 siXI,
     210             :                             const Word16 *rRotVctr,
     211             :                             const Word16 *iRotVctr,
     212             :                             Word16 m )
     213             : {
     214             :     cmplx CL_x, CL_z;
     215             :     cmplx_s C_c;
     216             :     Word32 i;
     217      212406 :     Word32 lc = L_shr( m, 1 );
     218             : 
     219      212406 :     const Word16 *cr = rRotVctr;
     220      212406 :     const Word16 *ci = iRotVctr;
     221             : 
     222     2898910 :     FOR( i = 0; i < lc; i++ )
     223             :     {
     224     2686504 :         CL_x = CL_form( *rXR, *rXI );
     225     2686504 :         C_c = C_form( *cr, *ci );
     226     2686504 :         CL_z = CL_mult_32x16( CL_x, C_c );
     227     2686504 :         *rYR = CL_Extract_real( CL_z );
     228     2686504 :         move32();
     229     2686504 :         *rYI = CL_Extract_imag( CL_z );
     230     2686504 :         move32();
     231     2686504 :         rYR += srYR;
     232     2686504 :         rYI += srYI;
     233     2686504 :         rXR += srXR;
     234     2686504 :         rXI += srXI;
     235             : 
     236     2686504 :         CL_x = CL_form( *iXR, *iXI );
     237     2686504 :         CL_z = CL_mult_32x16( CL_x, C_c );
     238     2686504 :         *iYR = CL_Extract_real( CL_z );
     239     2686504 :         move32();
     240     2686504 :         *iYI = CL_Extract_imag( CL_z );
     241     2686504 :         move32();
     242     2686504 :         iYR += siYR;
     243     2686504 :         iYI += siYI;
     244     2686504 :         iXR += siXR;
     245     2686504 :         iXI += siXI;
     246     2686504 :         cr++;
     247     2686504 :         ci++;
     248             :     }
     249      212406 : }
     250             : 
     251             : 
     252             : /* calcModulationAndFolding
     253             : 
     254             :    Parameters:
     255             :      *rY               O: pointer to folded samples (DST + DCT)
     256             :      *rX               I: pointer to real input samples (DST)
     257             :      *iX               I: pointer to imaginary input samples (DCT)
     258             :      *rRotVctr         I: pointer to real modulation coefficients
     259             :      *iRotVctr         I: pointer to imaginary modulation coefficients
     260             :      gain              I: gain value
     261             :      scale             I: scale factor
     262             :      m                 I: processed cldfb bands
     263             :      m2                I: half of processed cldfb bands
     264             : 
     265             :    Function:
     266             :      The function applies for each cldfb length a unrolled complex modulation with subsequent data folding
     267             : 
     268             :    Returns:
     269             :       void
     270             : */
     271       42710 : static void calcModulationAndFolding( Word16 *rY,
     272             :                                       Word32 *rX,
     273             :                                       Word32 *iX,
     274             :                                       const Word16 *rRotVctr,
     275             :                                       const Word16 *iRotVctr,
     276             :                                       Word16 gain,
     277             :                                       Word16 scale,
     278             :                                       Word16 m,
     279             :                                       Word16 m2 )
     280             : {
     281             :     Word16 *y11, *y12, *y13, *y14;
     282             :     Word16 *y21, *y22, *y23, *y24;
     283             :     Word32 *x11, *x12, *x13, *x14;
     284             :     Word32 *x21, *x22, *x23, *x24;
     285             :     const Word16 *r11, *r12, *r21, *r22;
     286             : 
     287             : 
     288       42710 :     y11 = &rY[( m + m2 ) + 1];
     289       42710 :     y12 = &rY[m2 - 2];
     290       42710 :     y13 = &rY[( m + m2 ) - 2];
     291       42710 :     y14 = &rY[m2 + 1];
     292             : 
     293       42710 :     y21 = &rY[m + m2];
     294       42710 :     y22 = &rY[m2 - 1];
     295       42710 :     y23 = &rY[( m + m2 ) - 1];
     296       42710 :     y24 = &rY[m2];
     297             : 
     298       42710 :     x11 = &rX[m - 2];
     299       42710 :     x12 = &rX[m - 1];
     300       42710 :     x13 = &iX[m - 2];
     301       42710 :     x14 = &iX[m - 1];
     302       42710 :     x21 = &rX[0];
     303       42710 :     x22 = &rX[1];
     304       42710 :     x23 = &iX[0];
     305       42710 :     x24 = &iX[1];
     306             : 
     307       42710 :     r11 = &rRotVctr[m2 - 1];
     308       42710 :     r12 = &iRotVctr[m2 - 1];
     309       42710 :     r21 = &rRotVctr[0];
     310       42710 :     r22 = &iRotVctr[0];
     311             : 
     312       42710 :     SWITCH( m )
     313             :     {
     314           0 :         case 10:
     315           0 :             cplxMultAdd10_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     316           0 :             cplxMultAdd10_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     317           0 :             BREAK;
     318           0 :         case 20:
     319           0 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     320           0 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     321           0 :             BREAK;
     322       26424 :         case 60:
     323       26424 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     324       26424 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     325       26424 :             ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
     326             :             /* no break */
     327       42710 :         case 40:
     328       42710 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     329       42710 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     330       42710 :             ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
     331       42710 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     332       42710 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     333       42710 :             ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
     334       42710 :             BREAK;
     335           0 :         default:
     336           0 :             assert( 0 );
     337             :     }
     338       42710 : }
     339             : 
     340             : 
     341             : /* cldfbAnalysis_fx
     342             : 
     343             :    Parameters:
     344             :      cldfbBank          I/O: handle to analysis CLDFB filter struct
     345             :      **rAnalysis      O:   matrix holding the real part of the subband samples
     346             :      **iAnalysis      O:   matrix holding the imaginary part of the subband samples
     347             :      *scaleFactor     O:   pointer to cldfb scalefactor struct
     348             :      *timeIn          I:   pointer to time domain data
     349             :      stride           I:   stride for time domain data
     350             :      *pWorkBuffer     I:   pointer to scratch buffer, needed for buffer of size 2*cldfbbands*Word32
     351             : 
     352             :    Function:
     353             :       Performs complex-valued subband filtering of the time domain data of timeIn and stores the real
     354             :       part of the subband samples in rAnalysis, and the imaginary part in iAnalysis
     355             : 
     356             :    Returns:
     357             :       void
     358             : */
     359        5370 : void cldfbAnalysis_fx(
     360             :     HANDLE_CLDFB_FILTER_BANK cldfbBank,
     361             :     Word32 **rAnalysis,
     362             :     Word32 **iAnalysis,
     363             :     CLDFB_SCALE_FACTOR *scaleFactor,
     364             :     const Word16 *timeIn, // Q(15-timeIn_e)
     365             :     const Word16 timeIn_e,
     366             :     const Word16 nTimeSlots,
     367             :     Word32 *pWorkBuffer // Qx
     368             : )
     369             : 
     370             : {
     371             :     Word16 i, k;
     372             :     Word16 L2, L3, L4, m, m2, M4;
     373             :     Word16 M0M2, M2M1, L3M1, L4M1;
     374             :     Word16 scale;
     375             :     Word16 offset;
     376             :     Word16 p_stride;
     377             :     Word16 nSamples;
     378             :     Word16 nSamplesUpd;
     379             :     Word16 stride;
     380             : 
     381             :     Word32 r1, r2;
     382             :     Word32 i1, i2;
     383             :     Word32 *rBuffer;
     384             :     Word32 *iBuffer;
     385             :     Word16 *pStates;
     386             : 
     387             :     Word16 *pStates1;
     388             :     Word16 *pStates2;
     389             :     Word16 *pStates3;
     390             :     Word16 *pStates4;
     391             :     Word16 *pStates6;
     392             :     Word16 *pStates5;
     393             : 
     394             :     const Word16 *rRotVctr;
     395             :     const Word16 *iRotVctr;
     396             :     const Word16 *pFilter;
     397             : 
     398             :     const Word16 *pFilter1;
     399             :     const Word16 *pFilter2;
     400             :     const Word16 *pFilter3;
     401             :     const Word16 *pFilter4;
     402             :     const Word16 *pFilter6;
     403             :     const Word16 *pFilter5;
     404             :     Word32 workBuffer[2 * BASOP_CFFT_MAX_LENGTH];
     405             : 
     406             : 
     407        5370 :     stride = 1; /* constant */
     408        5370 :     move16();
     409        5370 :     m = cldfbBank->no_channels;
     410        5370 :     move16();
     411        5370 :     L2 = shl( m, 1 );
     412        5370 :     m2 = shr( m, 1 );
     413        5370 :     M4 = shr( m, 2 );
     414        5370 :     M4 = sub( m2, M4 );
     415             : 
     416        5370 :     L3 = sub( L2, m2 );
     417        5370 :     L4 = add( L2, m2 );
     418             : 
     419        5370 :     M0M2 = sub( 0, m2 );
     420        5370 :     M2M1 = sub( m2, 1 );
     421        5370 :     L3M1 = sub( L3, 1 );
     422        5370 :     L4M1 = sub( L4, 1 );
     423             : 
     424        5370 :     rBuffer = &pWorkBuffer[0];
     425        5370 :     iBuffer = &pWorkBuffer[m];
     426             : 
     427        5370 :     rRotVctr = cldfbBank->rRotVctr;
     428        5370 :     iRotVctr = cldfbBank->iRotVctr;
     429             : 
     430        5370 :     pStates = cldfbBank->FilterStates;
     431        5370 :     pStates1 = &pStates[L3M1];
     432        5370 :     pStates2 = &pStates[L3];
     433        5370 :     pStates3 = &pStates[m2];
     434        5370 :     pStates4 = &pStates[M2M1];
     435        5370 :     pStates5 = &pStates[L4M1];
     436        5370 :     pStates6 = &pStates[M0M2];
     437             : 
     438        5370 :     p_stride = CLDFB_NO_POLY;
     439        5370 :     move16();
     440        5370 :     pFilter = &cldfbBank->p_filter[p_stride - CLDFB_NO_POLY];
     441        5370 :     pFilter1 = &pFilter[p_stride * L3M1];
     442        5370 :     pFilter2 = &pFilter[p_stride * L3];
     443        5370 :     pFilter3 = &pFilter[p_stride * m2];
     444        5370 :     pFilter4 = &pFilter[p_stride * M2M1];
     445        5370 :     pFilter5 = &pFilter[p_stride * L4M1];
     446        5370 :     pFilter6 = &pFilter[p_stride * M0M2];
     447             : 
     448        5370 :     nSamples = i_mult( nTimeSlots, cldfbBank->no_channels );
     449        5370 :     nSamplesUpd = i_mult( cldfbBank->no_col, cldfbBank->no_channels );
     450        5370 :     offset = sub( sub( cldfbBank->p_filter_length, cldfbBank->no_channels ), cldfbBank->zeros );
     451             : 
     452             :     /* Determine states scale */
     453        5370 :     scale = -15;
     454        5370 :     move16();
     455        5370 :     k = 0;
     456        5370 :     move16();
     457       53700 :     FOR( i = 0; i < offset; i += cldfbBank->no_channels )
     458             :     {
     459       48330 :         cldfbBank->FilterStates_e[k] = cldfbBank->FilterStates_e[( k + cldfbBank->no_col )];
     460       48330 :         move16();
     461       48330 :         assert( (size_t) k < sizeof( cldfbBank->FilterStates_e ) / sizeof( cldfbBank->FilterStates_e[0] ) );
     462       48330 :         scale = s_max( scale, cldfbBank->FilterStates_e[k] );
     463       48330 :         k = add( k, 1 );
     464             :     }
     465       90218 :     FOR( i = 0; i < nSamples; i += cldfbBank->no_channels )
     466             :     {
     467       84848 :         cldfbBank->FilterStates_e[k] = timeIn_e;
     468       84848 :         move16();
     469       84848 :         assert( (size_t) k < sizeof( cldfbBank->FilterStates_e ) / sizeof( cldfbBank->FilterStates_e[0] ) );
     470       84848 :         scale = s_max( scale, cldfbBank->FilterStates_e[k] );
     471       84848 :         k = add( k, 1 );
     472             :     }
     473        5370 :     i = s_max( scale, timeIn_e );
     474        5370 :     scale = sub( cldfbBank->FilterStates_eg, i );
     475        5370 :     cldfbBank->FilterStates_eg = i;
     476        5370 :     move16();
     477             : 
     478             :     /* if nTimeSlots==0, make sure we have a value. */
     479        5370 :     scaleFactor->lb_scale = add( cldfbBank->anaScalefactor, add( cldfbBank->FilterStates_eg, 5 ) );
     480        5370 :     move16();
     481             : 
     482             :     /* move and scale filter states */
     483      898458 :     FOR( i = 0; i < offset; i++ )
     484             :     {
     485      893088 :         pStates[i] = shl_sat( pStates[i + nSamplesUpd], scale ); // Q(15-(timeIn_e-FilterStates_eg))
     486      893088 :         move16();
     487             :     }
     488             : 
     489             :     /* copy and scale current time signal */
     490        5370 :     scale = sub( timeIn_e, cldfbBank->FilterStates_eg );
     491     1573434 :     FOR( i = 0; i < nSamples; i++ )
     492             :     {
     493     1568064 :         pStates[offset + i] = shl_sat( *timeIn, scale ); // Q(15-scale)
     494     1568064 :         move16();
     495     1568064 :         timeIn = timeIn + stride;
     496             :     }
     497             : 
     498       90218 :     FOR( k = 0; k < nTimeSlots; k++ )
     499             :     {
     500      476864 :         FOR( i = 0; i < M4; i++ )
     501             :         {
     502             :             /* prototype filter */
     503      392016 :             r1 = L_msu0( 0, pFilter1[0 - ( p_stride * ( i * 2 ) )], pStates1[( 0 * L2 ) - ( i * 2 )] );
     504      392016 :             r1 = L_msu0( r1, pFilter1[1 - ( p_stride * ( i * 2 ) )], pStates1[( 1 * L2 ) - ( i * 2 )] );
     505      392016 :             r1 = L_msu0( r1, pFilter1[2 - ( p_stride * ( i * 2 ) )], pStates1[( 2 * L2 ) - ( i * 2 )] );
     506      392016 :             r1 = L_msu0( r1, pFilter1[3 - ( p_stride * ( i * 2 ) )], pStates1[( 3 * L2 ) - ( i * 2 )] );
     507      392016 :             r1 = L_msu0( r1, pFilter1[4 - ( p_stride * ( i * 2 ) )], pStates1[( 4 * L2 ) - ( i * 2 )] );
     508             : 
     509      392016 :             r2 = L_msu0( 0, pFilter2[0 + ( p_stride * ( i * 2 ) )], pStates2[( 0 * L2 ) + ( i * 2 )] );
     510      392016 :             r2 = L_msu0( r2, pFilter2[1 + ( p_stride * ( i * 2 ) )], pStates2[( 1 * L2 ) + ( i * 2 )] );
     511      392016 :             r2 = L_msu0( r2, pFilter2[2 + ( p_stride * ( i * 2 ) )], pStates2[( 2 * L2 ) + ( i * 2 )] );
     512      392016 :             r2 = L_msu0( r2, pFilter2[3 + ( p_stride * ( i * 2 ) )], pStates2[( 3 * L2 ) + ( i * 2 )] );
     513      392016 :             r2 = L_msu0( r2, pFilter2[4 + ( p_stride * ( i * 2 ) )], pStates2[( 4 * L2 ) + ( i * 2 )] );
     514             : 
     515      392016 :             i1 = L_msu0( 0, pFilter3[0 + ( p_stride * ( i * 2 ) )], pStates3[( 0 * L2 ) + ( i * 2 )] );
     516      392016 :             i1 = L_msu0( i1, pFilter3[1 + ( p_stride * ( i * 2 ) )], pStates3[( 1 * L2 ) + ( i * 2 )] );
     517      392016 :             i1 = L_msu0( i1, pFilter3[2 + ( p_stride * ( i * 2 ) )], pStates3[( 2 * L2 ) + ( i * 2 )] );
     518      392016 :             i1 = L_msu0( i1, pFilter3[3 + ( p_stride * ( i * 2 ) )], pStates3[( 3 * L2 ) + ( i * 2 )] );
     519      392016 :             i1 = L_msu0( i1, pFilter3[4 + ( p_stride * ( i * 2 ) )], pStates3[( 4 * L2 ) + ( i * 2 )] );
     520             : 
     521      392016 :             i2 = L_msu0( 0, pFilter4[0 - ( p_stride * ( i * 2 ) )], pStates4[( 0 * L2 ) - ( i * 2 )] );
     522      392016 :             i2 = L_msu0( i2, pFilter4[1 - ( p_stride * ( i * 2 ) )], pStates4[( 1 * L2 ) - ( i * 2 )] );
     523      392016 :             i2 = L_msu0( i2, pFilter4[2 - ( p_stride * ( i * 2 ) )], pStates4[( 2 * L2 ) - ( i * 2 )] );
     524      392016 :             i2 = L_msu0( i2, pFilter4[3 - ( p_stride * ( i * 2 ) )], pStates4[( 3 * L2 ) - ( i * 2 )] );
     525      392016 :             i2 = L_msu0( i2, pFilter4[4 - ( p_stride * ( i * 2 ) )], pStates4[( 4 * L2 ) - ( i * 2 )] );
     526             : 
     527             :             /* folding */
     528      392016 :             rBuffer[2 * i] = L_sub( r1, r2 );
     529      392016 :             move32();
     530      392016 :             rBuffer[( ( i * 2 ) + 1 )] = L_negate( L_add( i1, i2 ) );
     531      392016 :             move32();
     532             : 
     533             :             /* folding */
     534      392016 :             iBuffer[2 * i] = L_add( r1, r2 );
     535      392016 :             move32();
     536      392016 :             iBuffer[( ( i * 2 ) + 1 )] = L_sub( i1, i2 );
     537      392016 :             move32();
     538             :         }
     539             : 
     540      476864 :         FOR( i = M4; i < m2; i++ )
     541             :         {
     542             :             /* prototype filter */
     543      392016 :             r1 = L_msu0( 0, pFilter1[0 - ( p_stride * ( i * 2 ) )], pStates1[( 0 * L2 ) - ( i * 2 )] );
     544      392016 :             r1 = L_msu0( r1, pFilter1[1 - ( p_stride * ( i * 2 ) )], pStates1[( 1 * L2 ) - ( i * 2 )] );
     545      392016 :             r1 = L_msu0( r1, pFilter1[2 - ( p_stride * ( i * 2 ) )], pStates1[( 2 * L2 ) - ( i * 2 )] );
     546      392016 :             r1 = L_msu0( r1, pFilter1[3 - ( p_stride * ( i * 2 ) )], pStates1[( 3 * L2 ) - ( i * 2 )] );
     547      392016 :             r1 = L_msu0( r1, pFilter1[4 - ( p_stride * ( i * 2 ) )], pStates1[( 4 * L2 ) - ( i * 2 )] );
     548             : 
     549      392016 :             r2 = L_msu0( 0, pFilter6[0 + ( p_stride * ( i * 2 ) )], pStates6[( 0 * L2 ) + ( i * 2 )] );
     550      392016 :             r2 = L_msu0( r2, pFilter6[1 + ( p_stride * ( i * 2 ) )], pStates6[( 1 * L2 ) + ( i * 2 )] );
     551      392016 :             r2 = L_msu0( r2, pFilter6[2 + ( p_stride * ( i * 2 ) )], pStates6[( 2 * L2 ) + ( i * 2 )] );
     552      392016 :             r2 = L_msu0( r2, pFilter6[3 + ( p_stride * ( i * 2 ) )], pStates6[( 3 * L2 ) + ( i * 2 )] );
     553      392016 :             r2 = L_msu0( r2, pFilter6[4 + ( p_stride * ( i * 2 ) )], pStates6[( 4 * L2 ) + ( i * 2 )] );
     554             : 
     555      392016 :             i1 = L_msu0( 0, pFilter5[0 - ( p_stride * ( i * 2 ) )], pStates5[( 0 * L2 ) - ( i * 2 )] );
     556      392016 :             i1 = L_msu0( i1, pFilter5[1 - ( p_stride * ( i * 2 ) )], pStates5[( 1 * L2 ) - ( i * 2 )] );
     557      392016 :             i1 = L_msu0( i1, pFilter5[2 - ( p_stride * ( i * 2 ) )], pStates5[( 2 * L2 ) - ( i * 2 )] );
     558      392016 :             i1 = L_msu0( i1, pFilter5[3 - ( p_stride * ( i * 2 ) )], pStates5[( 3 * L2 ) - ( i * 2 )] );
     559      392016 :             i1 = L_msu0( i1, pFilter5[4 - ( p_stride * ( i * 2 ) )], pStates5[( 4 * L2 ) - ( i * 2 )] );
     560             : 
     561      392016 :             i2 = L_msu0( 0, pFilter3[0 + ( p_stride * ( i * 2 ) )], pStates3[( 0 * L2 ) + ( i * 2 )] );
     562      392016 :             i2 = L_msu0( i2, pFilter3[1 + ( p_stride * ( i * 2 ) )], pStates3[( 1 * L2 ) + ( i * 2 )] );
     563      392016 :             i2 = L_msu0( i2, pFilter3[2 + ( p_stride * ( i * 2 ) )], pStates3[( 2 * L2 ) + ( i * 2 )] );
     564      392016 :             i2 = L_msu0( i2, pFilter3[3 + ( p_stride * ( i * 2 ) )], pStates3[( 3 * L2 ) + ( i * 2 )] );
     565      392016 :             i2 = L_msu0( i2, pFilter3[4 + ( p_stride * ( i * 2 ) )], pStates3[( 4 * L2 ) + ( i * 2 )] );
     566             : 
     567             :             /* folding */
     568      392016 :             rBuffer[2 * i] = L_add( r1, r2 );
     569      392016 :             move32();
     570      392016 :             rBuffer[( ( i * 2 ) + 1 )] = L_sub( i1, i2 );
     571      392016 :             move32();
     572             : 
     573             :             /* folding */
     574      392016 :             iBuffer[2 * i] = L_sub( r1, r2 );
     575      392016 :             move32();
     576      392016 :             iBuffer[( ( i * 2 ) + 1 )] = L_add( i1, i2 );
     577      392016 :             move32();
     578             :         }
     579             : 
     580             :         /* pre modulation of DST IV and DCT IV */
     581       84848 :         calcModulation( &rBuffer[0], &rBuffer[1], &rBuffer[0], &rBuffer[1], 2, 2, 2, 2,
     582             :                         &iBuffer[0], &iBuffer[1], &iBuffer[0], &iBuffer[1], 2, 2, 2, 2,
     583             :                         rRotVctr, iRotVctr, m );
     584             : 
     585             :         /* FFT of DST IV */
     586       84848 :         scale = 0;
     587       84848 :         move16();
     588       84848 :         BASOP_cfft( (cmplx *) rBuffer, m2, &scale, workBuffer );
     589             : 
     590             :         /* store analysis scalefactor for cldfb */
     591       84848 :         scaleFactor->lb_scale = add( cldfbBank->anaScalefactor, add( cldfbBank->FilterStates_eg, scale ) );
     592       84848 :         move16();
     593             : 
     594             :         /* FFT of DCT IV */
     595       84848 :         BASOP_cfft( (cmplx *) iBuffer, m2, &scale, workBuffer );
     596             : 
     597             :         /* post modulation of DST IV and DCT IV */
     598       84848 :         calcModulation( &rAnalysis[k][m - 1], &rAnalysis[k][0], &rBuffer[0], &rBuffer[1], -2, 2, 2, 2,
     599       84848 :                         &iAnalysis[k][0], &iAnalysis[k][m - 1], &iBuffer[0], &iBuffer[1], 2, -2, 2, 2,
     600             :                         rRotVctr, iRotVctr, m );
     601             : 
     602             : 
     603             :         /* update states pointer */
     604       84848 :         pStates1 = &pStates1[cldfbBank->no_channels];
     605       84848 :         pStates2 = &pStates2[cldfbBank->no_channels];
     606       84848 :         pStates3 = &pStates3[cldfbBank->no_channels];
     607       84848 :         pStates5 = &pStates5[cldfbBank->no_channels];
     608       84848 :         pStates4 = &pStates4[cldfbBank->no_channels];
     609       84848 :         pStates6 = &pStates6[cldfbBank->no_channels];
     610             :     }
     611        5370 : }
     612             : 
     613             : 
     614             : /* cldfbSynthesis_fx
     615             : 
     616             :    Parameters:
     617             :      cldfbBank          I/O: handle to analysis CLDFB filter struct
     618             :      **rAnalysis      I:   matrix holding the real part of the subband samples
     619             :      **iAnalysis      I:   matrix holding the imaginary part of the subband samples
     620             :      *scaleFactor     I:   pointer to cldfb scalefactor struct
     621             :      ov_len           I:   determines overlapping area in time slots (obsolete)
     622             :      *timeOut         O:   pointer to time domain data
     623             :      stride           I:   stride for time domain data
     624             :      *pWorkBuffer     I:   pointer to scratch buffer, needed for buffer of size 2*cldfbbands*Word32 + 2*cldfbbands*Word16
     625             : 
     626             :    Function:
     627             :       Performs inverse complex-valued subband filtering of the subband samples in rAnalysis and iAnalysis
     628             :       and stores the time domain data in timeOut
     629             : 
     630             :    Returns:
     631             :       void
     632             : */
     633        2685 : void cldfbSynthesis_fx(
     634             :     HANDLE_CLDFB_FILTER_BANK cldfbBank,
     635             :     Word32 **rAnalysis,
     636             :     Word32 **iAnalysis,
     637             :     const CLDFB_SCALE_FACTOR *scaleFactor,
     638             :     Word16 *timeOut, // Q(15-timeOut_e)
     639             :     const Word16 timeOut_e,
     640             :     const Word16 nTimeSlots,
     641             :     Word32 *pWorkBuffer // Qx
     642             : )
     643             : {
     644             :     Word16 i;
     645             :     Word16 k;
     646             :     Word16 L2;
     647             :     Word16 m;
     648             :     Word16 m2;
     649             :     Word16 Lz;
     650             :     Word16 Mz;
     651             :     Word32 acc;
     652             :     Word16 offset1;
     653             :     Word16 offset2;
     654             :     Word16 channels0;
     655             :     Word16 channels1;
     656             :     Word16 channels2;
     657             :     Word16 channels3;
     658             :     Word16 channels4;
     659             :     Word16 statesSizeM1;
     660             :     Word16 statesSizeM2;
     661             :     Word16 stride;
     662             : 
     663             :     Word16 scale, scaleMod;
     664             :     Word16 outScale;
     665             :     Word16 scaleLB;
     666             :     Word16 scaleHB;
     667             : 
     668             :     Word32 *rAnalysisS;
     669             :     Word32 *iAnalysisS;
     670             : 
     671             :     Word32 *rBuffer;
     672             :     Word32 *iBuffer;
     673             :     Word16 *nBuffer;
     674             : 
     675             :     Word16 *pStates;
     676             :     Word16 *pStatesI;
     677             :     Word16 *pStatesR;
     678             : 
     679             :     const Word16 *pFilterS;
     680             :     const Word16 *pFilterM;
     681             : 
     682             :     const Word16 *rRotVctr;
     683             :     const Word16 *iRotVctr;
     684             :     Word32 workBuffer[2 * BASOP_CFFT_MAX_LENGTH];
     685             : 
     686        2685 :     m = cldfbBank->no_channels;
     687        2685 :     move16();
     688        2685 :     L2 = shl( m, 1 );
     689        2685 :     m2 = shr( m, 1 );
     690        2685 :     Lz = s_min( cldfbBank->lsb, sub( m, cldfbBank->bandsToZero ) );
     691        2685 :     Mz = s_min( cldfbBank->usb, sub( m, cldfbBank->bandsToZero ) );
     692        2685 :     stride = 1; /* constant */
     693        2685 :     move16();
     694        2685 :     channels0 = sub( m, cldfbBank->zeros );
     695        2685 :     channels1 = sub( m, 1 );
     696        2685 :     channels2 = shl( m, 1 );
     697        2685 :     channels3 = add( m, channels2 );
     698        2685 :     channels4 = shl( channels2, 1 );
     699             : 
     700        2685 :     statesSizeM1 = sub( shl( cldfbBank->p_filter_length, 1 ), m );
     701        2685 :     statesSizeM2 = sub( statesSizeM1, m );
     702             : 
     703        2685 :     offset1 = sub( channels1, cldfbBank->zeros );
     704        2685 :     offset2 = add( offset1, cldfbBank->no_channels );
     705             : 
     706        2685 :     rBuffer = &pWorkBuffer[0];
     707        2685 :     iBuffer = &pWorkBuffer[m];
     708        2685 :     nBuffer = (Word16 *) ( &pWorkBuffer[L2] );
     709             : 
     710        2685 :     rAnalysisS = &pWorkBuffer[3 * m];
     711        2685 :     iAnalysisS = &pWorkBuffer[4 * m];
     712             : 
     713        2685 :     rRotVctr = cldfbBank->rRotVctr;
     714        2685 :     iRotVctr = cldfbBank->iRotVctr;
     715             : 
     716        2685 :     scale = scaleFactor->lb_scale;
     717        2685 :     move16();
     718        2685 :     if ( NE_16( Lz, Mz ) )
     719             :     {
     720        1258 :         scale = s_max( scale, scaleFactor->hb_scale );
     721             :     }
     722        2685 :     scaleLB = limitScale32( sub( scale, scaleFactor->lb_scale ) );
     723        2685 :     scaleHB = limitScale32( sub( scale, scaleFactor->hb_scale ) );
     724             : 
     725        2685 :     outScale = cldfbBank->synFilterHeadroom;
     726        2685 :     move16();
     727             : 
     728        2685 :     scaleMod = sub( add( scale, cldfbBank->outScalefactor ), outScale );
     729             : 
     730             :     /* Increase CLDFB synthesis states for low level signals */
     731        2685 :     IF( LT_16( scale, 8 ) )
     732             :     {
     733         116 :         scaleMod = add( scaleMod, 2 );
     734         116 :         outScale = sub( outScale, 2 );
     735             :     }
     736        2685 :     scaleMod = sub( scaleMod, timeOut_e );
     737        2685 :     scale = add( outScale, timeOut_e );
     738        2685 :     IF( NE_16( scale, cldfbBank->FilterStates_eg ) )
     739             :     {
     740         503 :         Scale_sig( cldfbBank->FilterStates, statesSizeM2, sub( cldfbBank->FilterStates_eg, scale ) ); // Q(15-scale)
     741         503 :         cldfbBank->FilterStates_eg = scale;
     742         503 :         move16();
     743             :     }
     744             : 
     745       45395 :     FOR( k = 0; k < nTimeSlots; k++ )
     746             :     {
     747             :         {
     748      437238 :             FOR( i = 0; i < Lz; i += 2 )
     749             :             {
     750      394528 :                 rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleLB );
     751      394528 :                 move32();
     752      394528 :                 iAnalysisS[i] = L_negate( L_shr( iAnalysis[k][i], scaleLB ) );
     753      394528 :                 move32();
     754             :             }
     755             : 
     756       42710 :             IF( LT_16( i, Mz ) )
     757             :             {
     758      385808 :                 FOR( ; i < Mz; i += 2 )
     759             :                 {
     760      365760 :                     rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleHB );
     761      365760 :                     move32();
     762      365760 :                     iAnalysisS[i] = L_negate( L_shr( iAnalysis[k][i], scaleHB ) );
     763      365760 :                     move32();
     764             :                 }
     765             :             }
     766             : 
     767       42710 :             IF( LT_16( i, m ) )
     768             :             {
     769      380814 :                 FOR( ; i < m; i += 2 )
     770             :                 {
     771      358152 :                     rAnalysisS[i] = 0;
     772      358152 :                     move32();
     773      358152 :                     iAnalysisS[i] = 0;
     774      358152 :                     move32();
     775             :                 }
     776             :             }
     777             : 
     778      437238 :             FOR( i = 1; i < Lz; i += 2 )
     779             :             {
     780      394528 :                 rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleLB );
     781      394528 :                 move32();
     782      394528 :                 iAnalysisS[i] = L_shr( iAnalysis[k][i], scaleLB );
     783      394528 :                 move32();
     784             :             }
     785             : 
     786       42710 :             IF( LT_16( i, Mz ) )
     787             :             {
     788      385808 :                 FOR( ; i < Mz; i += 2 )
     789             :                 {
     790      365760 :                     rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleHB );
     791      365760 :                     move32();
     792      365760 :                     iAnalysisS[i] = L_shr( iAnalysis[k][i], scaleHB );
     793      365760 :                     move32();
     794             :                 }
     795             :             }
     796             : 
     797       42710 :             IF( LT_16( i, m ) )
     798             :             {
     799      380814 :                 FOR( ; i < m; i += 2 )
     800             :                 {
     801      358152 :                     rAnalysisS[i] = 0;
     802      358152 :                     move32();
     803      358152 :                     iAnalysisS[i] = 0;
     804      358152 :                     move32();
     805             :                 }
     806             :             }
     807             :         }
     808             : 
     809             :         /* pre modulation */
     810       42710 :         calcModulation( &rBuffer[0], &rBuffer[1], &rAnalysisS[0], &rAnalysisS[m - 1], 2, 2, 2, -2,
     811       42710 :                         &iBuffer[0], &iBuffer[1], &iAnalysisS[0], &iAnalysisS[m - 1], 2, 2, 2, -2,
     812             :                         rRotVctr, iRotVctr, m );
     813             : 
     814             : 
     815             :         /* FFT of DST IV */
     816       42710 :         scale = 0;
     817       42710 :         move16();
     818       42710 :         BASOP_cfft( (cmplx *) rBuffer, m2, &scale, workBuffer );
     819             : 
     820             :         /* FFT of DCT IV */
     821       42710 :         scale = scaleMod;
     822       42710 :         move16();
     823       42710 :         BASOP_cfft( (cmplx *) iBuffer, m2, &scale, workBuffer );
     824             : 
     825             :         /* post modulation and folding */
     826       42710 :         calcModulationAndFolding( nBuffer, rBuffer, iBuffer, rRotVctr, iRotVctr, cldfbBank->synGain, scale, m, m2 );
     827             : 
     828             :         /* prototype filter */
     829       42710 :         pStates = &cldfbBank->FilterStates[( k * L2 )];
     830       42710 :         pFilterS = &cldfbBank->p_filter[0];
     831       42710 :         pFilterM = &cldfbBank->p_filter[shr( cldfbBank->p_filter_length, 1 )];
     832             : 
     833     2279590 :         FOR( i = 0; i < channels0; i++ )
     834             :         {
     835     2236880 :             pStatesI = &pStates[i];
     836     2236880 :             pStatesR = &pStates[add( i, channels3 )];
     837             : 
     838     2236880 :             acc = L_mult( *pStatesI, *pFilterS++ );
     839     2236880 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     840     2236880 :             pStatesR += channels4;
     841     2236880 :             pStatesI += channels4;
     842             : 
     843     2236880 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     844     2236880 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     845     2236880 :             pStatesR += channels4;
     846     2236880 :             pStatesI += channels4;
     847             : 
     848     2236880 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     849     2236880 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     850     2236880 :             pStatesR += channels4;
     851     2236880 :             pStatesI += channels4;
     852             : 
     853     2236880 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     854     2236880 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     855     2236880 :             pStatesI += channels4;
     856             : 
     857     2236880 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     858     2236880 :             acc = L_mac( acc, nBuffer[sub( channels1, i )], *pFilterM++ );
     859             : 
     860             :             BASOP_SATURATE_WARNING_OFF_EVS
     861     2236880 :             timeOut[( offset1 - i ) * stride] = round_fx_sat( L_shl_sat( acc, outScale ) );
     862             :             BASOP_SATURATE_WARNING_ON_EVS
     863     2236880 :             move16();
     864             :         }
     865             : 
     866       42710 :         FOR( ; i < cldfbBank->no_channels; i++ )
     867             :         {
     868           0 :             pStatesI = &pStates[i + channels2];
     869           0 :             pStatesR = &pStates[( i + channels2 ) + channels3];
     870             : 
     871           0 :             acc = L_mult( *pStatesI, *pFilterS++ );
     872           0 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     873           0 :             pStatesR += channels4;
     874           0 :             pStatesI += channels4;
     875             : 
     876           0 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     877           0 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     878           0 :             pStatesR += channels4;
     879           0 :             pStatesI += channels4;
     880             : 
     881           0 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     882           0 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     883           0 :             pStatesR += channels4;
     884           0 :             pStatesI += channels4;
     885             : 
     886           0 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     887           0 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     888             : 
     889           0 :             acc = L_mac( acc, nBuffer[channels1 + m - i], *pFilterS++ );
     890           0 :             pFilterM++;
     891             : 
     892             :             BASOP_SATURATE_WARNING_OFF_EVS
     893           0 :             timeOut[( offset2 - i ) * stride] = round_fx_sat( L_shl_sat( acc, outScale ) );
     894             :             BASOP_SATURATE_WARNING_ON_EVS
     895           0 :             move16();
     896             :         }
     897             : 
     898     2279590 :         FOR( i = 0; i < cldfbBank->no_channels; i++ )
     899             :         {
     900     2236880 :             pStates[statesSizeM1 + i] = nBuffer[channels1 - i];
     901     2236880 :             move16();
     902     2236880 :             pStates[statesSizeM2 + i] = nBuffer[( channels1 + m ) - i];
     903     2236880 :             move16();
     904             :         }
     905             : 
     906       42710 :         timeOut = &timeOut[m * stride];
     907             :     }
     908             : 
     909             :     /* move filter states */
     910        2685 :     Copy( &cldfbBank->FilterStates[nTimeSlots * L2], cldfbBank->FilterStates, statesSizeM2 );
     911        2685 :     set16_fx( &cldfbBank->FilterStates[statesSizeM2], 0, L2 );
     912        2685 : }
     913             : 
     914             : 
     915             : /*-------------------------------------------------------------------*
     916             :  * configureClfdb()
     917             :  *
     918             :  * configures a CLDFB handle
     919             :  *--------------------------------------------------------------------*/
     920             : 
     921          19 : void configureCldfb( HANDLE_CLDFB_FILTER_BANK h_cldfb, /*!< Returns handle */
     922             :                      const Word16 no_channels,         /*!< Number of channels (bands) */
     923             :                      const Word16 frameSize            /*!< FrameSize */
     924             : )
     925             : {
     926             : 
     927          19 :     h_cldfb->no_channels = no_channels;
     928          19 :     move16();
     929          19 :     assert( h_cldfb->no_channels >= 10 );
     930          19 :     h_cldfb->no_col = div_l( frameSize, shr( h_cldfb->no_channels, 1 ) );
     931          19 :     move16();
     932             : 
     933             :     /* was cldfbInitFilterBank()*/
     934          19 :     h_cldfb->anaScalefactor = 0;
     935          19 :     move16();
     936          19 :     h_cldfb->synScalefactor = 0;
     937          19 :     move16();
     938          19 :     h_cldfb->bandsToZero = 0;
     939          19 :     move16();
     940          19 :     h_cldfb->filtermode = 0;
     941          19 :     move16();
     942          19 :     h_cldfb->memory = 0;
     943          19 :     move16();
     944          19 :     h_cldfb->memory_length = 0;
     945          19 :     move16();
     946             : 
     947          19 :     h_cldfb->p_filter_length = i_mult( 10, h_cldfb->no_channels );
     948          19 :     move16();
     949             : 
     950          19 :     h_cldfb->flags = s_or( h_cldfb->flags, CLDFB_FLAG_2_5MS_SETUP );
     951          19 :     move16();
     952          19 :     h_cldfb->filterScale = CLDFB_CLDFB80_PFT_SCALE;
     953          19 :     move16();
     954             : 
     955          19 :     h_cldfb->zeros = 0;
     956          19 :     move16();
     957          19 :     h_cldfb->synFilterHeadroom = SYN_FILTER_HEADROOM_2_5MS;
     958          19 :     move16();
     959             : 
     960          19 :     cldfb_init_proto_and_twiddles( h_cldfb );
     961             : 
     962          19 :     h_cldfb->lsb = no_channels;
     963          19 :     move16();
     964          19 :     h_cldfb->usb = s_min( no_channels, h_cldfb->no_channels ); /* Does this make any sense? in the previous implemenatation lsb, usb and no_channels are all maxCldfbBands */
     965          19 :     move16();
     966             : 
     967          19 :     h_cldfb->FilterStates = (void *) h_cldfb->FilterStates;
     968          19 :     h_cldfb->outScalefactor = h_cldfb->synScalefactor;
     969          19 :     move16();
     970             : 
     971          19 :     return;
     972             : }
     973             : 
     974             : /*-------------------------------------------------------------------*
     975             :  * openClfdb()
     976             :  *
     977             :  * open and configures a CLDFB handle
     978             :  *--------------------------------------------------------------------*/
     979           9 : ivas_error openCldfb(
     980             :     HANDLE_CLDFB_FILTER_BANK *h_cldfb, /*!< Returns handle */
     981             :     const Word16 type,                 /*!< analysis or synthesis */
     982             :     const Word16 maxCldfbBands,        /*!< number of cldfb bands */
     983             :     const Word16 frameSize             /*!< FrameSize */
     984             : )
     985             : {
     986             :     HANDLE_CLDFB_FILTER_BANK hs;
     987             : 
     988           9 :     hs = (HANDLE_CLDFB_FILTER_BANK) malloc( sizeof( CLDFB_FILTER_BANK ) );
     989           9 :     IF( hs == NULL )
     990             :     {
     991           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" );
     992             :     }
     993             : 
     994           9 :     hs->type = type;
     995           9 :     move16();
     996             : 
     997           9 :     IF( type == CLDFB_ANALYSIS )
     998             :     {
     999           6 :         hs->FilterStates = (Word16 *) malloc( STATE_BUFFER_SIZE * maxCldfbBands * sizeof( Word16 ) );
    1000             :     }
    1001             :     ELSE
    1002             :     {
    1003           3 :         hs->FilterStates = (Word16 *) malloc( 2 * STATE_BUFFER_SIZE * maxCldfbBands * sizeof( Word16 ) );
    1004             :     }
    1005           9 :     if ( hs->FilterStates == NULL )
    1006             :     {
    1007           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" );
    1008             :     }
    1009           9 :     hs->flags = s_and( hs->flags, ~CLDFB_FLAG_KEEP_STATES );
    1010           9 :     move16();
    1011           9 :     configureCldfb( hs, maxCldfbBands, frameSize );
    1012             : 
    1013           9 :     hs->memory = NULL;
    1014           9 :     hs->memory_length = 0;
    1015           9 :     move16();
    1016             : 
    1017           9 :     IF( hs->type == CLDFB_ANALYSIS )
    1018             :     {
    1019           6 :         test();
    1020           6 :         IF( ( s_and( hs->flags, CLDFB_FLAG_KEEP_STATES ) == 0 ) && ( hs->FilterStates != 0 ) )
    1021             :         {
    1022           6 :             set16_fx( hs->FilterStates, 0, i_mult( STATE_BUFFER_SIZE, hs->no_channels ) );
    1023           6 :             set16_fx( hs->FilterStates_e, 0, sizeof( hs->FilterStates_e ) / sizeof( hs->FilterStates_e[0] ) );
    1024             : 
    1025           6 :             hs->FilterStates_eg = 0;
    1026           6 :             move16();
    1027             :         }
    1028             :     }
    1029           3 :     ELSE IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1030             :     {
    1031           3 :         IF( hs->FilterStates != 0 )
    1032             :         {
    1033           3 :             IF( s_and( hs->flags, CLDFB_FLAG_KEEP_STATES ) == 0 )
    1034             :             {
    1035           3 :                 set16_fx( hs->FilterStates, 0, i_mult( shl( STATE_BUFFER_SIZE, 1 ), hs->no_channels ) );
    1036             :             }
    1037             :         }
    1038           3 :         hs->FilterStates_eg = 0;
    1039           3 :         move16();
    1040             :     }
    1041             : 
    1042           9 :     if ( h_cldfb != NULL )
    1043             :     {
    1044           9 :         *h_cldfb = hs;
    1045             :     }
    1046             : 
    1047           9 :     return IVAS_ERR_OK;
    1048             : }
    1049             : 
    1050             : 
    1051             : /*-------------------------------------------------------------------*
    1052             :  * resampleCldfb()
    1053             :  *
    1054             :  * Change sample rate of filter bank
    1055             :  *--------------------------------------------------------------------*/
    1056          10 : void resampleCldfb( HANDLE_CLDFB_FILTER_BANK hs,
    1057             :                     const Word16 newCldfbBands,
    1058             :                     const Word16 frameSize,
    1059             :                     const Word8 firstFrame )
    1060             : 
    1061             : {
    1062             :     Word16 timeOffset;
    1063             :     Word16 timeOffsetOld;
    1064             :     Word16 noChannelsOld;
    1065             : 
    1066          10 :     noChannelsOld = hs->no_channels;
    1067          10 :     move16();
    1068          10 :     timeOffsetOld = sub( sub( hs->p_filter_length, hs->no_channels ), hs->zeros );
    1069             : 
    1070             :     /* change all CLDFB bank parameters that depend on the no of channels */
    1071          10 :     hs->flags = s_or( hs->flags, CLDFB_FLAG_KEEP_STATES );
    1072          10 :     move16();
    1073             : 
    1074             :     /* new settings */
    1075          10 :     configureCldfb( hs, newCldfbBands, frameSize );
    1076             : 
    1077             :     /* resample cldfb state buffer */
    1078          10 :     timeOffset = sub( sub( hs->p_filter_length, hs->no_channels ), hs->zeros );
    1079             : 
    1080          10 :     IF( firstFrame == 0 )
    1081             :     {
    1082             :         /*low complexity-resampling only stored previous samples that are needed for next frame modulation */
    1083           4 :         lerp( hs->FilterStates + i_mult( noChannelsOld, hs->no_col ), hs->FilterStates + i_mult( noChannelsOld, hs->no_col ), timeOffset, timeOffsetOld );
    1084           4 :         Copy( hs->FilterStates + i_mult( noChannelsOld, hs->no_col ), hs->FilterStates + frameSize, timeOffset );
    1085             :     }
    1086             : 
    1087          10 :     return;
    1088             : }
    1089             : 
    1090             : /*
    1091             :    AnalysisPostSpectrumScaling_Fx
    1092             : 
    1093             :     Parameters:
    1094             :     cldfbBank          I: CLDFB handle
    1095             :        **rSubband32    I: matrix holding real part of the CLDFB subsamples
    1096             :     **iSubband32    I: matrix holding imaginary part of the CLDFB subsamples
    1097             :        **rSubband16    O: matrix holding real part of the CLDFB subsamples
    1098             :     **iSubband16    O: matrix holding imaginary part of the CLDFB subsamples
    1099             :      *cldfbScale        O: cldfb lowband scalefactor
    1100             : 
    1101             :     Function:
    1102             :        performs dynamic spectrum scaling for all subband
    1103             : 
    1104             :     Returns:
    1105             :        headroom
    1106             : */
    1107             : Word16
    1108           0 : AnalysisPostSpectrumScaling_Fx( HANDLE_CLDFB_FILTER_BANK cldfbBank, /*!< Handle of cldfbBank  */
    1109             :                                 Word32 **rSubband32,                /*!< Real bands Q(cldfbSacle)*/
    1110             :                                 Word32 **iSubband32,                /*!< Imaginary bands Q(cldfbSacle)*/
    1111             :                                 Word16 **rSubband16,                /*!< Real bands Q(cldfbSacle)*/
    1112             :                                 Word16 **iSubband16,                /*!< Imaginary bands Q(cldfbScale)*/
    1113             :                                 Word16 *cldfbScale                  /*!< CLDFB lowband scalefactor */
    1114             : )
    1115             : {
    1116             :     Word16 i;
    1117             :     Word16 j;
    1118             :     Word16 headRoom;
    1119             : 
    1120             : 
    1121           0 :     headRoom = BASOP_util_norm_l_dim2_cplx(
    1122             :         (const Word32 *const *) rSubband32,
    1123             :         (const Word32 *const *) iSubband32,
    1124             :         0,
    1125           0 :         cldfbBank->no_channels,
    1126             :         0,
    1127           0 :         cldfbBank->no_col );
    1128             : 
    1129           0 :     FOR( i = 0; i < cldfbBank->no_col; i++ )
    1130             :     {
    1131           0 :         FOR( j = 0; j < cldfbBank->no_channels; j++ )
    1132             :         {
    1133           0 :             rSubband16[i][j] = round_fx_sat( L_shl_sat( rSubband32[i][j], headRoom ) ); // Q(cldfbSacle_headRoom)
    1134           0 :             iSubband16[i][j] = round_fx_sat( L_shl_sat( iSubband32[i][j], headRoom ) ); // Q(cldfbSacle+headRoom)
    1135           0 :             move16();
    1136           0 :             move16();
    1137             :         }
    1138             :     }
    1139             : 
    1140           0 :     *cldfbScale = add( *cldfbScale, headRoom );
    1141           0 :     move16();
    1142             : 
    1143             : 
    1144           0 :     return headRoom;
    1145             : }
    1146             : 
    1147             : 
    1148             : /*-------------------------------------------------------------------*
    1149             :  * analysisCLDFBEncoder()
    1150             :  *
    1151             :  * Encoder CLDFB analysis + energy stage
    1152             :  *--------------------------------------------------------------------*/
    1153             : 
    1154           0 : void analysisCldfbEncoder_fx(
    1155             :     Encoder_State *st_fx, /* i/o: encoder state structure                    */
    1156             :     const Word16 *timeIn, // Q15
    1157             :     Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
    1158             :     Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
    1159             :     Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], // Q(enerScale.lb_scale16)
    1160             :     Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], // Q(enerScale.lb_scale16)
    1161             :     Word32 enerBuffSum[CLDFB_NO_CHANNELS_MAX],                    // Q(31-enerBuffSum_exp)
    1162             :     Word16 *enerBuffSum_exp,
    1163             :     CLDFB_SCALE_FACTOR *scale )
    1164             : {
    1165             :     Word16 i;
    1166             :     CLDFB_SCALE_FACTOR enerScale;
    1167             :     Word32 *ppBuf_Real[CLDFB_NO_COL_MAX];
    1168             :     Word32 *ppBuf_Imag[CLDFB_NO_COL_MAX];
    1169             :     Word16 *ppBuf_Real16[CLDFB_NO_COL_MAX];
    1170             :     Word16 *ppBuf_Imag16[CLDFB_NO_COL_MAX];
    1171             :     Word32 workBuffer[256];
    1172           0 :     Word16 num_slots = 1;
    1173           0 :     move16();
    1174             : 
    1175           0 :     FOR( i = 0; i < CLDFB_NO_COL_MAX; i++ )
    1176             :     {
    1177           0 :         ppBuf_Real[i] = &realBuffer[i][0];
    1178           0 :         ppBuf_Imag[i] = &imagBuffer[i][0];
    1179           0 :         ppBuf_Real16[i] = &realBuffer16[i][0];
    1180           0 :         ppBuf_Imag16[i] = &imagBuffer16[i][0];
    1181             :     }
    1182             : 
    1183             :     /* perform analysis */
    1184           0 :     cldfbAnalysis_fx( st_fx->cldfbAnaEnc, ppBuf_Real, ppBuf_Imag, scale, timeIn, 0, CLDFB_NO_COL_MAX, workBuffer );
    1185             : 
    1186           0 :     enerScale.lb_scale = negate( scale->lb_scale );
    1187           0 :     enerScale.lb_scale16 = negate( scale->lb_scale );
    1188           0 :     move16();
    1189           0 :     move16();
    1190             : 
    1191             :     /* get 16bit respresentation */
    1192           0 :     AnalysisPostSpectrumScaling_Fx(
    1193             :         st_fx->cldfbAnaEnc,
    1194             :         ppBuf_Real,
    1195             :         ppBuf_Imag,
    1196             :         ppBuf_Real16,
    1197             :         ppBuf_Imag16,
    1198             :         &enerScale.lb_scale16 );
    1199             : 
    1200             :     /* get the energy */
    1201           0 :     GetEnergyCldfb( &st_fx->energyCoreLookahead_Fx,
    1202             :                     &st_fx->sf_energyCoreLookahead_Fx,
    1203             :                     num_slots,
    1204             :                     ppBuf_Real16,
    1205             :                     ppBuf_Imag16,
    1206           0 :                     enerScale.lb_scale16,
    1207           0 :                     st_fx->cldfbAnaEnc->no_channels,
    1208           0 :                     st_fx->cldfbAnaEnc->no_col,
    1209             :                     &st_fx->currEnergyHF_fx,
    1210             :                     &st_fx->currEnergyHF_e_fx,
    1211             :                     enerBuffSum,
    1212             :                     enerBuffSum_exp,
    1213             :                     st_fx->hTECEnc );
    1214             : 
    1215           0 :     return;
    1216             : }
    1217             : 
    1218           0 : void GetEnergyCldfb( Word32 *energyLookahead,     /*!< o: Q(*sf_energyLookahead) |   pointer to the result in the core look-ahead slot */
    1219             :                      Word16 *sf_energyLookahead,  /*!< o:         pointer to the scalefactor of the result in the core look-ahead slot  */
    1220             :                      const Word16 numLookahead,   /*!< i: Q0      the number of look-ahead time-slots */
    1221             :                      Word16 **realValues,         /*!< i: Q(sf_Values) |   the real part of the CLDFB subsamples */
    1222             :                      Word16 **imagValues,         /*!< i: Q(sf_Values) |   the imaginary part of the CLDFB subsamples */
    1223             :                      Word16 sf_Values,            /*!< i:         scalefactor of the CLDFB subcamples - apply as a negated Exponent */
    1224             :                      Word16 numberBands,          /*!< i: Q0  |   number of CLDFB bands */
    1225             :                      Word16 numberCols,           /*!< i: Q0  |   number of CLDFB subsamples */
    1226             :                      Word32 *energyHF,            /*!< o: Q31 |   pointer to HF energy */
    1227             :                      Word16 *energyHF_Exp,        /*!< o:         pointer to exponent of HF energy */
    1228             :                      Word32 *energyValuesSum,     /*!< o: Q(2*sf_Values-4) |   pointer to sum array of energy values, not initialized*/
    1229             :                      Word16 *energyValuesSum_Exp, /*!< o:         pointer to exponents of energyValuesSum, not initialized */
    1230             :                      TEC_ENC_HANDLE hTecEnc )
    1231             : {
    1232             :     Word16 j;
    1233             :     Word16 k;
    1234             :     Word16 s;
    1235             :     Word16 sm;
    1236             :     Word32 nrg;
    1237             :     Word16 numberColsL;
    1238             :     Word16 numberBandsM;
    1239             :     Word16 numberBandsM20;
    1240             :     Word32 energyValues[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    1241             :     Word16 energyValuesSumE[CLDFB_NO_CHANNELS_MAX];
    1242             :     // Word16 freqTable[2] = {20, 40};
    1243             : #ifndef ISSUE_1836_replace_overflow_libcom
    1244             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
    1245             :     Flag Overflow = 0;
    1246             :     move32();
    1247             : #endif
    1248             : #endif
    1249             : 
    1250           0 :     FOR( k = 0; k < numberCols; k++ )
    1251             :     {
    1252           0 :         FOR( j = 0; j < numberBands; j++ )
    1253             :         {
    1254           0 :             nrg = L_mult0( realValues[k][j], realValues[k][j] );     // Q(2*sf_Values)
    1255           0 :             nrg = L_mac0( nrg, imagValues[k][j], imagValues[k][j] ); // Q(2*sf_Values)
    1256             : 
    1257           0 :             energyValues[k][j] = nrg;
    1258           0 :             move32();
    1259             :         }
    1260             :     }
    1261             : 
    1262           0 :     IF( GE_16( numberBands, freqTable[1] ) && hTecEnc != NULL )
    1263             :     {
    1264             :         Word32 *tempEnergyValuesArry[CLDFB_NO_COL_MAX];
    1265             :         Word16 ScaleX2;
    1266           0 :         assert( numberCols == CLDFB_NO_COL_MAX );
    1267           0 :         FOR( j = 0; j < numberCols; j++ )
    1268             :         {
    1269           0 :             tempEnergyValuesArry[j] = &energyValues[j][0];
    1270             :         }
    1271             : 
    1272           0 :         ScaleX2 = shl( sf_Values, 1 );
    1273           0 :         calcHiEnvLoBuff_Fix(
    1274             :             numberCols,
    1275             :             freqTable,
    1276             :             1,
    1277             :             tempEnergyValuesArry,
    1278           0 :             hTecEnc->loBuffer,
    1279           0 :             hTecEnc->hiTempEnv,
    1280             :             ScaleX2 );
    1281             :     }
    1282             : 
    1283           0 :     FOR( j = 0; j < numberBands; j++ )
    1284             :     {
    1285           0 :         energyValuesSum[j] = 0;
    1286           0 :         move32();
    1287           0 :         energyValuesSumE[j] = 31;
    1288           0 :         move16();
    1289           0 :         FOR( k = 0; k < CLDFB_NO_COL_MAX; k++ )
    1290             :         {
    1291           0 :             nrg = L_shr_r( energyValues[k][j], sub( energyValuesSumE[j], 31 ) ); // Q(2*sf_Values - (energyValuesSumE[j]-31))
    1292           0 :             IF( LT_32( L_sub( maxWord32, nrg ), energyValuesSum[j] ) )
    1293             :             {
    1294           0 :                 energyValuesSumE[j] = add( energyValuesSumE[j], 1 );
    1295           0 :                 move16();
    1296           0 :                 energyValuesSum[j] = L_shr_r( energyValuesSum[j], 1 );
    1297           0 :                 move32();
    1298           0 :                 nrg = L_shr_r( energyValues[k][j], 1 );
    1299             :             }
    1300           0 :             energyValuesSum[j] = L_add( energyValuesSum[j], nrg );
    1301           0 :             move32();
    1302             :         }
    1303           0 :         test();
    1304           0 :         if ( j == 0 || GT_16( energyValuesSumE[j], *energyValuesSum_Exp ) )
    1305             :         {
    1306           0 :             *energyValuesSum_Exp = energyValuesSumE[j];
    1307           0 :             move16();
    1308             :         }
    1309             :     }
    1310           0 :     FOR( j = 0; j < numberBands; j++ )
    1311             :     {
    1312           0 :         energyValuesSum[j] = L_shr_r( energyValuesSum[j], sub( *energyValuesSum_Exp, energyValuesSumE[j] ) ); // Q(energyValuesSum_Exp - (2*sf_Values))
    1313           0 :         move32();
    1314             :     }
    1315           0 :     *energyValuesSum_Exp = sub( *energyValuesSum_Exp, shl( sf_Values, 1 ) );
    1316           0 :     move16();
    1317             : 
    1318           0 :     IF( GT_16( numberBands, 20 ) )
    1319             :     {
    1320           0 :         numberBandsM = s_min( numberBands, 40 );
    1321           0 :         numberBandsM20 = sub( numberBandsM, 20 );
    1322             : 
    1323           0 :         numberColsL = sub( numberCols, numLookahead );
    1324             : 
    1325             :         /* sum up CLDFB energy above 8 kHz */
    1326           0 :         s = BASOP_util_norm_s_bands2shift( i_mult( numberColsL, numberBandsM20 ) );
    1327           0 :         s = sub( s, 4 );
    1328           0 :         nrg = 0;
    1329           0 :         move32();
    1330           0 :         FOR( k = 0; k < numberColsL; k++ )
    1331             :         {
    1332           0 :             FOR( j = 20; j < numberBandsM; j++ )
    1333             :             {
    1334             : #ifdef ISSUE_1836_replace_overflow_libcom
    1335           0 :                 nrg = L_add_sat( nrg, L_shr_sat( energyValues[k][j], s ) );
    1336             : #else
    1337             :                 nrg = L_add_o( nrg, L_shr_o( energyValues[k][j], s, &Overflow ), &Overflow );
    1338             : #endif
    1339             :             }
    1340             :         }
    1341             : 
    1342           0 :         s = sub( sub( shl( sf_Values, 1 ), 1 ), s );
    1343           0 :         sm = sub( s_min( s, *sf_energyLookahead ), 1 );
    1344             : 
    1345           0 :         *energyHF = L_add( L_shr( nrg, limitScale32( sub( s, sm ) ) ),
    1346           0 :                            L_shr( *energyLookahead, sub( *sf_energyLookahead, sm ) ) ); // Q(31-(-nm))
    1347           0 :         move32();
    1348             : 
    1349           0 :         *energyHF_Exp = negate( sm );
    1350           0 :         move16();
    1351             : 
    1352             :         /* process look-ahead region */
    1353           0 :         s = BASOP_util_norm_s_bands2shift( i_mult( numLookahead, numberBandsM20 ) );
    1354           0 :         s = sub( s, 2 );
    1355           0 :         nrg = 0;
    1356           0 :         move32();
    1357           0 :         FOR( k = numberColsL; k < numberCols; k++ )
    1358             :         {
    1359           0 :             FOR( j = 20; j < numberBandsM; j++ )
    1360             :             {
    1361             : #ifdef ISSUE_1836_replace_overflow_libcom
    1362           0 :                 nrg = L_add_sat( nrg, L_shr_sat( energyValues[k][j], s ) );
    1363             : #else
    1364             :                 nrg = L_add_o( nrg, L_shr_o( energyValues[k][j], s, &Overflow ), &Overflow );
    1365             : #endif
    1366             :             }
    1367             :         }
    1368             : 
    1369           0 :         s = sub( shl( sf_Values, 1 ), s );
    1370           0 :         sm = sub( s_min( s, 44 ), 1 );
    1371             :         BASOP_SATURATE_WARNING_OFF_EVS
    1372             :         /* nrg + 6.1e-5f => value 0x40000000, scale 44 */
    1373           0 :         *energyLookahead = L_add_sat( L_shr_sat( nrg, sub( s, sm ) ),
    1374           0 :                                       L_shr_sat( 0x40000000, s_max( -31, s_min( 31, sub( 44, sm ) ) ) ) );
    1375           0 :         move32();
    1376             :         BASOP_SATURATE_WARNING_ON_EVS
    1377           0 :         *sf_energyLookahead = sm;
    1378           0 :         move16();
    1379             : 
    1380           0 :         return;
    1381             :     }
    1382             : 
    1383             : 
    1384           0 :     *energyHF = 0x40000000;
    1385           0 :     move32();
    1386           0 :     *energyHF_Exp = 17;
    1387           0 :     move16();
    1388             : }
    1389             : 
    1390             : 
    1391             : Word16
    1392          14 : CLDFB_getNumChannels( Word32 sampleRate )
    1393             : {
    1394             : 
    1395          14 :     Word16 nChannels = 0;
    1396          14 :     move16();
    1397             : 
    1398             : 
    1399          14 :     SWITCH( sampleRate )
    1400             :     {
    1401           5 :         case 48000:
    1402           5 :             move16();
    1403           5 :             nChannels = 60;
    1404           5 :             BREAK;
    1405           1 :         case 32000:
    1406           1 :             move16();
    1407           1 :             nChannels = 40;
    1408           1 :             BREAK;
    1409           0 :         case 25600:
    1410           0 :             move16();
    1411           0 :             nChannels = 32;
    1412           0 :             BREAK;
    1413           5 :         case 16000:
    1414           5 :             move16();
    1415           5 :             nChannels = 20;
    1416           5 :             BREAK;
    1417           3 :         case 12800:
    1418           3 :             move16();
    1419           3 :             nChannels = 16;
    1420           3 :             BREAK;
    1421           0 :         case 8000:
    1422           0 :             move16();
    1423           0 :             nChannels = 10;
    1424           0 :             BREAK;
    1425             :     }
    1426             : 
    1427          14 :     return ( nChannels );
    1428             : }
    1429             : 
    1430             : /*-------------------------------------------------------------------*
    1431             :  * cldfb_get_memory_length()
    1432             :  *
    1433             :  * Return length of filter state for recovery
    1434             :  *--------------------------------------------------------------------*/
    1435             : static Word16
    1436         309 : cldfb_get_memory_length( HANDLE_CLDFB_FILTER_BANK hs )
    1437             : {
    1438         309 :     IF( EQ_16( hs->type, CLDFB_ANALYSIS ) )
    1439             :     {
    1440         206 :         return ( i_mult( hs->no_channels, STATE_BUFFER_SIZE ) );
    1441             :     }
    1442             :     ELSE
    1443             :     {
    1444         103 :         return ( i_mult( hs->no_channels, ( 9 * 2 ) ) );
    1445             :     }
    1446             : }
    1447             : 
    1448             : /*-------------------------------------------------------------------*
    1449             :  * GetEnergyCldfb()
    1450             :  *
    1451             :  * Remove handle
    1452             :  *--------------------------------------------------------------------*/
    1453           9 : void deleteCldfb( HANDLE_CLDFB_FILTER_BANK *h_cldfb ) /* i: cldfb handle */
    1454             : {
    1455           9 :     IF( *h_cldfb != NULL )
    1456             :     {
    1457           9 :         IF( ( *h_cldfb )->FilterStates != NULL )
    1458             :         {
    1459           9 :             free( ( *h_cldfb )->FilterStates );
    1460             :         }
    1461           9 :         free( *h_cldfb );
    1462             :     }
    1463           9 :     *h_cldfb = NULL;
    1464           9 : }
    1465             : 
    1466             : 
    1467             : /*-------------------------------------------------------------------*
    1468             :  * cldfb_init_proto_and_twiddles()
    1469             :  *
    1470             :  * Initializes rom pointer
    1471             :  *--------------------------------------------------------------------*/
    1472             : static void
    1473          19 : cldfb_init_proto_and_twiddles( HANDLE_CLDFB_FILTER_BANK hs ) /* i: cldfb handle */
    1474             : {
    1475             : 
    1476             :     /*find appropriate set of rotVecs*/
    1477          19 :     SWITCH( hs->no_channels )
    1478             :     {
    1479           0 :         case 10:
    1480             : 
    1481           0 :             hs->rRotVctr = rRotVectr_10;
    1482           0 :             hs->iRotVctr = iRotVectr_10;
    1483           0 :             hs->synGain = cldfb_synGain[0];
    1484           0 :             move16();
    1485           0 :             hs->p_filter = cldfb_protoFilter_2_5ms[0];
    1486           0 :             hs->scale = cldfb_scale_2_5ms[0];
    1487           0 :             move16();
    1488           0 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1489             :             {
    1490           0 :                 hs->synScalefactor = add( cldfb_synScale[0], hs->filterScale );
    1491           0 :                 move16();
    1492             :             }
    1493             :             ELSE
    1494             :             {
    1495           0 :                 hs->anaScalefactor = add( cldfb_anaScale[0], hs->filterScale );
    1496           0 :                 move16();
    1497             :             }
    1498           0 :             BREAK;
    1499             : 
    1500           6 :         case 16:
    1501           6 :             hs->rRotVctr = rRotVectr_16;
    1502           6 :             hs->iRotVctr = iRotVectr_16;
    1503           6 :             hs->synGain = cldfb_synGain[1];
    1504           6 :             move16();
    1505           6 :             hs->p_filter = cldfb_protoFilter_2_5ms[1];
    1506           6 :             hs->scale = cldfb_scale_2_5ms[1];
    1507           6 :             move16();
    1508             :             {
    1509           6 :                 hs->anaScalefactor = add( cldfb_anaScale[1], hs->filterScale );
    1510           6 :                 move16();
    1511             :             }
    1512           6 :             BREAK;
    1513             : 
    1514           7 :         case 20:
    1515           7 :             hs->rRotVctr = rRotVectr_20;
    1516           7 :             hs->iRotVctr = iRotVectr_20;
    1517           7 :             hs->synGain = cldfb_synGain[2];
    1518           7 :             move16();
    1519           7 :             hs->p_filter = cldfb_protoFilter_2_5ms[2];
    1520           7 :             hs->scale = cldfb_scale_2_5ms[2];
    1521           7 :             move16();
    1522           7 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1523             :             {
    1524           0 :                 hs->synScalefactor = add( cldfb_synScale[2], hs->filterScale );
    1525           0 :                 move16();
    1526             :             }
    1527             :             ELSE
    1528             :             {
    1529           7 :                 hs->anaScalefactor = add( cldfb_anaScale[2], hs->filterScale );
    1530           7 :                 move16();
    1531             :             }
    1532           7 :             BREAK;
    1533             : 
    1534           0 :         case 32:
    1535           0 :             hs->rRotVctr = rRotVectr_32;
    1536           0 :             hs->iRotVctr = iRotVectr_32;
    1537           0 :             hs->synGain = cldfb_synGain[3];
    1538           0 :             move16();
    1539           0 :             hs->p_filter = cldfb_protoFilter_2_5ms[3];
    1540           0 :             hs->scale = cldfb_scale_2_5ms[3];
    1541           0 :             move16();
    1542             :             {
    1543           0 :                 hs->anaScalefactor = add( cldfb_anaScale[3], hs->filterScale );
    1544           0 :                 move16();
    1545             :             }
    1546           0 :             BREAK;
    1547             : 
    1548           1 :         case 40:
    1549           1 :             hs->rRotVctr = rRotVectr_40;
    1550           1 :             hs->iRotVctr = iRotVectr_40;
    1551           1 :             hs->synGain = cldfb_synGain[4];
    1552           1 :             move16();
    1553           1 :             hs->p_filter = cldfb_protoFilter_2_5ms[4];
    1554           1 :             hs->scale = cldfb_scale_2_5ms[4];
    1555           1 :             move16();
    1556           1 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1557             :             {
    1558           1 :                 hs->synScalefactor = add( cldfb_synScale[4], hs->filterScale );
    1559           1 :                 move16();
    1560             :             }
    1561             :             ELSE
    1562             :             {
    1563           0 :                 hs->anaScalefactor = add( cldfb_anaScale[4], hs->filterScale );
    1564           0 :                 move16();
    1565             :             }
    1566           1 :             BREAK;
    1567             : 
    1568           5 :         case 60:
    1569           5 :             hs->rRotVctr = rRotVectr_60;
    1570           5 :             hs->iRotVctr = iRotVectr_60;
    1571           5 :             hs->synGain = cldfb_synGain[5];
    1572           5 :             move16();
    1573           5 :             hs->p_filter = cldfb_protoFilter_2_5ms[5];
    1574           5 :             hs->scale = cldfb_scale_2_5ms[5];
    1575           5 :             move16();
    1576           5 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1577             :             {
    1578           2 :                 hs->synScalefactor = add( cldfb_synScale[5], hs->filterScale );
    1579           2 :                 move16();
    1580             :             }
    1581             :             ELSE
    1582             :             {
    1583           3 :                 hs->anaScalefactor = add( cldfb_anaScale[5], hs->filterScale );
    1584           3 :                 move16();
    1585             :             }
    1586           5 :             BREAK;
    1587             :     }
    1588          19 : }
    1589             : 
    1590             : 
    1591             : #define CLDFB_MEM_EXPONENTS ( CLDFB_NO_COL_MAX + 9 )
    1592             : 
    1593             : /*-------------------------------------------------------------------*
    1594             :  * cldfb_save_memory()
    1595             :  *
    1596             :  * Save the memory of filter; to be restored with cldfb_restore_memory()
    1597             :  *--------------------------------------------------------------------*/
    1598             : ivas_error
    1599          75 : cldfb_save_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i: cldfb handle */
    1600             : {
    1601          75 :     test();
    1602          75 :     IF( hs->memory != NULL || hs->memory_length != 0 )
    1603             :     {
    1604             :         /* memory already stored; Free memory first */
    1605           0 :         return IVAS_ERR_OK;
    1606             :     }
    1607          75 :     hs->memory_length = cldfb_get_memory_length( hs );
    1608          75 :     move16();
    1609          75 :     hs->memory = (Word16 *) calloc( hs->memory_length + CLDFB_MEM_EXPONENTS + 1, sizeof( Word16 ) );
    1610             : 
    1611             :     /* save the memory */
    1612          75 :     Copy( hs->FilterStates, hs->memory, hs->memory_length );
    1613          75 :     Copy( hs->FilterStates_e, hs->memory + hs->memory_length, CLDFB_MEM_EXPONENTS );
    1614          75 :     hs->memory[hs->memory_length + CLDFB_MEM_EXPONENTS] = hs->FilterStates_eg;
    1615          75 :     move16();
    1616          75 :     IF( hs->memory == NULL )
    1617             :     {
    1618           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB\n" );
    1619             :     }
    1620          75 :     return IVAS_ERR_OK;
    1621             : }
    1622             : 
    1623             : 
    1624             : /*-------------------------------------------------------------------*
    1625             :  * cldfb_restore_memory()
    1626             :  *
    1627             :  * Restores the memory of filter; memory to be save by cldfb_save_memory()
    1628             :  *--------------------------------------------------------------------*/
    1629          75 : void cldfb_restore_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i/o: cldfb handle */
    1630             : 
    1631             : {
    1632             :     Word16 size;
    1633             : 
    1634             : 
    1635          75 :     size = cldfb_get_memory_length( hs );
    1636             : 
    1637             :     /* read the memory */
    1638          75 :     Copy( hs->memory, hs->FilterStates, hs->memory_length );
    1639          75 :     Copy( hs->memory + hs->memory_length, hs->FilterStates_e, CLDFB_MEM_EXPONENTS );
    1640          75 :     hs->FilterStates_eg = hs->memory[hs->memory_length + CLDFB_MEM_EXPONENTS];
    1641          75 :     move16();
    1642             : 
    1643             : 
    1644             :     /* adjust sample rate if it was changed in the meanwhile */
    1645          75 :     IF( NE_16( hs->memory_length, size ) )
    1646             :     {
    1647           0 :         lerp( hs->FilterStates, hs->FilterStates, size, hs->memory_length );
    1648             :     }
    1649             : 
    1650          75 :     hs->memory_length = 0;
    1651          75 :     free( hs->memory );
    1652          75 :     hs->memory = NULL;
    1653             : 
    1654          75 :     return;
    1655             : }
    1656             : 
    1657             : /*-------------------------------------------------------------------*
    1658             :  * cldfb_reset_memory()
    1659             :  *
    1660             :  * Resets the memory of filter.
    1661             :  *--------------------------------------------------------------------*/
    1662         159 : void cldfb_reset_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i/o: cldfb handle */
    1663             : {
    1664             :     Word16 length;
    1665             : 
    1666         159 :     length = cldfb_get_memory_length( hs );
    1667             :     /* erase the memory */
    1668         159 :     set16_fx( hs->FilterStates, 0, length );
    1669         159 :     set16_fx( hs->FilterStates_e, 0, sizeof( hs->FilterStates_e ) / sizeof( hs->FilterStates_e[0] ) );
    1670         159 :     hs->FilterStates_eg = 0;
    1671         159 :     move16();
    1672         159 :     return;
    1673             : }

Generated by: LCOV version 1.14