LCOV - code coverage report
Current view: top level - lib_com - cldfb_evs.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 665 743 89.5 %
Date: 2025-05-03 01:55:50 Functions: 19 21 90.5 %

          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      134034 : 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      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     138      134034 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     139      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     140      134034 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     141      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     142      134034 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     143      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     144      134034 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     145      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     146      134034 :     add1( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     147      134034 : }
     148             : 
     149      134034 : 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      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     156      134034 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     157      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     158      134034 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     159      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     160      134034 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     161      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     162      134034 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     163      134034 :     cplxMpy( rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c );
     164      134034 :     add2( rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s );
     165      134034 : }
     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      334276 : 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      334276 :     Word32 lc = L_shr( m, 1 );
     218             : 
     219      334276 :     const Word16 *cr = rRotVctr;
     220      334276 :     const Word16 *ci = iRotVctr;
     221             : 
     222     5890112 :     FOR( i = 0; i < lc; i++ )
     223             :     {
     224     5555836 :         CL_x = CL_form( *rXR, *rXI );
     225     5555836 :         C_c = C_form( *cr, *ci );
     226     5555836 :         CL_z = CL_mult_32x16( CL_x, C_c );
     227     5555836 :         *rYR = CL_Extract_real( CL_z );
     228     5555836 :         move32();
     229     5555836 :         *rYI = CL_Extract_imag( CL_z );
     230     5555836 :         move32();
     231     5555836 :         rYR += srYR;
     232     5555836 :         rYI += srYI;
     233     5555836 :         rXR += srXR;
     234     5555836 :         rXI += srXI;
     235             : 
     236     5555836 :         CL_x = CL_form( *iXR, *iXI );
     237     5555836 :         CL_z = CL_mult_32x16( CL_x, C_c );
     238     5555836 :         *iYR = CL_Extract_real( CL_z );
     239     5555836 :         move32();
     240     5555836 :         *iYI = CL_Extract_imag( CL_z );
     241     5555836 :         move32();
     242     5555836 :         iYR += siYR;
     243     5555836 :         iYI += siYI;
     244     5555836 :         iXR += siXR;
     245     5555836 :         iXI += siXI;
     246     5555836 :         cr++;
     247     5555836 :         ci++;
     248             :     }
     249      334276 : }
     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       64592 : 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       64592 :     y11 = &rY[( m + m2 ) + 1];
     289       64592 :     y12 = &rY[m2 - 2];
     290       64592 :     y13 = &rY[( m + m2 ) - 2];
     291       64592 :     y14 = &rY[m2 + 1];
     292             : 
     293       64592 :     y21 = &rY[m + m2];
     294       64592 :     y22 = &rY[m2 - 1];
     295       64592 :     y23 = &rY[( m + m2 ) - 1];
     296       64592 :     y24 = &rY[m2];
     297             : 
     298       64592 :     x11 = &rX[m - 2];
     299       64592 :     x12 = &rX[m - 1];
     300       64592 :     x13 = &iX[m - 2];
     301       64592 :     x14 = &iX[m - 1];
     302       64592 :     x21 = &rX[0];
     303       64592 :     x22 = &rX[1];
     304       64592 :     x23 = &iX[0];
     305       64592 :     x24 = &iX[1];
     306             : 
     307       64592 :     r11 = &rRotVctr[m2 - 1];
     308       64592 :     r12 = &iRotVctr[m2 - 1];
     309       64592 :     r21 = &rRotVctr[0];
     310       64592 :     r22 = &iRotVctr[0];
     311             : 
     312       64592 :     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       21712 :         case 20:
     319       21712 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     320       21712 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     321       21712 :             BREAK;
     322       26562 :         case 60:
     323       26562 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     324       26562 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     325       26562 :             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       42880 :         case 40:
     328       42880 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     329       42880 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     330       42880 :             ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
     331       42880 :             cplxMultAdd20_1( y11, y12, y13, y14, x11, x12, x13, x14, r11, r12, gain, scale, -2, -1 );
     332       42880 :             cplxMultAdd20_2( y21, y22, y23, y24, x21, x22, x23, x24, r21, r22, gain, scale, 2, 1 );
     333       42880 :             ptrUpdate20( y11, y12, y13, y14, r11, x11, x12, x13, x14, r12, y21, y22, y23, y24, r21, x21, x22, x23, x24, r22 );
     334       42880 :             BREAK;
     335           0 :         default:
     336           0 :             assert( 0 );
     337             :     }
     338       64592 : }
     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        8490 : 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        8490 :     stride = 1; /* constant */
     408        8490 :     move16();
     409        8490 :     m = cldfbBank->no_channels;
     410        8490 :     move16();
     411        8490 :     L2 = shl( m, 1 );
     412        8490 :     m2 = shr( m, 1 );
     413        8490 :     M4 = shr( m, 2 );
     414        8490 :     M4 = sub( m2, M4 );
     415             : 
     416        8490 :     L3 = sub( L2, m2 );
     417        8490 :     L4 = add( L2, m2 );
     418             : 
     419        8490 :     M0M2 = sub( 0, m2 );
     420        8490 :     M2M1 = sub( m2, 1 );
     421        8490 :     L3M1 = sub( L3, 1 );
     422        8490 :     L4M1 = sub( L4, 1 );
     423             : 
     424        8490 :     rBuffer = &pWorkBuffer[0];
     425        8490 :     iBuffer = &pWorkBuffer[m];
     426             : 
     427        8490 :     rRotVctr = cldfbBank->rRotVctr;
     428        8490 :     iRotVctr = cldfbBank->iRotVctr;
     429             : 
     430        8490 :     pStates = cldfbBank->FilterStates;
     431        8490 :     pStates1 = &pStates[L3M1];
     432        8490 :     pStates2 = &pStates[L3];
     433        8490 :     pStates3 = &pStates[m2];
     434        8490 :     pStates4 = &pStates[M2M1];
     435        8490 :     pStates5 = &pStates[L4M1];
     436        8490 :     pStates6 = &pStates[M0M2];
     437             : 
     438        8490 :     p_stride = CLDFB_NO_POLY;
     439        8490 :     move16();
     440        8490 :     pFilter = &cldfbBank->p_filter[p_stride - CLDFB_NO_POLY];
     441        8490 :     pFilter1 = &pFilter[p_stride * L3M1];
     442        8490 :     pFilter2 = &pFilter[p_stride * L3];
     443        8490 :     pFilter3 = &pFilter[p_stride * m2];
     444        8490 :     pFilter4 = &pFilter[p_stride * M2M1];
     445        8490 :     pFilter5 = &pFilter[p_stride * L4M1];
     446        8490 :     pFilter6 = &pFilter[p_stride * M0M2];
     447             : 
     448        8490 :     nSamples = i_mult( nTimeSlots, cldfbBank->no_channels );
     449        8490 :     nSamplesUpd = i_mult( cldfbBank->no_col, cldfbBank->no_channels );
     450        8490 :     offset = sub( sub( cldfbBank->p_filter_length, cldfbBank->no_channels ), cldfbBank->zeros );
     451             : 
     452             :     /* Determine states scale */
     453        8490 :     scale = -15;
     454        8490 :     move16();
     455        8490 :     k = 0;
     456        8490 :     move16();
     457       84900 :     FOR( i = 0; i < offset; i += cldfbBank->no_channels )
     458             :     {
     459       76410 :         cldfbBank->FilterStates_e[k] = cldfbBank->FilterStates_e[( k + cldfbBank->no_col )];
     460       76410 :         move16();
     461       76410 :         assert( (size_t) k < sizeof( cldfbBank->FilterStates_e ) / sizeof( cldfbBank->FilterStates_e[0] ) );
     462       76410 :         scale = s_max( scale, cldfbBank->FilterStates_e[k] );
     463       76410 :         k = add( k, 1 );
     464             :     }
     465      143332 :     FOR( i = 0; i < nSamples; i += cldfbBank->no_channels )
     466             :     {
     467      134842 :         cldfbBank->FilterStates_e[k] = timeIn_e;
     468      134842 :         move16();
     469      134842 :         assert( (size_t) k < sizeof( cldfbBank->FilterStates_e ) / sizeof( cldfbBank->FilterStates_e[0] ) );
     470      134842 :         scale = s_max( scale, cldfbBank->FilterStates_e[k] );
     471      134842 :         k = add( k, 1 );
     472             :     }
     473        8490 :     i = s_max( scale, timeIn_e );
     474        8490 :     scale = sub( cldfbBank->FilterStates_eg, i );
     475        8490 :     cldfbBank->FilterStates_eg = i;
     476        8490 :     move16();
     477             : 
     478             :     /* if nTimeSlots==0, make sure we have a value. */
     479        8490 :     scaleFactor->lb_scale = add( cldfbBank->anaScalefactor, add( cldfbBank->FilterStates_eg, 5 ) );
     480        8490 :     move16();
     481             : 
     482             :     /* move and scale filter states */
     483     2390034 :     FOR( i = 0; i < offset; i++ )
     484             :     {
     485     2381544 :         pStates[i] = shl_sat( pStates[i + nSamplesUpd], scale ); // Q(15-(timeIn_e-FilterStates_eg))
     486     2381544 :         move16();
     487             :     }
     488             : 
     489             :     /* copy and scale current time signal */
     490        8490 :     scale = sub( timeIn_e, cldfbBank->FilterStates_eg );
     491     4223986 :     FOR( i = 0; i < nSamples; i++ )
     492             :     {
     493     4215496 :         pStates[offset + i] = shl_sat( *timeIn, scale ); // Q(15-scale)
     494     4215496 :         move16();
     495     4215496 :         timeIn = timeIn + stride;
     496             :     }
     497             : 
     498      143332 :     FOR( k = 0; k < nTimeSlots; k++ )
     499             :     {
     500     1188716 :         FOR( i = 0; i < M4; i++ )
     501             :         {
     502             :             /* prototype filter */
     503     1053874 :             r1 = L_msu0( 0, pFilter1[0 - ( p_stride * ( i * 2 ) )], pStates1[( 0 * L2 ) - ( i * 2 )] );
     504     1053874 :             r1 = L_msu0( r1, pFilter1[1 - ( p_stride * ( i * 2 ) )], pStates1[( 1 * L2 ) - ( i * 2 )] );
     505     1053874 :             r1 = L_msu0( r1, pFilter1[2 - ( p_stride * ( i * 2 ) )], pStates1[( 2 * L2 ) - ( i * 2 )] );
     506     1053874 :             r1 = L_msu0( r1, pFilter1[3 - ( p_stride * ( i * 2 ) )], pStates1[( 3 * L2 ) - ( i * 2 )] );
     507     1053874 :             r1 = L_msu0( r1, pFilter1[4 - ( p_stride * ( i * 2 ) )], pStates1[( 4 * L2 ) - ( i * 2 )] );
     508             : 
     509     1053874 :             r2 = L_msu0( 0, pFilter2[0 + ( p_stride * ( i * 2 ) )], pStates2[( 0 * L2 ) + ( i * 2 )] );
     510     1053874 :             r2 = L_msu0( r2, pFilter2[1 + ( p_stride * ( i * 2 ) )], pStates2[( 1 * L2 ) + ( i * 2 )] );
     511     1053874 :             r2 = L_msu0( r2, pFilter2[2 + ( p_stride * ( i * 2 ) )], pStates2[( 2 * L2 ) + ( i * 2 )] );
     512     1053874 :             r2 = L_msu0( r2, pFilter2[3 + ( p_stride * ( i * 2 ) )], pStates2[( 3 * L2 ) + ( i * 2 )] );
     513     1053874 :             r2 = L_msu0( r2, pFilter2[4 + ( p_stride * ( i * 2 ) )], pStates2[( 4 * L2 ) + ( i * 2 )] );
     514             : 
     515     1053874 :             i1 = L_msu0( 0, pFilter3[0 + ( p_stride * ( i * 2 ) )], pStates3[( 0 * L2 ) + ( i * 2 )] );
     516     1053874 :             i1 = L_msu0( i1, pFilter3[1 + ( p_stride * ( i * 2 ) )], pStates3[( 1 * L2 ) + ( i * 2 )] );
     517     1053874 :             i1 = L_msu0( i1, pFilter3[2 + ( p_stride * ( i * 2 ) )], pStates3[( 2 * L2 ) + ( i * 2 )] );
     518     1053874 :             i1 = L_msu0( i1, pFilter3[3 + ( p_stride * ( i * 2 ) )], pStates3[( 3 * L2 ) + ( i * 2 )] );
     519     1053874 :             i1 = L_msu0( i1, pFilter3[4 + ( p_stride * ( i * 2 ) )], pStates3[( 4 * L2 ) + ( i * 2 )] );
     520             : 
     521     1053874 :             i2 = L_msu0( 0, pFilter4[0 - ( p_stride * ( i * 2 ) )], pStates4[( 0 * L2 ) - ( i * 2 )] );
     522     1053874 :             i2 = L_msu0( i2, pFilter4[1 - ( p_stride * ( i * 2 ) )], pStates4[( 1 * L2 ) - ( i * 2 )] );
     523     1053874 :             i2 = L_msu0( i2, pFilter4[2 - ( p_stride * ( i * 2 ) )], pStates4[( 2 * L2 ) - ( i * 2 )] );
     524     1053874 :             i2 = L_msu0( i2, pFilter4[3 - ( p_stride * ( i * 2 ) )], pStates4[( 3 * L2 ) - ( i * 2 )] );
     525     1053874 :             i2 = L_msu0( i2, pFilter4[4 - ( p_stride * ( i * 2 ) )], pStates4[( 4 * L2 ) - ( i * 2 )] );
     526             : 
     527             :             /* folding */
     528     1053874 :             rBuffer[2 * i] = L_sub( r1, r2 );
     529     1053874 :             move32();
     530     1053874 :             rBuffer[( ( i * 2 ) + 1 )] = L_negate( L_add( i1, i2 ) );
     531     1053874 :             move32();
     532             : 
     533             :             /* folding */
     534     1053874 :             iBuffer[2 * i] = L_add( r1, r2 );
     535     1053874 :             move32();
     536     1053874 :             iBuffer[( ( i * 2 ) + 1 )] = L_sub( i1, i2 );
     537     1053874 :             move32();
     538             :         }
     539             : 
     540     1188716 :         FOR( i = M4; i < m2; i++ )
     541             :         {
     542             :             /* prototype filter */
     543     1053874 :             r1 = L_msu0( 0, pFilter1[0 - ( p_stride * ( i * 2 ) )], pStates1[( 0 * L2 ) - ( i * 2 )] );
     544     1053874 :             r1 = L_msu0( r1, pFilter1[1 - ( p_stride * ( i * 2 ) )], pStates1[( 1 * L2 ) - ( i * 2 )] );
     545     1053874 :             r1 = L_msu0( r1, pFilter1[2 - ( p_stride * ( i * 2 ) )], pStates1[( 2 * L2 ) - ( i * 2 )] );
     546     1053874 :             r1 = L_msu0( r1, pFilter1[3 - ( p_stride * ( i * 2 ) )], pStates1[( 3 * L2 ) - ( i * 2 )] );
     547     1053874 :             r1 = L_msu0( r1, pFilter1[4 - ( p_stride * ( i * 2 ) )], pStates1[( 4 * L2 ) - ( i * 2 )] );
     548             : 
     549     1053874 :             r2 = L_msu0( 0, pFilter6[0 + ( p_stride * ( i * 2 ) )], pStates6[( 0 * L2 ) + ( i * 2 )] );
     550     1053874 :             r2 = L_msu0( r2, pFilter6[1 + ( p_stride * ( i * 2 ) )], pStates6[( 1 * L2 ) + ( i * 2 )] );
     551     1053874 :             r2 = L_msu0( r2, pFilter6[2 + ( p_stride * ( i * 2 ) )], pStates6[( 2 * L2 ) + ( i * 2 )] );
     552     1053874 :             r2 = L_msu0( r2, pFilter6[3 + ( p_stride * ( i * 2 ) )], pStates6[( 3 * L2 ) + ( i * 2 )] );
     553     1053874 :             r2 = L_msu0( r2, pFilter6[4 + ( p_stride * ( i * 2 ) )], pStates6[( 4 * L2 ) + ( i * 2 )] );
     554             : 
     555     1053874 :             i1 = L_msu0( 0, pFilter5[0 - ( p_stride * ( i * 2 ) )], pStates5[( 0 * L2 ) - ( i * 2 )] );
     556     1053874 :             i1 = L_msu0( i1, pFilter5[1 - ( p_stride * ( i * 2 ) )], pStates5[( 1 * L2 ) - ( i * 2 )] );
     557     1053874 :             i1 = L_msu0( i1, pFilter5[2 - ( p_stride * ( i * 2 ) )], pStates5[( 2 * L2 ) - ( i * 2 )] );
     558     1053874 :             i1 = L_msu0( i1, pFilter5[3 - ( p_stride * ( i * 2 ) )], pStates5[( 3 * L2 ) - ( i * 2 )] );
     559     1053874 :             i1 = L_msu0( i1, pFilter5[4 - ( p_stride * ( i * 2 ) )], pStates5[( 4 * L2 ) - ( i * 2 )] );
     560             : 
     561     1053874 :             i2 = L_msu0( 0, pFilter3[0 + ( p_stride * ( i * 2 ) )], pStates3[( 0 * L2 ) + ( i * 2 )] );
     562     1053874 :             i2 = L_msu0( i2, pFilter3[1 + ( p_stride * ( i * 2 ) )], pStates3[( 1 * L2 ) + ( i * 2 )] );
     563     1053874 :             i2 = L_msu0( i2, pFilter3[2 + ( p_stride * ( i * 2 ) )], pStates3[( 2 * L2 ) + ( i * 2 )] );
     564     1053874 :             i2 = L_msu0( i2, pFilter3[3 + ( p_stride * ( i * 2 ) )], pStates3[( 3 * L2 ) + ( i * 2 )] );
     565     1053874 :             i2 = L_msu0( i2, pFilter3[4 + ( p_stride * ( i * 2 ) )], pStates3[( 4 * L2 ) + ( i * 2 )] );
     566             : 
     567             :             /* folding */
     568     1053874 :             rBuffer[2 * i] = L_add( r1, r2 );
     569     1053874 :             move32();
     570     1053874 :             rBuffer[( ( i * 2 ) + 1 )] = L_sub( i1, i2 );
     571     1053874 :             move32();
     572             : 
     573             :             /* folding */
     574     1053874 :             iBuffer[2 * i] = L_sub( r1, r2 );
     575     1053874 :             move32();
     576     1053874 :             iBuffer[( ( i * 2 ) + 1 )] = L_add( i1, i2 );
     577     1053874 :             move32();
     578             :         }
     579             : 
     580             :         /* pre modulation of DST IV and DCT IV */
     581      134842 :         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      134842 :         scale = 0;
     587      134842 :         move16();
     588      134842 :         BASOP_cfft( (cmplx *) rBuffer, m2, &scale, workBuffer );
     589             : 
     590             :         /* store analysis scalefactor for cldfb */
     591      134842 :         scaleFactor->lb_scale = add( cldfbBank->anaScalefactor, add( cldfbBank->FilterStates_eg, scale ) );
     592      134842 :         move16();
     593             : 
     594             :         /* FFT of DCT IV */
     595      134842 :         BASOP_cfft( (cmplx *) iBuffer, m2, &scale, workBuffer );
     596             : 
     597             :         /* post modulation of DST IV and DCT IV */
     598      134842 :         calcModulation( &rAnalysis[k][m - 1], &rAnalysis[k][0], &rBuffer[0], &rBuffer[1], -2, 2, 2, 2,
     599      134842 :                         &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      134842 :         pStates1 = &pStates1[cldfbBank->no_channels];
     605      134842 :         pStates2 = &pStates2[cldfbBank->no_channels];
     606      134842 :         pStates3 = &pStates3[cldfbBank->no_channels];
     607      134842 :         pStates5 = &pStates5[cldfbBank->no_channels];
     608      134842 :         pStates4 = &pStates4[cldfbBank->no_channels];
     609      134842 :         pStates6 = &pStates6[cldfbBank->no_channels];
     610             :     }
     611        8490 : }
     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        4052 : 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        4052 :     m = cldfbBank->no_channels;
     687        4052 :     move16();
     688        4052 :     L2 = shl( m, 1 );
     689        4052 :     m2 = shr( m, 1 );
     690        4052 :     Lz = s_min( cldfbBank->lsb, sub( m, cldfbBank->bandsToZero ) );
     691        4052 :     Mz = s_min( cldfbBank->usb, sub( m, cldfbBank->bandsToZero ) );
     692        4052 :     stride = 1; /* constant */
     693        4052 :     move16();
     694        4052 :     channels0 = sub( m, cldfbBank->zeros );
     695        4052 :     channels1 = sub( m, 1 );
     696        4052 :     channels2 = shl( m, 1 );
     697        4052 :     channels3 = add( m, channels2 );
     698        4052 :     channels4 = shl( channels2, 1 );
     699             : 
     700        4052 :     statesSizeM1 = sub( shl( cldfbBank->p_filter_length, 1 ), m );
     701        4052 :     statesSizeM2 = sub( statesSizeM1, m );
     702             : 
     703        4052 :     offset1 = sub( channels1, cldfbBank->zeros );
     704        4052 :     offset2 = add( offset1, cldfbBank->no_channels );
     705             : 
     706        4052 :     rBuffer = &pWorkBuffer[0];
     707        4052 :     iBuffer = &pWorkBuffer[m];
     708        4052 :     nBuffer = (Word16 *) ( &pWorkBuffer[L2] );
     709             : 
     710        4052 :     rAnalysisS = &pWorkBuffer[3 * m];
     711        4052 :     iAnalysisS = &pWorkBuffer[4 * m];
     712             : 
     713        4052 :     rRotVctr = cldfbBank->rRotVctr;
     714        4052 :     iRotVctr = cldfbBank->iRotVctr;
     715             : 
     716        4052 :     scale = scaleFactor->lb_scale;
     717        4052 :     move16();
     718        4052 :     if ( NE_16( Lz, Mz ) )
     719             :     {
     720        1255 :         scale = s_max( scale, scaleFactor->hb_scale );
     721             :     }
     722        4052 :     scaleLB = limitScale32( sub( scale, scaleFactor->lb_scale ) );
     723        4052 :     scaleHB = limitScale32( sub( scale, scaleFactor->hb_scale ) );
     724             : 
     725        4052 :     outScale = cldfbBank->synFilterHeadroom;
     726        4052 :     move16();
     727             : 
     728        4052 :     scaleMod = sub( add( scale, cldfbBank->outScalefactor ), outScale );
     729             : 
     730             :     /* Increase CLDFB synthesis states for low level signals */
     731        4052 :     IF( LT_16( scale, 8 ) )
     732             :     {
     733         127 :         scaleMod = add( scaleMod, 2 );
     734         127 :         outScale = sub( outScale, 2 );
     735             :     }
     736        4052 :     scaleMod = sub( scaleMod, timeOut_e );
     737        4052 :     scale = add( outScale, timeOut_e );
     738        4052 :     IF( NE_16( scale, cldfbBank->FilterStates_eg ) )
     739             :     {
     740         505 :         Scale_sig( cldfbBank->FilterStates, statesSizeM2, sub( cldfbBank->FilterStates_eg, scale ) ); // Q(15-scale)
     741         505 :         cldfbBank->FilterStates_eg = scale;
     742         505 :         move16();
     743             :     }
     744             : 
     745       68644 :     FOR( k = 0; k < nTimeSlots; k++ )
     746             :     {
     747             :         {
     748      677876 :             FOR( i = 0; i < Lz; i += 2 )
     749             :             {
     750      613284 :                 rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleLB );
     751      613284 :                 move32();
     752      613284 :                 iAnalysisS[i] = L_negate( L_shr( iAnalysis[k][i], scaleLB ) );
     753      613284 :                 move32();
     754             :             }
     755             : 
     756       64592 :             IF( LT_16( i, Mz ) )
     757             :             {
     758      386418 :                 FOR( ; i < Mz; i += 2 )
     759             :                 {
     760      366408 :                     rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleHB );
     761      366408 :                     move32();
     762      366408 :                     iAnalysisS[i] = L_negate( L_shr( iAnalysis[k][i], scaleHB ) );
     763      366408 :                     move32();
     764             :                 }
     765             :             }
     766             : 
     767       64592 :             IF( LT_16( i, m ) )
     768             :             {
     769      383518 :                 FOR( ; i < m; i += 2 )
     770             :                 {
     771      360648 :                     rAnalysisS[i] = 0;
     772      360648 :                     move32();
     773      360648 :                     iAnalysisS[i] = 0;
     774      360648 :                     move32();
     775             :                 }
     776             :             }
     777             : 
     778      677876 :             FOR( i = 1; i < Lz; i += 2 )
     779             :             {
     780      613284 :                 rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleLB );
     781      613284 :                 move32();
     782      613284 :                 iAnalysisS[i] = L_shr( iAnalysis[k][i], scaleLB );
     783      613284 :                 move32();
     784             :             }
     785             : 
     786       64592 :             IF( LT_16( i, Mz ) )
     787             :             {
     788      386418 :                 FOR( ; i < Mz; i += 2 )
     789             :                 {
     790      366408 :                     rAnalysisS[i] = L_shr( rAnalysis[k][i], scaleHB );
     791      366408 :                     move32();
     792      366408 :                     iAnalysisS[i] = L_shr( iAnalysis[k][i], scaleHB );
     793      366408 :                     move32();
     794             :                 }
     795             :             }
     796             : 
     797       64592 :             IF( LT_16( i, m ) )
     798             :             {
     799      383518 :                 FOR( ; i < m; i += 2 )
     800             :                 {
     801      360648 :                     rAnalysisS[i] = 0;
     802      360648 :                     move32();
     803      360648 :                     iAnalysisS[i] = 0;
     804      360648 :                     move32();
     805             :                 }
     806             :             }
     807             :         }
     808             : 
     809             :         /* pre modulation */
     810       64592 :         calcModulation( &rBuffer[0], &rBuffer[1], &rAnalysisS[0], &rAnalysisS[m - 1], 2, 2, 2, -2,
     811       64592 :                         &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       64592 :         scale = 0;
     817       64592 :         move16();
     818       64592 :         BASOP_cfft( (cmplx *) rBuffer, m2, &scale, workBuffer );
     819             : 
     820             :         /* FFT of DCT IV */
     821       64592 :         scale = scaleMod;
     822       64592 :         move16();
     823       64592 :         BASOP_cfft( (cmplx *) iBuffer, m2, &scale, workBuffer );
     824             : 
     825             :         /* post modulation and folding */
     826       64592 :         calcModulationAndFolding( nBuffer, rBuffer, iBuffer, rRotVctr, iRotVctr, cldfbBank->synGain, scale, m, m2 );
     827             : 
     828             :         /* prototype filter */
     829       64592 :         pStates = &cldfbBank->FilterStates[( k * L2 )];
     830       64592 :         pFilterS = &cldfbBank->p_filter[0];
     831       64592 :         pFilterM = &cldfbBank->p_filter[shr( cldfbBank->p_filter_length, 1 )];
     832             : 
     833     2745272 :         FOR( i = 0; i < channels0; i++ )
     834             :         {
     835     2680680 :             pStatesI = &pStates[i];
     836     2680680 :             pStatesR = &pStates[add( i, channels3 )];
     837             : 
     838     2680680 :             acc = L_mult( *pStatesI, *pFilterS++ );
     839     2680680 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     840     2680680 :             pStatesR += channels4;
     841     2680680 :             pStatesI += channels4;
     842             : 
     843     2680680 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     844     2680680 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     845     2680680 :             pStatesR += channels4;
     846     2680680 :             pStatesI += channels4;
     847             : 
     848     2680680 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     849     2680680 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     850     2680680 :             pStatesR += channels4;
     851     2680680 :             pStatesI += channels4;
     852             : 
     853     2680680 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     854     2680680 :             acc = L_mac( acc, *pStatesR, *pFilterM++ );
     855     2680680 :             pStatesI += channels4;
     856             : 
     857     2680680 :             acc = L_mac( acc, *pStatesI, *pFilterS++ );
     858     2680680 :             acc = L_mac( acc, nBuffer[sub( channels1, i )], *pFilterM++ );
     859             : 
     860             :             BASOP_SATURATE_WARNING_OFF_EVS
     861     2680680 :             timeOut[( offset1 - i ) * stride] = round_fx_sat( L_shl_sat( acc, outScale ) );
     862             :             BASOP_SATURATE_WARNING_ON_EVS
     863     2680680 :             move16();
     864             :         }
     865             : 
     866       64592 :         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     2745272 :         FOR( i = 0; i < cldfbBank->no_channels; i++ )
     899             :         {
     900     2680680 :             pStates[statesSizeM1 + i] = nBuffer[channels1 - i];
     901     2680680 :             move16();
     902     2680680 :             pStates[statesSizeM2 + i] = nBuffer[( channels1 + m ) - i];
     903     2680680 :             move16();
     904             :         }
     905             : 
     906       64592 :         timeOut = &timeOut[m * stride];
     907             :     }
     908             : 
     909             :     /* move filter states */
     910        4052 :     Copy( &cldfbBank->FilterStates[nTimeSlots * L2], cldfbBank->FilterStates, statesSizeM2 );
     911        4052 :     set16_fx( &cldfbBank->FilterStates[statesSizeM2], 0, L2 );
     912        4052 : }
     913             : 
     914             : 
     915             : /*-------------------------------------------------------------------*
     916             :  * configureClfdb()
     917             :  *
     918             :  * configures a CLDFB handle
     919             :  *--------------------------------------------------------------------*/
     920             : 
     921          25 : 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          25 :     h_cldfb->no_channels = no_channels;
     928          25 :     move16();
     929          25 :     assert( h_cldfb->no_channels >= 10 );
     930          25 :     h_cldfb->no_col = div_l( frameSize, shr( h_cldfb->no_channels, 1 ) );
     931          25 :     move16();
     932             : 
     933             :     /* was cldfbInitFilterBank()*/
     934          25 :     h_cldfb->anaScalefactor = 0;
     935          25 :     move16();
     936          25 :     h_cldfb->synScalefactor = 0;
     937          25 :     move16();
     938          25 :     h_cldfb->bandsToZero = 0;
     939          25 :     move16();
     940          25 :     h_cldfb->filtermode = 0;
     941          25 :     move16();
     942          25 :     h_cldfb->memory = 0;
     943          25 :     move16();
     944          25 :     h_cldfb->memory_length = 0;
     945          25 :     move16();
     946             : 
     947          25 :     h_cldfb->p_filter_length = i_mult( 10, h_cldfb->no_channels );
     948          25 :     move16();
     949             : 
     950          25 :     h_cldfb->flags = s_or( h_cldfb->flags, CLDFB_FLAG_2_5MS_SETUP );
     951          25 :     move16();
     952          25 :     h_cldfb->filterScale = CLDFB_CLDFB80_PFT_SCALE;
     953          25 :     move16();
     954             : 
     955          25 :     h_cldfb->zeros = 0;
     956          25 :     move16();
     957          25 :     h_cldfb->synFilterHeadroom = SYN_FILTER_HEADROOM_2_5MS;
     958          25 :     move16();
     959             : 
     960          25 :     cldfb_init_proto_and_twiddles( h_cldfb );
     961             : 
     962          25 :     h_cldfb->lsb = no_channels;
     963          25 :     move16();
     964          25 :     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          25 :     move16();
     966             : 
     967          25 :     h_cldfb->FilterStates = (void *) h_cldfb->FilterStates;
     968          25 :     h_cldfb->outScalefactor = h_cldfb->synScalefactor;
     969          25 :     move16();
     970             : 
     971          25 :     return;
     972             : }
     973             : 
     974             : /*-------------------------------------------------------------------*
     975             :  * openClfdb()
     976             :  *
     977             :  * open and configures a CLDFB handle
     978             :  *--------------------------------------------------------------------*/
     979          15 : 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          15 :     hs = (HANDLE_CLDFB_FILTER_BANK) malloc( sizeof( CLDFB_FILTER_BANK ) );
     989          15 :     IF( hs == NULL )
     990             :     {
     991           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" );
     992             :     }
     993             : 
     994          15 :     hs->type = type;
     995          15 :     move16();
     996             : 
     997          15 :     IF( type == CLDFB_ANALYSIS )
     998             :     {
     999           9 :         hs->FilterStates = (Word16 *) malloc( STATE_BUFFER_SIZE * maxCldfbBands * sizeof( Word16 ) );
    1000             :     }
    1001             :     ELSE
    1002             :     {
    1003           6 :         hs->FilterStates = (Word16 *) malloc( 2 * STATE_BUFFER_SIZE * maxCldfbBands * sizeof( Word16 ) );
    1004             :     }
    1005          15 :     if ( hs->FilterStates == NULL )
    1006             :     {
    1007           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" );
    1008             :     }
    1009          15 :     hs->flags = s_and( hs->flags, ~CLDFB_FLAG_KEEP_STATES );
    1010          15 :     move16();
    1011          15 :     configureCldfb( hs, maxCldfbBands, frameSize );
    1012             : 
    1013          15 :     hs->memory = NULL;
    1014          15 :     hs->memory_length = 0;
    1015          15 :     move16();
    1016             : 
    1017          15 :     IF( hs->type == CLDFB_ANALYSIS )
    1018             :     {
    1019           9 :         test();
    1020           9 :         IF( ( s_and( hs->flags, CLDFB_FLAG_KEEP_STATES ) == 0 ) && ( hs->FilterStates != 0 ) )
    1021             :         {
    1022           9 :             set16_fx( hs->FilterStates, 0, i_mult( STATE_BUFFER_SIZE, hs->no_channels ) );
    1023           9 :             set16_fx( hs->FilterStates_e, 0, sizeof( hs->FilterStates_e ) / sizeof( hs->FilterStates_e[0] ) );
    1024             : 
    1025           9 :             hs->FilterStates_eg = 0;
    1026           9 :             move16();
    1027             :         }
    1028             :     }
    1029           6 :     ELSE IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1030             :     {
    1031           6 :         IF( hs->FilterStates != 0 )
    1032             :         {
    1033           6 :             IF( s_and( hs->flags, CLDFB_FLAG_KEEP_STATES ) == 0 )
    1034             :             {
    1035           6 :                 set16_fx( hs->FilterStates, 0, i_mult( shl( STATE_BUFFER_SIZE, 1 ), hs->no_channels ) );
    1036             :             }
    1037             :         }
    1038           6 :         hs->FilterStates_eg = 0;
    1039           6 :         move16();
    1040             :     }
    1041             : 
    1042          15 :     if ( h_cldfb != NULL )
    1043             :     {
    1044          15 :         *h_cldfb = hs;
    1045             :     }
    1046             : 
    1047          15 :     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      397424 : 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      397424 :     headRoom = BASOP_util_norm_l_dim2_cplx(
    1122             :         (const Word32 *const *) rSubband32,
    1123             :         (const Word32 *const *) iSubband32,
    1124             :         0,
    1125      397424 :         cldfbBank->no_channels,
    1126             :         0,
    1127      397424 :         cldfbBank->no_col );
    1128             : 
    1129     6756208 :     FOR( i = 0; i < cldfbBank->no_col; i++ )
    1130             :     {
    1131   364294784 :         FOR( j = 0; j < cldfbBank->no_channels; j++ )
    1132             :         {
    1133   357936000 :             rSubband16[i][j] = round_fx_sat( L_shl_sat( rSubband32[i][j], headRoom ) ); // Q(cldfbSacle_headRoom)
    1134   357936000 :             iSubband16[i][j] = round_fx_sat( L_shl_sat( iSubband32[i][j], headRoom ) ); // Q(cldfbSacle+headRoom)
    1135   357936000 :             move16();
    1136   357936000 :             move16();
    1137             :         }
    1138             :     }
    1139             : 
    1140      397424 :     *cldfbScale = add( *cldfbScale, headRoom );
    1141      397424 :     move16();
    1142             : 
    1143             : 
    1144      397424 :     return headRoom;
    1145             : }
    1146             : 
    1147             : 
    1148             : /*-------------------------------------------------------------------*
    1149             :  * analysisCLDFBEncoder()
    1150             :  *
    1151             :  * Encoder CLDFB analysis + energy stage
    1152             :  *--------------------------------------------------------------------*/
    1153             : 
    1154        3100 : 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        3100 :     Word16 num_slots = 1;
    1173        3100 :     move16();
    1174             : 
    1175       52700 :     FOR( i = 0; i < CLDFB_NO_COL_MAX; i++ )
    1176             :     {
    1177       49600 :         ppBuf_Real[i] = &realBuffer[i][0];
    1178       49600 :         ppBuf_Imag[i] = &imagBuffer[i][0];
    1179       49600 :         ppBuf_Real16[i] = &realBuffer16[i][0];
    1180       49600 :         ppBuf_Imag16[i] = &imagBuffer16[i][0];
    1181             :     }
    1182             : 
    1183             :     /* perform analysis */
    1184        3100 :     cldfbAnalysis_fx( st_fx->cldfbAnaEnc, ppBuf_Real, ppBuf_Imag, scale, timeIn, 0, CLDFB_NO_COL_MAX, workBuffer );
    1185             : 
    1186        3100 :     enerScale.lb_scale = negate( scale->lb_scale );
    1187        3100 :     enerScale.lb_scale16 = negate( scale->lb_scale );
    1188        3100 :     move16();
    1189        3100 :     move16();
    1190             : 
    1191             :     /* get 16bit respresentation */
    1192        3100 :     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        3100 :     GetEnergyCldfb( &st_fx->energyCoreLookahead_Fx,
    1202             :                     &st_fx->sf_energyCoreLookahead_Fx,
    1203             :                     num_slots,
    1204             :                     ppBuf_Real16,
    1205             :                     ppBuf_Imag16,
    1206        3100 :                     enerScale.lb_scale16,
    1207        3100 :                     st_fx->cldfbAnaEnc->no_channels,
    1208        3100 :                     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        3100 :     return;
    1216             : }
    1217             : 
    1218      397424 : 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             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
    1244      397424 :     Flag Overflow = 0;
    1245      397424 :     move32();
    1246             : #endif
    1247             : 
    1248     6756208 :     FOR( k = 0; k < numberCols; k++ )
    1249             :     {
    1250   364294784 :         FOR( j = 0; j < numberBands; j++ )
    1251             :         {
    1252   357936000 :             nrg = L_mult0( realValues[k][j], realValues[k][j] );     // Q(2*sf_Values)
    1253   357936000 :             nrg = L_mac0( nrg, imagValues[k][j], imagValues[k][j] ); // Q(2*sf_Values)
    1254             : 
    1255   357936000 :             energyValues[k][j] = nrg;
    1256   357936000 :             move32();
    1257             :         }
    1258             :     }
    1259             : 
    1260      397424 :     IF( GE_16( numberBands, freqTable[1] ) && hTecEnc != NULL )
    1261             :     {
    1262             :         Word32 *tempEnergyValuesArry[CLDFB_NO_COL_MAX];
    1263             :         Word16 ScaleX2;
    1264        3100 :         assert( numberCols == CLDFB_NO_COL_MAX );
    1265       52700 :         FOR( j = 0; j < numberCols; j++ )
    1266             :         {
    1267       49600 :             tempEnergyValuesArry[j] = &energyValues[j][0];
    1268             :         }
    1269             : 
    1270        3100 :         ScaleX2 = shl( sf_Values, 1 );
    1271        3100 :         calcHiEnvLoBuff_Fix(
    1272             :             numberCols,
    1273             :             freqTable,
    1274             :             1,
    1275             :             tempEnergyValuesArry,
    1276        3100 :             hTecEnc->loBuffer,
    1277        3100 :             hTecEnc->hiTempEnv,
    1278             :             ScaleX2 );
    1279             :     }
    1280             : 
    1281    22768424 :     FOR( j = 0; j < numberBands; j++ )
    1282             :     {
    1283    22371000 :         energyValuesSum[j] = 0;
    1284    22371000 :         move32();
    1285    22371000 :         energyValuesSumE[j] = 31;
    1286    22371000 :         move16();
    1287   380307000 :         FOR( k = 0; k < CLDFB_NO_COL_MAX; k++ )
    1288             :         {
    1289   357936000 :             nrg = L_shr_r( energyValues[k][j], sub( energyValuesSumE[j], 31 ) ); // Q(2*sf_Values - (energyValuesSumE[j]-31))
    1290   357936000 :             IF( LT_32( L_sub( maxWord32, nrg ), energyValuesSum[j] ) )
    1291             :             {
    1292      990700 :                 energyValuesSumE[j] = add( energyValuesSumE[j], 1 );
    1293      990700 :                 move16();
    1294      990700 :                 energyValuesSum[j] = L_shr_r( energyValuesSum[j], 1 );
    1295      990700 :                 move32();
    1296      990700 :                 nrg = L_shr_r( energyValues[k][j], 1 );
    1297             :             }
    1298   357936000 :             energyValuesSum[j] = L_add( energyValuesSum[j], nrg );
    1299   357936000 :             move32();
    1300             :         }
    1301    22371000 :         test();
    1302    22371000 :         if ( j == 0 || GT_16( energyValuesSumE[j], *energyValuesSum_Exp ) )
    1303             :         {
    1304      468909 :             *energyValuesSum_Exp = energyValuesSumE[j];
    1305      468909 :             move16();
    1306             :         }
    1307             :     }
    1308    22768424 :     FOR( j = 0; j < numberBands; j++ )
    1309             :     {
    1310    22371000 :         energyValuesSum[j] = L_shr_r( energyValuesSum[j], sub( *energyValuesSum_Exp, energyValuesSumE[j] ) ); // Q(energyValuesSum_Exp - (2*sf_Values))
    1311    22371000 :         move32();
    1312             :     }
    1313      397424 :     *energyValuesSum_Exp = sub( *energyValuesSum_Exp, shl( sf_Values, 1 ) );
    1314      397424 :     move16();
    1315             : 
    1316      397424 :     IF( GT_16( numberBands, 20 ) )
    1317             :     {
    1318      381329 :         numberBandsM = s_min( numberBands, 40 );
    1319      381329 :         numberBandsM20 = sub( numberBandsM, 20 );
    1320             : 
    1321      381329 :         numberColsL = sub( numberCols, numLookahead );
    1322             : 
    1323             :         /* sum up CLDFB energy above 8 kHz */
    1324      381329 :         s = BASOP_util_norm_s_bands2shift( i_mult( numberColsL, numberBandsM20 ) );
    1325      381329 :         s = sub( s, 4 );
    1326      381329 :         nrg = 0;
    1327      381329 :         move32();
    1328     6101264 :         FOR( k = 0; k < numberColsL; k++ )
    1329             :         {
    1330   120118635 :             FOR( j = 20; j < numberBandsM; j++ )
    1331             :             {
    1332   114398700 :                 nrg = L_add_o( nrg, L_shr_o( energyValues[k][j], s, &Overflow ), &Overflow );
    1333             :             }
    1334             :         }
    1335             : 
    1336      381329 :         s = sub( sub( shl( sf_Values, 1 ), 1 ), s );
    1337      381329 :         sm = sub( s_min( s, *sf_energyLookahead ), 1 );
    1338             : 
    1339      381329 :         *energyHF = L_add( L_shr( nrg, limitScale32( sub( s, sm ) ) ),
    1340      381329 :                            L_shr( *energyLookahead, sub( *sf_energyLookahead, sm ) ) ); // Q(31-(-nm))
    1341      381329 :         move32();
    1342             : 
    1343      381329 :         *energyHF_Exp = negate( sm );
    1344      381329 :         move16();
    1345             : 
    1346             :         /* process look-ahead region */
    1347      381329 :         s = BASOP_util_norm_s_bands2shift( i_mult( numLookahead, numberBandsM20 ) );
    1348      381329 :         s = sub( s, 2 );
    1349      381329 :         nrg = 0;
    1350      381329 :         move32();
    1351      762658 :         FOR( k = numberColsL; k < numberCols; k++ )
    1352             :         {
    1353     8007909 :             FOR( j = 20; j < numberBandsM; j++ )
    1354             :             {
    1355     7626580 :                 nrg = L_add_o( nrg, L_shr_o( energyValues[k][j], s, &Overflow ), &Overflow );
    1356             :             }
    1357             :         }
    1358             : 
    1359      381329 :         s = sub( shl( sf_Values, 1 ), s );
    1360      381329 :         sm = sub( s_min( s, 44 ), 1 );
    1361             :         BASOP_SATURATE_WARNING_OFF_EVS
    1362             :         /* nrg + 6.1e-5f => value 0x40000000, scale 44 */
    1363      381329 :         *energyLookahead = L_add_sat( L_shr_sat( nrg, sub( s, sm ) ),
    1364      381329 :                                       L_shr_sat( 0x40000000, s_max( -31, s_min( 31, sub( 44, sm ) ) ) ) );
    1365      381329 :         move32();
    1366             :         BASOP_SATURATE_WARNING_ON_EVS
    1367      381329 :         *sf_energyLookahead = sm;
    1368      381329 :         move16();
    1369             : 
    1370      381329 :         return;
    1371             :     }
    1372             : 
    1373             : 
    1374       16095 :     *energyHF = 0x40000000;
    1375       16095 :     move32();
    1376       16095 :     *energyHF_Exp = 17;
    1377       16095 :     move16();
    1378             : }
    1379             : 
    1380             : 
    1381             : Word16
    1382          20 : CLDFB_getNumChannels( Word32 sampleRate )
    1383             : {
    1384             : 
    1385          20 :     Word16 nChannels = 0;
    1386          20 :     move16();
    1387             : 
    1388             : 
    1389          20 :     SWITCH( sampleRate )
    1390             :     {
    1391           7 :         case 48000:
    1392           7 :             move16();
    1393           7 :             nChannels = 60;
    1394           7 :             BREAK;
    1395           2 :         case 32000:
    1396           2 :             move16();
    1397           2 :             nChannels = 40;
    1398           2 :             BREAK;
    1399           0 :         case 25600:
    1400           0 :             move16();
    1401           0 :             nChannels = 32;
    1402           0 :             BREAK;
    1403           8 :         case 16000:
    1404           8 :             move16();
    1405           8 :             nChannels = 20;
    1406           8 :             BREAK;
    1407           3 :         case 12800:
    1408           3 :             move16();
    1409           3 :             nChannels = 16;
    1410           3 :             BREAK;
    1411           0 :         case 8000:
    1412           0 :             move16();
    1413           0 :             nChannels = 10;
    1414           0 :             BREAK;
    1415             :     }
    1416             : 
    1417          20 :     return ( nChannels );
    1418             : }
    1419             : 
    1420             : /*-------------------------------------------------------------------*
    1421             :  * cldfb_get_memory_length()
    1422             :  *
    1423             :  * Return length of filter state for recovery
    1424             :  *--------------------------------------------------------------------*/
    1425             : static Word16
    1426         285 : cldfb_get_memory_length( HANDLE_CLDFB_FILTER_BANK hs )
    1427             : {
    1428         285 :     IF( EQ_16( hs->type, CLDFB_ANALYSIS ) )
    1429             :     {
    1430         190 :         return ( i_mult( hs->no_channels, STATE_BUFFER_SIZE ) );
    1431             :     }
    1432             :     ELSE
    1433             :     {
    1434          95 :         return ( i_mult( hs->no_channels, ( 9 * 2 ) ) );
    1435             :     }
    1436             : }
    1437             : 
    1438             : /*-------------------------------------------------------------------*
    1439             :  * GetEnergyCldfb()
    1440             :  *
    1441             :  * Remove handle
    1442             :  *--------------------------------------------------------------------*/
    1443          15 : void deleteCldfb( HANDLE_CLDFB_FILTER_BANK *h_cldfb ) /* i: cldfb handle */
    1444             : {
    1445          15 :     IF( *h_cldfb != NULL )
    1446             :     {
    1447          15 :         IF( ( *h_cldfb )->FilterStates != NULL )
    1448             :         {
    1449          15 :             free( ( *h_cldfb )->FilterStates );
    1450             :         }
    1451          15 :         free( *h_cldfb );
    1452             :     }
    1453          15 :     *h_cldfb = NULL;
    1454          15 : }
    1455             : 
    1456             : 
    1457             : /*-------------------------------------------------------------------*
    1458             :  * cldfb_init_proto_and_twiddles()
    1459             :  *
    1460             :  * Initializes rom pointer
    1461             :  *--------------------------------------------------------------------*/
    1462             : static void
    1463          25 : cldfb_init_proto_and_twiddles( HANDLE_CLDFB_FILTER_BANK hs ) /* i: cldfb handle */
    1464             : {
    1465             : 
    1466             :     /*find appropriate set of rotVecs*/
    1467          25 :     SWITCH( hs->no_channels )
    1468             :     {
    1469           0 :         case 10:
    1470             : 
    1471           0 :             hs->rRotVctr = rRotVectr_10;
    1472           0 :             hs->iRotVctr = iRotVectr_10;
    1473           0 :             hs->synGain = cldfb_synGain[0];
    1474           0 :             move16();
    1475           0 :             hs->p_filter = cldfb_protoFilter_2_5ms[0];
    1476           0 :             hs->scale = cldfb_scale_2_5ms[0];
    1477           0 :             move16();
    1478           0 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1479             :             {
    1480           0 :                 hs->synScalefactor = add( cldfb_synScale[0], hs->filterScale );
    1481           0 :                 move16();
    1482             :             }
    1483             :             ELSE
    1484             :             {
    1485           0 :                 hs->anaScalefactor = add( cldfb_anaScale[0], hs->filterScale );
    1486           0 :                 move16();
    1487             :             }
    1488           0 :             BREAK;
    1489             : 
    1490           6 :         case 16:
    1491           6 :             hs->rRotVctr = rRotVectr_16;
    1492           6 :             hs->iRotVctr = iRotVectr_16;
    1493           6 :             hs->synGain = cldfb_synGain[1];
    1494           6 :             move16();
    1495           6 :             hs->p_filter = cldfb_protoFilter_2_5ms[1];
    1496           6 :             hs->scale = cldfb_scale_2_5ms[1];
    1497           6 :             move16();
    1498             :             {
    1499           6 :                 hs->anaScalefactor = add( cldfb_anaScale[1], hs->filterScale );
    1500           6 :                 move16();
    1501             :             }
    1502           6 :             BREAK;
    1503             : 
    1504          10 :         case 20:
    1505          10 :             hs->rRotVctr = rRotVectr_20;
    1506          10 :             hs->iRotVctr = iRotVectr_20;
    1507          10 :             hs->synGain = cldfb_synGain[2];
    1508          10 :             move16();
    1509          10 :             hs->p_filter = cldfb_protoFilter_2_5ms[2];
    1510          10 :             hs->scale = cldfb_scale_2_5ms[2];
    1511          10 :             move16();
    1512          10 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1513             :             {
    1514           3 :                 hs->synScalefactor = add( cldfb_synScale[2], hs->filterScale );
    1515           3 :                 move16();
    1516             :             }
    1517             :             ELSE
    1518             :             {
    1519           7 :                 hs->anaScalefactor = add( cldfb_anaScale[2], hs->filterScale );
    1520           7 :                 move16();
    1521             :             }
    1522          10 :             BREAK;
    1523             : 
    1524           0 :         case 32:
    1525           0 :             hs->rRotVctr = rRotVectr_32;
    1526           0 :             hs->iRotVctr = iRotVectr_32;
    1527           0 :             hs->synGain = cldfb_synGain[3];
    1528           0 :             move16();
    1529           0 :             hs->p_filter = cldfb_protoFilter_2_5ms[3];
    1530           0 :             hs->scale = cldfb_scale_2_5ms[3];
    1531           0 :             move16();
    1532             :             {
    1533           0 :                 hs->anaScalefactor = add( cldfb_anaScale[3], hs->filterScale );
    1534           0 :                 move16();
    1535             :             }
    1536           0 :             BREAK;
    1537             : 
    1538           2 :         case 40:
    1539           2 :             hs->rRotVctr = rRotVectr_40;
    1540           2 :             hs->iRotVctr = iRotVectr_40;
    1541           2 :             hs->synGain = cldfb_synGain[4];
    1542           2 :             move16();
    1543           2 :             hs->p_filter = cldfb_protoFilter_2_5ms[4];
    1544           2 :             hs->scale = cldfb_scale_2_5ms[4];
    1545           2 :             move16();
    1546           2 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1547             :             {
    1548           1 :                 hs->synScalefactor = add( cldfb_synScale[4], hs->filterScale );
    1549           1 :                 move16();
    1550             :             }
    1551             :             ELSE
    1552             :             {
    1553           1 :                 hs->anaScalefactor = add( cldfb_anaScale[4], hs->filterScale );
    1554           1 :                 move16();
    1555             :             }
    1556           2 :             BREAK;
    1557             : 
    1558           7 :         case 60:
    1559           7 :             hs->rRotVctr = rRotVectr_60;
    1560           7 :             hs->iRotVctr = iRotVectr_60;
    1561           7 :             hs->synGain = cldfb_synGain[5];
    1562           7 :             move16();
    1563           7 :             hs->p_filter = cldfb_protoFilter_2_5ms[5];
    1564           7 :             hs->scale = cldfb_scale_2_5ms[5];
    1565           7 :             move16();
    1566           7 :             IF( EQ_16( hs->type, CLDFB_SYNTHESIS ) )
    1567             :             {
    1568           2 :                 hs->synScalefactor = add( cldfb_synScale[5], hs->filterScale );
    1569           2 :                 move16();
    1570             :             }
    1571             :             ELSE
    1572             :             {
    1573           5 :                 hs->anaScalefactor = add( cldfb_anaScale[5], hs->filterScale );
    1574           5 :                 move16();
    1575             :             }
    1576           7 :             BREAK;
    1577             :     }
    1578          25 : }
    1579             : 
    1580             : 
    1581             : #define CLDFB_MEM_EXPONENTS ( CLDFB_NO_COL_MAX + 9 )
    1582             : 
    1583             : /*-------------------------------------------------------------------*
    1584             :  * cldfb_save_memory()
    1585             :  *
    1586             :  * Save the memory of filter; to be restored with cldfb_restore_memory()
    1587             :  *--------------------------------------------------------------------*/
    1588             : ivas_error
    1589          72 : cldfb_save_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i: cldfb handle */
    1590             : {
    1591          72 :     test();
    1592          72 :     IF( hs->memory != NULL || hs->memory_length != 0 )
    1593             :     {
    1594             :         /* memory already stored; Free memory first */
    1595           0 :         return IVAS_ERR_OK;
    1596             :     }
    1597          72 :     hs->memory_length = cldfb_get_memory_length( hs );
    1598          72 :     move16();
    1599          72 :     hs->memory = (Word16 *) calloc( hs->memory_length + CLDFB_MEM_EXPONENTS + 1, sizeof( Word16 ) );
    1600             : 
    1601             :     /* save the memory */
    1602          72 :     Copy( hs->FilterStates, hs->memory, hs->memory_length );
    1603          72 :     Copy( hs->FilterStates_e, hs->memory + hs->memory_length, CLDFB_MEM_EXPONENTS );
    1604          72 :     hs->memory[hs->memory_length + CLDFB_MEM_EXPONENTS] = hs->FilterStates_eg;
    1605          72 :     move16();
    1606          72 :     IF( hs->memory == NULL )
    1607             :     {
    1608           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB\n" );
    1609             :     }
    1610          72 :     return IVAS_ERR_OK;
    1611             : }
    1612             : 
    1613             : 
    1614             : /*-------------------------------------------------------------------*
    1615             :  * cldfb_restore_memory()
    1616             :  *
    1617             :  * Restores the memory of filter; memory to be save by cldfb_save_memory()
    1618             :  *--------------------------------------------------------------------*/
    1619          72 : void cldfb_restore_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i/o: cldfb handle */
    1620             : 
    1621             : {
    1622             :     Word16 size;
    1623             : 
    1624             : 
    1625          72 :     size = cldfb_get_memory_length( hs );
    1626             : 
    1627             :     /* read the memory */
    1628          72 :     Copy( hs->memory, hs->FilterStates, hs->memory_length );
    1629          72 :     Copy( hs->memory + hs->memory_length, hs->FilterStates_e, CLDFB_MEM_EXPONENTS );
    1630          72 :     hs->FilterStates_eg = hs->memory[hs->memory_length + CLDFB_MEM_EXPONENTS];
    1631          72 :     move16();
    1632             : 
    1633             : 
    1634             :     /* adjust sample rate if it was changed in the meanwhile */
    1635          72 :     IF( NE_16( hs->memory_length, size ) )
    1636             :     {
    1637           0 :         lerp( hs->FilterStates, hs->FilterStates, size, hs->memory_length );
    1638             :     }
    1639             : 
    1640          72 :     hs->memory_length = 0;
    1641          72 :     free( hs->memory );
    1642          72 :     hs->memory = NULL;
    1643             : 
    1644          72 :     return;
    1645             : }
    1646             : 
    1647             : /*-------------------------------------------------------------------*
    1648             :  * cldfb_reset_memory()
    1649             :  *
    1650             :  * Resets the memory of filter.
    1651             :  *--------------------------------------------------------------------*/
    1652         141 : void cldfb_reset_memory( HANDLE_CLDFB_FILTER_BANK hs ) /* i/o: cldfb handle */
    1653             : {
    1654             :     Word16 length;
    1655             : 
    1656         141 :     length = cldfb_get_memory_length( hs );
    1657             :     /* erase the memory */
    1658         141 :     set16_fx( hs->FilterStates, 0, length );
    1659         141 :     set16_fx( hs->FilterStates_e, 0, sizeof( hs->FilterStates_e ) / sizeof( hs->FilterStates_e[0] ) );
    1660         141 :     hs->FilterStates_eg = 0;
    1661         141 :     move16();
    1662         141 :     return;
    1663             : }

Generated by: LCOV version 1.14