diff --git a/lib_com/cldfb.c b/lib_com/cldfb.c index ed4aa63b5d72df06c7dbf8685a143c6216c75797..fd09c1c46b6f8cac53fe8cd0d84364ff2d21507a 100644 --- a/lib_com/cldfb.c +++ b/lib_com/cldfb.c @@ -258,6 +258,215 @@ void cldfbAnalysis_ivas( return; } +#ifdef IVAS_FLOAT_FIXED +void cldfbAnalysis_ivas_fx( + const Word32 *timeIn_fx, /* i : time buffer Qx */ + Word32 **realBuffer_fx, /* o : real value buffer Qx - 5*/ + Word32 **imagBuffer_fx, /* o : imag value buffer QX - 5*/ + const Word16 samplesToProcess, /* i : samples to process */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filterbank state */ +) +{ + Word16 i, k; + Word16 L2, M1, M2, M4; + Word16 no_col = h_cldfb->no_col; + + Word32 r1_fx, r2_fx, rr12_fx, ir12_fx; + Word32 i1_fx, i2_fx, ri12_fx, ii12_fx; + Word32 rBuffer_fx[2 * CLDFB_NO_CHANNELS_MAX]; + Word32 iBuffer_fx[2 * CLDFB_NO_CHANNELS_MAX]; + const Word32 *rot_vctr_re_fx; + const Word32 *rot_vctr_im_fx; + const Word16 *ptr_pf_fx; + Word16 ptr_pf_sf; + Word32 *timeBuffer_fx, buffer_fx[( CLDFB_NO_CHANNELS_MAX * CLDFB_NO_COL_MAX ) + ( 9 * CLDFB_NO_CHANNELS_MAX )]; + Word16 offset, frameSize; + + offset = sub( h_cldfb->p_filter_length, h_cldfb->no_channels ); + frameSize = i_mult( h_cldfb->no_channels, h_cldfb->no_col ); + + assert( h_cldfb->prototype == CLDFB_PROTOTYPE_1_25MS ); + /* prepare input buffer */ + timeBuffer_fx = buffer_fx; + Copy32( h_cldfb->cldfb_state_fx, timeBuffer_fx, offset ); + + IF( GT_16( samplesToProcess, -1 ) ) + { + Copy32( timeIn_fx, timeBuffer_fx + offset, samplesToProcess ); + set32_fx( timeBuffer_fx + offset + samplesToProcess, 0, sub( frameSize, samplesToProcess ) ); + } + ELSE + { + Copy32( timeIn_fx, timeBuffer_fx + offset, frameSize ); + } + + /* only process needed cols */ + IF( GT_16( samplesToProcess, -1 ) ) + { + no_col = min( no_col, div_l( sub( add( samplesToProcess, h_cldfb->no_channels ), 1 ), shr( h_cldfb->no_channels, 1 ) ) ); + } + + M1 = h_cldfb->no_channels; + M2 = shr( M1, 1 ); + M4 = shr( M1, 2 ); + L2 = shl( M1, 1 ); + + IF( M2 & 1 ) + { + M4 = add( M4, 1 ); + } + + rot_vctr_re_fx = h_cldfb->rot_vec_ana_re_fx; + rot_vctr_im_fx = h_cldfb->rot_vec_ana_im_fx; + + ptr_pf_fx = h_cldfb->p_filter; + ptr_pf_sf = h_cldfb->p_filter_sf; + move16(); + + FOR( i = 0; i < no_col; i++ ) + { + FOR( k = 0; k < M4; k++ ) + { + /* prototype filter */ + r1_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 0 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 1 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 2 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 3 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 4 * L2 )] ) ); // Qx + + r2_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 - M2 + ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 - M2 + ( 2 * k ) + 0 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 + ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 - M2 + ( 2 * k ) + 1 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 + ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 - M2 + ( 2 * k ) + 2 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 + ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 - M2 + ( 2 * k ) + 3 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 + ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 - M2 + ( 2 * k ) + 4 * L2 )] ) ); // Qx + + i1_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 0 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 1 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 2 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 3 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 4 * L2 )] ) ); // Qx + + i2_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 - 1 - ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 - 3 * M2 - 1 - ( 2 * k ) + 0 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 - 1 - ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 - 3 * M2 - 1 - ( 2 * k ) + 1 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 - 1 - ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 - 3 * M2 - 1 - ( 2 * k ) + 2 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 - 1 - ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 - 3 * M2 - 1 - ( 2 * k ) + 3 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 - 1 - ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 - 3 * M2 - 1 - ( 2 * k ) + 4 * L2 )] ) ); // Qx + + r1_fx = Mpy_32_16_1( r1_fx, ptr_pf_sf ); // Qx - 1 + r2_fx = Mpy_32_16_1( r2_fx, ptr_pf_sf ); // Qx - 1 + i1_fx = Mpy_32_16_1( i1_fx, ptr_pf_sf ); // Qx - 1 + i2_fx = Mpy_32_16_1( i2_fx, ptr_pf_sf ); // Qx - 1 + + /* folding + pre modulation of DST IV */ + rr12_fx = L_sub( r1_fx, r2_fx ); // Qx - 1 + ri12_fx = L_negate( L_add( i1_fx, i2_fx ) ); // Qx - 1 + // cplxMult( &rBuffer_fx[2 * k], &rBuffer_fx[2 * k + 1], rr12_fx, ri12_fx, rot_vctr_re_fx[k], rot_vctr_im_fx[k] ); + rBuffer_fx[2 * k] = L_sub( Mpy_32_32( rr12_fx, rot_vctr_re_fx[k] ), Mpy_32_32( ri12_fx, rot_vctr_im_fx[k] ) ); // Qx - 3 + move32(); + rBuffer_fx[2 * k + 1] = L_add( Mpy_32_32( rr12_fx, rot_vctr_im_fx[k] ), Mpy_32_32( ri12_fx, rot_vctr_re_fx[k] ) ); // Qx - 3 + move32(); + + /* folding + pre modulation of DCT IV */ + ir12_fx = L_add( r1_fx, r2_fx ); // Qx - 1 + ii12_fx = L_sub( i1_fx, i2_fx ); // Qx - 1 + // cplxMult( &iBuffer_fx[2 * k], &iBuffer_fx[2 * k + 1], ir12_fx, ii12_fx, rot_vctr_re_fx[k], rot_vctr_im_fx[k] ); + iBuffer_fx[2 * k] = L_sub( Mpy_32_32( ir12_fx, rot_vctr_re_fx[k] ), Mpy_32_32( ii12_fx, rot_vctr_im_fx[k] ) ); // Qx - 3 + move32(); + iBuffer_fx[2 * k + 1] = L_add( Mpy_32_32( ir12_fx, rot_vctr_im_fx[k] ), Mpy_32_32( ii12_fx, rot_vctr_re_fx[k] ) ); // Qx - 3 + move32(); + } + + FOR( k = M4; k < M2; k++ ) + { + /* prototype filter */ + r1_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 0 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 1 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 2 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 3 * L2 )] ) ); // Qx + r1_fx = L_sub( r1_fx, Mpy_32_16_1( timeBuffer_fx[L2 - M2 - 1 - ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 - M2 - 1 - ( 2 * k ) + 4 * L2 )] ) ); // Qx + + r2_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 - 5 * M2 + ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 - 5 * M2 + ( 2 * k ) + 0 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 5 * M2 + ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 - 5 * M2 + ( 2 * k ) + 1 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 5 * M2 + ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 - 5 * M2 + ( 2 * k ) + 2 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 5 * M2 + ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 - 5 * M2 + ( 2 * k ) + 3 * L2 )] ) ); // Qx + r2_fx = L_sub( r2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 5 * M2 + ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 - 5 * M2 + ( 2 * k ) + 4 * L2 )] ) ); // Qx + + i1_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 + M2 - 1 - ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 + M2 - 1 - ( 2 * k ) + 0 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 + M2 - 1 - ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 + M2 - 1 - ( 2 * k ) + 1 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 + M2 - 1 - ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 + M2 - 1 - ( 2 * k ) + 2 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 + M2 - 1 - ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 + M2 - 1 - ( 2 * k ) + 3 * L2 )] ) ); // Qx + i1_fx = L_sub( i1_fx, Mpy_32_16_1( timeBuffer_fx[L2 + M2 - 1 - ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 + M2 - 1 - ( 2 * k ) + 4 * L2 )] ) ); // Qx + + i2_fx = L_sub( 0, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 0 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 0 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 1 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 1 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 2 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 2 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 3 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 3 * L2 )] ) ); // Qx + i2_fx = L_sub( i2_fx, Mpy_32_16_1( timeBuffer_fx[L2 - 3 * M2 + ( 2 * k ) + 4 * L2], ptr_pf_fx[( L2 - 3 * M2 + ( 2 * k ) + 4 * L2 )] ) ); // Qx + + r1_fx = Mpy_32_16_1( r1_fx, ptr_pf_sf ); // Qx - 1 + r2_fx = Mpy_32_16_1( r2_fx, ptr_pf_sf ); // Qx - 1 + i1_fx = Mpy_32_16_1( i1_fx, ptr_pf_sf ); // Qx - 1 + i2_fx = Mpy_32_16_1( i2_fx, ptr_pf_sf ); // Qx - 1 + + /* folding + pre modulation of DST IV */ + rr12_fx = L_add( r1_fx, r2_fx ); // Qx - 1 + ri12_fx = L_sub( i1_fx, i2_fx ); // Qx - 1 + // cplxMult( &rBuffer_fx[2 * k], &rBuffer[2 * k + 1], rr12, ri12, rot_vctr_re[k], rot_vctr_im[k] ); + rBuffer_fx[2 * k] = L_sub( Mpy_32_32( rr12_fx, rot_vctr_re_fx[k] ), Mpy_32_32( ri12_fx, rot_vctr_im_fx[k] ) ); // Qx - 3 + move32(); + rBuffer_fx[2 * k + 1] = L_add( Mpy_32_32( rr12_fx, rot_vctr_im_fx[k] ), Mpy_32_32( ri12_fx, rot_vctr_re_fx[k] ) ); // Qx - 3 + move32(); + + /* folding + pre modulation of DCT IV */ + ir12_fx = L_sub( r1_fx, r2_fx ); // Qx - 1 + ii12_fx = L_add( i1_fx, i2_fx ); // Qx - 1 + // cplxMult( &iBuffer[2 * k], &iBuffer[2 * k + 1], ir12, ii12, rot_vctr_re[k], rot_vctr_im[k] ); + iBuffer_fx[2 * k] = L_sub( Mpy_32_32( ir12_fx, rot_vctr_re_fx[k] ), Mpy_32_32( ii12_fx, rot_vctr_im_fx[k] ) ); // Qx - 3 + move32(); + iBuffer_fx[2 * k + 1] = L_add( Mpy_32_32( ir12_fx, rot_vctr_im_fx[k] ), Mpy_32_32( ii12_fx, rot_vctr_re_fx[k] ) ); // Qx - 3 + move32(); + } + + /* FFT of DST IV */ + fft_cldfb_fx( rBuffer_fx, M2 ); + + + /* post modulation of DST IV */ + FOR( k = 0; k < M2; k++ ) + { + // cplxMult( &realBuffer[i][M1 - 1 - ( 2 * k )], &realBuffer[i][2 * k], rBuffer[2 * k], rBuffer[2 * k + 1], rot_vctr_re[k], rot_vctr_im[k] ); + realBuffer_fx[i][M1 - 1 - ( 2 * k )] = L_sub( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_re_fx[k] ), Mpy_32_32( rBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ) ); // Qx - 5 + move32(); + realBuffer_fx[i][2 * k] = L_add( Mpy_32_32( rBuffer_fx[2 * k], rot_vctr_im_fx[k] ), Mpy_32_32( rBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ) ); // Qx - 5 + move32(); + } + + /* FFT of DCT IV */ + fft_cldfb_fx( iBuffer_fx, M2 ); + + + /* post modulation of DCT IV */ + FOR( k = 0; k < M2; k++ ) + { + /* do it inplace */ + // cplxMult( &imagBuffer[i][2 * k], &imagBuffer[i][M1 - 1 - ( 2 * k )], iBuffer[2 * k], iBuffer[2 * k + 1], rot_vctr_re[k], rot_vctr_im[k] ); + imagBuffer_fx[i][2 * k] = L_sub( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_re_fx[k] ), Mpy_32_32( iBuffer_fx[2 * k + 1], rot_vctr_im_fx[k] ) ); // QX - 5 + move32(); + imagBuffer_fx[i][M1 - 1 - ( 2 * k )] = L_add( Mpy_32_32( iBuffer_fx[2 * k], rot_vctr_im_fx[k] ), Mpy_32_32( iBuffer_fx[2 * k + 1], rot_vctr_re_fx[k] ) ); // Qx - 5 + move32(); + } + + timeBuffer_fx += L2 * 5; + timeBuffer_fx += h_cldfb->no_channels - h_cldfb->p_filter_length; + } + + /* update memory */ + Copy32( buffer_fx + frameSize, h_cldfb->cldfb_state_fx, offset ); + + return; +} +#endif + /*-------------------------------------------------------------------* * cldfbAnalysis_ts_ivas() * @@ -899,6 +1108,215 @@ void cldfbSynthesis_ivas( return; } +#ifdef IVAS_FLOAT_FIXED +void cldfbSynthesis_ivas_fx( + Word32 **realBuffer_fx, /* i : real values Qx*/ + Word32 **imagBuffer_fx, /* i : imag values Qx*/ + Word32 *timeOut_fx, /* o : output time domain samples Qx - 1*/ + const Word16 samplesToProcess, /* i : number of processed samples */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filter bank state */ +) +{ + Word16 i; + Word16 k; + Word16 L2; + Word16 M1; + Word16 M2; + Word16 M41; + Word16 M42; + Word16 Mz; + + Word32 rBuffer_fx[2 * CLDFB_NO_CHANNELS_MAX]; + Word32 iBuffer_fx[2 * CLDFB_NO_CHANNELS_MAX]; + const Word32 *rot_vctr_re_fx; + const Word32 *rot_vctr_im_fx; + const Word32 *rot_vctr_delay_re_fx; + const Word32 *rot_vctr_delay_im_fx; + Word32 rr12_fx, ir12_fx; + Word32 ri12_fx, ii12_fx; + + Word32 *synthesisBuffer_fx, buffer_fx[( CLDFB_NO_CHANNELS_MAX * CLDFB_NO_COL_MAX ) + ( 10 * CLDFB_NO_CHANNELS_MAX )]; + Word32 new_samples_fx[2 * CLDFB_NO_CHANNELS_MAX]; + + Word32 *ptr_time_out_fx; + const Word16 *p_filter; + Word16 p_filter_sf; + + Word32 accu0, accu1, accu2, accu3, accu4; + Word16 no_col = h_cldfb->no_col; + move16(); + + M1 = h_cldfb->no_channels; + L2 = shl( M1, 1 ); + M2 = shr( M1, 1 ); + M41 = shr( M2, 1 ); + M42 = sub( M2, M41 ); + Mz = sub( M1, h_cldfb->bandsToZero ); + + /* only process needed cols */ + IF( GT_16( samplesToProcess, -1 ) ) + { + no_col = min( no_col, ( samplesToProcess + h_cldfb->no_channels - 1 ) / h_cldfb->no_channels ); + move16(); + } + + rot_vctr_re_fx = h_cldfb->rot_vec_syn_re_fx; + rot_vctr_im_fx = h_cldfb->rot_vec_syn_im_fx; + + rot_vctr_delay_re_fx = h_cldfb->rot_vec_syn_delay_re_fx; + rot_vctr_delay_im_fx = h_cldfb->rot_vec_syn_delay_im_fx; + + synthesisBuffer_fx = buffer_fx; + Copy32( h_cldfb->cldfb_state_fx, synthesisBuffer_fx + ( M1 * no_col ), h_cldfb->p_filter_length ); + + p_filter = h_cldfb->p_filter; + p_filter_sf = h_cldfb->p_filter_sf; + move16(); + ptr_time_out_fx = timeOut_fx; + + /*synthesisBuffer += M1 * h_cldfb->no_col;*/ + synthesisBuffer_fx += M1 * no_col; + + FOR( k = 0; k < no_col; k++ ) + { + IF( EQ_16( (Word16) h_cldfb->prototype, (Word16) CLDFB_PROTOTYPE_5_00MS ) ) + { + /* rotation due to delay*/ + /*if(h_cldfb->ds != M1)*/ + IF( rot_vctr_delay_re_fx != NULL ) + { + FOR( i = 0; i < M1; i++ ) + { + Word32 cplx_aux; + /* delay */ + /*cplxMult(&rBuffer[i], &iBuffer[i], realBuffer[k][i], imagBuffer[k][i], cos((EVS_PI/M1)*(i+0.5)*(-(h_cldfb->ds-M1)*0.5)), + sin((EVS_PI/M1)*(i+0.5)*(-(h_cldfb->ds-M1)*0.5)));*/ + /*cplxMult(&rBuffer[i], &iBuffer[i], realBuffer[k][i], imagBuffer[k][i], rot_vctr_delay_re[i], rot_vctr_delay_im[i]);*/ + /*cplxMult(&realBuffer[k][i], &imagBuffer[k][i], realBuffer[k][i], imagBuffer[k][i], rot_vctr_delay_re[i], rot_vctr_delay_im[i]);*/ + cplx_aux = L_sub( Mpy_32_32( realBuffer_fx[k][i], rot_vctr_delay_re_fx[i] ), Mpy_32_32( imagBuffer_fx[k][i], rot_vctr_delay_im_fx[i] ) ); // Qx + imagBuffer_fx[k][i] = L_add( Mpy_32_32( realBuffer_fx[k][i], rot_vctr_delay_im_fx[i] ), Mpy_32_32( imagBuffer_fx[k][i], rot_vctr_delay_re_fx[i] ) ); + move32(); + realBuffer_fx[k][i] = cplx_aux; + move32(); + /*realBuffer[k][i] = rBuffer[i];*/ + /*imagBuffer[k][i] = iBuffer[i];*/ + } + } + } + FOR( i = Mz; i < M1; i++ ) + { + realBuffer_fx[k][i] = L_deposit_l( 0 ); + move32(); + imagBuffer_fx[k][i] = L_deposit_l( 0 ); + move32(); + } + + FOR( i = 0; i < M2; i++ ) + { + /* pre modulation of DST IV */ + /*cplxMult(&rBuffer[2*i], &rBuffer[2*i+1], realBuffer[k][2*i], realBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]);*/ + rBuffer_fx[2 * i] = L_sub( Mpy_32_32( realBuffer_fx[k][2 * i], rot_vctr_re_fx[i] ), Mpy_32_32( realBuffer_fx[k][M1 - 1 - 2 * i], rot_vctr_im_fx[i] ) ); // Qx + move32(); + rBuffer_fx[2 * i + 1] = L_add( Mpy_32_32( realBuffer_fx[k][2 * i], rot_vctr_im_fx[i] ), Mpy_32_32( realBuffer_fx[k][M1 - 1 - 2 * i], rot_vctr_re_fx[i] ) ); // Qx + move32(); + + /* pre modulation of DCT IV */ + /*cplxMult(&iBuffer[2*i], &iBuffer[2*i+1],-imagBuffer[k][2*i], imagBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]);*/ + iBuffer_fx[2 * i] = L_sub( Mpy_32_32( ( L_negate( imagBuffer_fx[k][2 * i] ) ), rot_vctr_re_fx[i] ), Mpy_32_32( imagBuffer_fx[k][M1 - 1 - 2 * i], rot_vctr_im_fx[i] ) ); // Qx + move32(); + iBuffer_fx[2 * i + 1] = L_add( Mpy_32_32( ( L_negate( imagBuffer_fx[k][2 * i] ) ), rot_vctr_im_fx[i] ), Mpy_32_32( imagBuffer_fx[k][M1 - 1 - 2 * i], rot_vctr_re_fx[i] ) ); // Qx + move32(); + } + + /* FFT of DST IV */ + fft_cldfb_fx( rBuffer_fx, M2 ); + + /* FFT of DCT IV */ + fft_cldfb_fx( iBuffer_fx, M2 ); + + /* folding */ + FOR( i = 0; i < M41; i++ ) + { + /* post modulation of DST IV */ + rr12_fx = L_sub( Mpy_32_32( rBuffer_fx[M1 - 2 - 2 * i], rot_vctr_re_fx[M2 - 1 - i] ), Mpy_32_32( rBuffer_fx[M1 - 1 - 2 * i], rot_vctr_im_fx[M2 - 1 - i] ) ); // Qx + ri12_fx = L_add( Mpy_32_32( rBuffer_fx[M1 - 2 - 2 * i], rot_vctr_im_fx[M2 - 1 - i] ), Mpy_32_32( rBuffer_fx[M1 - 1 - 2 * i], rot_vctr_re_fx[M2 - 1 - i] ) ); // Qx + + /* post modulation of DCT IV */ + ir12_fx = L_sub( Mpy_32_32( iBuffer_fx[M1 - 2 - 2 * i], rot_vctr_re_fx[M2 - 1 - i] ), Mpy_32_32( iBuffer_fx[M1 - 1 - 2 * i], rot_vctr_im_fx[M2 - 1 - i] ) ); // Qx + ii12_fx = L_add( Mpy_32_32( iBuffer_fx[M1 - 2 - 2 * i], rot_vctr_im_fx[M2 - 1 - i] ), Mpy_32_32( iBuffer_fx[M1 - 1 - 2 * i], rot_vctr_re_fx[M2 - 1 - i] ) ); // Qx + + new_samples_fx[M1 + M2 + 1 + 2 * i] = L_negate( L_add( rr12_fx, ii12_fx ) ); // Qx + move32(); + new_samples_fx[M2 - 2 - 2 * i] = L_negate( L_add( ri12_fx, ir12_fx ) ); // Qx + move32(); + + new_samples_fx[M1 + M2 - 2 - 2 * i] = L_sub( rr12_fx, ii12_fx ); // Qx + move32(); + new_samples_fx[M2 + 1 + 2 * i] = L_sub( ir12_fx, ri12_fx ); // Qx + move32(); + } + + FOR( i = 0; i < M42; i++ ) + { + /* post modulation of DST IV */ + rr12_fx = L_sub( Mpy_32_32( rBuffer_fx[2 * i], rot_vctr_re_fx[i] ), Mpy_32_32( rBuffer_fx[2 * i + 1], rot_vctr_im_fx[i] ) ); // Qx + ri12_fx = L_add( Mpy_32_32( rBuffer_fx[2 * i], rot_vctr_im_fx[i] ), Mpy_32_32( rBuffer_fx[2 * i + 1], rot_vctr_re_fx[i] ) ); // Qx + + /* post modulation of DCT IV */ + ir12_fx = L_sub( Mpy_32_32( iBuffer_fx[2 * i], rot_vctr_re_fx[i] ), Mpy_32_32( iBuffer_fx[2 * i + 1], rot_vctr_im_fx[i] ) ); // Qx + ii12_fx = L_add( Mpy_32_32( iBuffer_fx[2 * i], rot_vctr_im_fx[i] ), Mpy_32_32( iBuffer_fx[2 * i + 1], rot_vctr_re_fx[i] ) ); // Qx + + new_samples_fx[M1 + M2 + 2 * i] = L_add( ri12_fx, ir12_fx ); // Qx + move32(); + new_samples_fx[M2 - 1 - 2 * i] = L_add( rr12_fx, ii12_fx ); // Qx + move32(); + + new_samples_fx[M1 + M2 - 1 - 2 * i] = L_sub( ir12_fx, ri12_fx ); // Qx + move32(); + new_samples_fx[M2 + 2 * i] = L_sub( rr12_fx, ii12_fx ); // Qx + move32(); + } + + /* synthesis prototype filter */ + FOR( i = 0; i < L2; i++ ) + { + accu0 = L_add( synthesisBuffer_fx[0 * L2 + i], Mpy_32_16_1( Mpy_32_16_1( new_samples_fx[L2 - 1 - i], p_filter[( 0 * L2 + i )] ), p_filter_sf ) ); // Qx - 1 + accu1 = L_add( synthesisBuffer_fx[1 * L2 + i], Mpy_32_16_1( Mpy_32_16_1( new_samples_fx[L2 - 1 - i], p_filter[( 1 * L2 + i )] ), p_filter_sf ) ); // Qx - 1 + accu2 = L_add( synthesisBuffer_fx[2 * L2 + i], Mpy_32_16_1( Mpy_32_16_1( new_samples_fx[L2 - 1 - i], p_filter[( 2 * L2 + i )] ), p_filter_sf ) ); // Qx - 1 + accu3 = L_add( synthesisBuffer_fx[3 * L2 + i], Mpy_32_16_1( Mpy_32_16_1( new_samples_fx[L2 - 1 - i], p_filter[( 3 * L2 + i )] ), p_filter_sf ) ); // Qx - 1 + accu4 = L_add( synthesisBuffer_fx[4 * L2 + i], Mpy_32_16_1( Mpy_32_16_1( new_samples_fx[L2 - 1 - i], p_filter[( 4 * L2 + i )] ), p_filter_sf ) ); // Qx - 1 + + synthesisBuffer_fx[0 * L2 + i] = accu0; + move32(); + synthesisBuffer_fx[1 * L2 + i] = accu1; + move32(); + synthesisBuffer_fx[2 * L2 + i] = accu2; + move32(); + synthesisBuffer_fx[3 * L2 + i] = accu3; + move32(); + synthesisBuffer_fx[4 * L2 + i] = accu4; + move32(); + } + + FOR( i = 0; i < M1; i++ ) + { + ptr_time_out_fx[M1 - 1 - i] = synthesisBuffer_fx[4 * L2 + M1 + i]; + move32(); + } + + ptr_time_out_fx += M1; + + synthesisBuffer_fx -= M1; + + set32_fx( synthesisBuffer_fx, 0, M1 ); + } + + /* update memory */ + Copy32( buffer_fx, h_cldfb->cldfb_state_fx, h_cldfb->p_filter_length ); + + return; +} +#endif /*-------------------------------------------------------------------* * configureClfdb() @@ -923,7 +1341,30 @@ void configureCldfb_ivas( return; } +#ifdef IVAS_FLOAT_FIXED +void configureCldfb_ivas_fx( + HANDLE_CLDFB_FILTER_BANK h_cldfb, /* i/o: filter bank handle */ + const Word32 sampling_rate /* i : sampling rate */ +) +{ + + h_cldfb->no_col = CLDFB_NO_COL_MAX; + h_cldfb->bandsToZero = 0; + h_cldfb->nab = 0; + // h_cldfb->no_channels = (int16_t) ( sampling_rate * INV_CLDFB_BANDWIDTH + 0.5f ); + Word32 n_sampling_rate = sampling_rate * 2; + Word32 val = L_add( Mpy_32_16_1( n_sampling_rate, 41 ), 1 ); + val = L_shr( val, 1 ); + h_cldfb->no_channels = extract_l( val ); + + h_cldfb->p_filter_length = 10 * h_cldfb->no_channels; + + cldfb_init_proto_and_twiddles( h_cldfb ); + + return; +} +#endif /*-------------------------------------------------------------------* * openClfdb() * @@ -965,15 +1406,15 @@ ivas_error openCldfb_ivas( { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" ); } + set_f( hs->cldfb_state, 0.0f, buf_len ); #ifdef IVAS_FLOAT_FIXED if ( ( hs->cldfb_state_fx = (Word32 *) malloc( buf_len * sizeof( Word32 ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for CLDFB" ); } - set32_fx(hs->cldfb_state_fx, 0, buf_len); + set32_fx( hs->cldfb_state_fx, 0, buf_len ); #endif // IVAS_FLOAT_FIXED - set_f( hs->cldfb_state, 0.0f, buf_len ); *h_cldfb = hs; @@ -998,10 +1439,14 @@ void resampleCldfb_ivas( /* new settings */ configureCldfb_ivas( hs, newSamplerate ); + timeOffset = hs->p_filter_length - hs->no_channels; /*low complexity-resampling only stored previous samples that are needed for next frame modulation */ lerp_flt( hs->cldfb_state, hs->cldfb_state, timeOffset, timeOffsetold ); +#ifdef IVAS_FLOAT_FIXED + L_lerp_fx( hs->cldfb_state_fx, hs->cldfb_state_fx, timeOffset, timeOffsetold ); +#endif return; } @@ -1132,10 +1577,13 @@ void deleteCldfb_ivas( if ( hs->cldfb_state ) { free( hs->cldfb_state ); + } #ifdef IVAS_FLOAT_FIXED + if ( hs->cldfb_state_fx ) + { free( hs->cldfb_state_fx ); -#endif } +#endif free( hs ); *h_cldfb = NULL; @@ -1165,8 +1613,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_re_fx = rot_vec_ana_re_L10_fx; hs->rot_vec_ana_im_fx = rot_vec_ana_im_L10_fx; + hs->rot_vec_syn_re_fx = rot_vec_syn_re_L10_fx; + hs->rot_vec_syn_im_fx = rot_vec_syn_im_L10_fx; #endif - if ( hs->prototype == CLDFB_PROTOTYPE_1_25MS ) { hs->p_filter_flt = CLDFB80_10_flt; @@ -1180,7 +1629,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = NULL; hs->rot_vec_ana_delay_im_fx = NULL; - hs->p_filter_sf = (Word16)17036; + hs->rot_vec_syn_delay_im_fx = NULL; + hs->rot_vec_syn_delay_re_fx = NULL; + hs->p_filter_sf = (Word16) 17036; hs->p_filter = CLDFB80_10_fx; #endif } @@ -1197,7 +1648,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_ana_delay_im_fx = rot_vec_delay_im_LDQMF_fx; - hs->p_filter_sf = (Word16)15388; + hs->rot_vec_syn_delay_im_fx = rot_vec_delay_re_LDQMF_fx; + hs->rot_vec_syn_delay_re_fx = rot_vec_delay_im_LDQMF_fx; + hs->p_filter_sf = (Word16) 15388; hs->p_filter = LDQMF_10_fx; #endif } @@ -1211,6 +1664,8 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_re_fx = rot_vec_ana_re_L16_fx; hs->rot_vec_ana_im_fx = rot_vec_ana_im_L16_fx; + hs->rot_vec_syn_re_fx = rot_vec_syn_re_L16_fx; + hs->rot_vec_syn_im_fx = rot_vec_syn_im_L16_fx; #endif if ( hs->prototype == CLDFB_PROTOTYPE_1_25MS ) { @@ -1222,10 +1677,12 @@ static void cldfb_init_proto_and_twiddles( hs->rot_vec_ana_delay_im = NULL; hs->rot_vec_syn_delay_re = NULL; hs->rot_vec_syn_delay_im = NULL; -#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = NULL; hs->rot_vec_ana_delay_im_fx = NULL; - hs->p_filter_sf = (Word16)17051; + hs->rot_vec_syn_delay_im_fx = NULL; + hs->rot_vec_syn_delay_re_fx = NULL; + hs->p_filter_sf = (Word16) 17051; hs->p_filter = CLDFB80_16_fx; #endif } @@ -1242,7 +1699,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_ana_delay_im_fx = rot_vec_delay_im_LDQMF_fx; - hs->p_filter_sf = (Word16)15388; + hs->rot_vec_syn_delay_im_fx = rot_vec_delay_re_LDQMF_fx; + hs->rot_vec_syn_delay_re_fx = rot_vec_delay_im_LDQMF_fx; + hs->p_filter_sf = (Word16) 15388; hs->p_filter = LDQMF_16_fx; #endif } @@ -1256,6 +1715,8 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_re_fx = rot_vec_ana_re_L20_fx; hs->rot_vec_ana_im_fx = rot_vec_ana_im_L20_fx; + hs->rot_vec_syn_re_fx = rot_vec_syn_re_L20_fx; + hs->rot_vec_syn_im_fx = rot_vec_syn_im_L20_fx; #endif if ( hs->prototype == CLDFB_PROTOTYPE_1_25MS ) { @@ -1270,7 +1731,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = NULL; hs->rot_vec_ana_delay_im_fx = NULL; - hs->p_filter_sf = (Word16)17050; + hs->rot_vec_syn_delay_im_fx = NULL; + hs->rot_vec_syn_delay_re_fx = NULL; + hs->p_filter_sf = (Word16) 17050; hs->p_filter = CLDFB80_20_fx; #endif } @@ -1287,7 +1750,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_ana_delay_im_fx = rot_vec_delay_im_LDQMF_fx; - hs->p_filter_sf = (Word16)15390; + hs->rot_vec_syn_delay_im_fx = rot_vec_delay_re_LDQMF_fx; + hs->rot_vec_syn_delay_re_fx = rot_vec_delay_im_LDQMF_fx; + hs->p_filter_sf = (Word16) 15390; hs->p_filter = LDQMF_20_fx; #endif } @@ -1301,6 +1766,8 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_re_fx = rot_vec_ana_re_L30_fx; hs->rot_vec_ana_im_fx = rot_vec_ana_im_L30_fx; + hs->rot_vec_syn_re_fx = rot_vec_syn_re_L30_fx; + hs->rot_vec_syn_im_fx = rot_vec_syn_im_L30_fx; #endif if ( hs->prototype == CLDFB_PROTOTYPE_1_25MS ) { @@ -1315,7 +1782,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = NULL; hs->rot_vec_ana_delay_im_fx = NULL; - hs->p_filter_sf = (Word16)17051; + hs->rot_vec_syn_delay_im_fx = NULL; + hs->rot_vec_syn_delay_re_fx = NULL; + hs->p_filter_sf = (Word16) 17051; hs->p_filter = CLDFB80_30_fx; #endif } @@ -1332,7 +1801,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_ana_delay_im_fx = rot_vec_delay_im_LDQMF_fx; - hs->p_filter_sf = (Word16)15388; + hs->rot_vec_syn_delay_im_fx = rot_vec_delay_re_LDQMF_fx; + hs->rot_vec_syn_delay_re_fx = rot_vec_delay_im_LDQMF_fx; + hs->p_filter_sf = (Word16) 15388; hs->p_filter = LDQMF_30_fx; #endif } @@ -1346,6 +1817,8 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_re_fx = rot_vec_ana_re_L32_fx; hs->rot_vec_ana_im_fx = rot_vec_ana_im_L32_fx; + hs->rot_vec_syn_re_fx = rot_vec_syn_re_L32_fx; + hs->rot_vec_syn_im_fx = rot_vec_syn_im_L32_fx; #endif if ( hs->prototype == CLDFB_PROTOTYPE_1_25MS ) { @@ -1360,7 +1833,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = NULL; hs->rot_vec_ana_delay_im_fx = NULL; - hs->p_filter_sf = (Word16)17050; + hs->rot_vec_syn_delay_im_fx = NULL; + hs->rot_vec_syn_delay_re_fx = NULL; + hs->p_filter_sf = (Word16) 17050; hs->p_filter = CLDFB80_32_fx; #endif } @@ -1377,7 +1852,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_ana_delay_im_fx = rot_vec_delay_im_LDQMF_fx; - hs->p_filter_sf = (Word16)15392; + hs->rot_vec_syn_delay_im_fx = rot_vec_delay_re_LDQMF_fx; + hs->rot_vec_syn_delay_re_fx = rot_vec_delay_im_LDQMF_fx; + hs->p_filter_sf = (Word16) 15392; hs->p_filter = LDQMF_32_fx; #endif } @@ -1391,6 +1868,8 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_re_fx = rot_vec_ana_re_L40_fx; hs->rot_vec_ana_im_fx = rot_vec_ana_im_L40_fx; + hs->rot_vec_syn_re_fx = rot_vec_syn_re_L40_fx; + hs->rot_vec_syn_im_fx = rot_vec_syn_im_L40_fx; #endif if ( hs->prototype == CLDFB_PROTOTYPE_1_25MS ) { @@ -1405,7 +1884,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = NULL; hs->rot_vec_ana_delay_im_fx = NULL; - hs->p_filter_sf = (Word16)17051; + hs->rot_vec_syn_delay_im_fx = NULL; + hs->rot_vec_syn_delay_re_fx = NULL; + hs->p_filter_sf = (Word16) 17051; hs->p_filter = CLDFB80_40_fx; #endif } @@ -1422,7 +1903,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_ana_delay_im_fx = rot_vec_delay_im_LDQMF_fx; - hs->p_filter_sf = (Word16)15391; + hs->rot_vec_syn_delay_im_fx = rot_vec_delay_re_LDQMF_fx; + hs->rot_vec_syn_delay_re_fx = rot_vec_delay_im_LDQMF_fx; + hs->p_filter_sf = (Word16) 15391; hs->p_filter = LDQMF_40_fx; #endif } @@ -1436,6 +1919,8 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_re_fx = rot_vec_ana_re_L60_fx; hs->rot_vec_ana_im_fx = rot_vec_ana_im_L60_fx; + hs->rot_vec_syn_re_fx = rot_vec_syn_re_L60_fx; + hs->rot_vec_syn_im_fx = rot_vec_syn_im_L60_fx; #endif if ( hs->prototype == CLDFB_PROTOTYPE_1_25MS ) { @@ -1450,7 +1935,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = NULL; hs->rot_vec_ana_delay_im_fx = NULL; - hs->p_filter_sf = (Word16)17051; + hs->rot_vec_syn_delay_im_fx = NULL; + hs->rot_vec_syn_delay_re_fx = NULL; + hs->p_filter_sf = (Word16) 17051; hs->p_filter = CLDFB80_60_fx; #endif } @@ -1467,7 +1954,9 @@ static void cldfb_init_proto_and_twiddles( #ifdef IVAS_FLOAT_FIXED hs->rot_vec_ana_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_ana_delay_im_fx = rot_vec_delay_im_LDQMF_fx; - hs->p_filter_sf = (Word16)15391; + hs->rot_vec_syn_delay_im_fx = rot_vec_delay_re_LDQMF_fx; + hs->rot_vec_syn_delay_re_fx = rot_vec_delay_im_LDQMF_fx; + hs->p_filter_sf = (Word16) 15391; hs->p_filter = LDQMF_60_fx; #endif } @@ -1555,7 +2044,7 @@ void cldfb_restore_memory_ivas( } hs->memory_length = 0; - free( hs->memory_flt); + free( hs->memory_flt ); hs->memory_flt = NULL; return; @@ -1591,24 +2080,23 @@ void cldfb_reset_memory_ivas( } #ifdef IVAS_FLOAT_FIXED void cldfb_reset_memory_fx( - HANDLE_CLDFB_FILTER_BANK hs /* i/o: filter bank handle */, - Word16* memory_length -) + HANDLE_CLDFB_FILTER_BANK hs /* i/o: filter bank handle */, + Word16 *memory_length ) { - UWord16 offset = sub(hs->p_filter_length, hs->no_channels); + UWord16 offset = sub( hs->p_filter_length, hs->no_channels ); - IF (hs->type == CLDFB_ANALYSIS) - { - *memory_length = offset; - } - ELSE - { - *memory_length = hs->p_filter_length; - } + IF( hs->type == CLDFB_ANALYSIS ) + { + *memory_length = offset; + } + ELSE + { + *memory_length = hs->p_filter_length; + } - /* save the memory */ - set32_fx(hs->cldfb_state_fx, 0, *memory_length); + /* save the memory */ + set32_fx( hs->cldfb_state_fx, 0, *memory_length ); - return; + return; } #endif diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 3c1f5614844dc4c71884e8ed53175d4123a32c50..dfaad821a67a2f8f825827c3aadef11d5fa960d1 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -8021,4 +8021,28 @@ void bpf_pitch_coherence_fx( Decoder_State *st, /* i/o: decoder state structure */ const Word32 pitch_buf[] /* i : pitch for each subframe [0,1,2,3] */ ); + +void cldfbAnalysis_ivas_fx( + const Word32 *timeIn_fx, /* i : time buffer Qx */ + Word32 **realBuffer_fx, /* o : real value buffer Qx - 5*/ + Word32 **imagBuffer_fx, /* o : imag value buffer QX - 5*/ + const int16_t samplesToProcess, /* i : samples to process */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filterbank state */ +); + +void cldfbSynthesis_ivas_fx( + Word32 **realBuffer_fx, /* i : real values Qx*/ + Word32 **imagBuffer_fx, /* i : imag values Qx*/ + Word32 *timeOut_fx, /* o : output time domain samples Qx - 1*/ + const Word16 samplesToProcess, /* i : number of processed samples */ + HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filter bank state */ +); + +// bass_psfilter.c +void addBassPostFilter_fx( + const Word32 *harm_timeIn_fx, + const int16_t samplesToProcess, + Word32 **rAnalysis_fx, + Word32 **iAnalysis_fx, + HANDLE_CLDFB_FILTER_BANK cldfb ); #endif \ No newline at end of file diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c index 50f955071232509af4e1415566942f36c37b016d..77fc1a2ab9d3eadcc2da2708763ccfca8a5b2de5 100644 --- a/lib_com/rom_com.c +++ b/lib_com/rom_com.c @@ -9976,35 +9976,73 @@ const float rot_vec_syn_re_L10[5] = 0.1117172025f,0.1048929802f,0.0878011021f,0.0621146404f,0.0303479649f, }; +/*Q31*/ +const Word32 rot_vec_syn_re_L10_fx[5] = +{ + 239910864 ,225255952 ,188551424 ,133390176 ,65171760 , +}; + + const float rot_vec_syn_im_L10[5] = { -0.0043893808f,-0.0386970634f,-0.0692168078f,-0.0929611287f,-0.1076057667f, }; +/*Q31*/ +const Word32 rot_vec_syn_im_L10_fx[5] = +{ + -9426123 ,-83101312 ,-148641968 ,-199632496 ,-231081632 , +}; + const float rot_vec_syn_re_L16[8] = { 0.1117697258f,0.1090868144f,0.1022117580f,0.0914087610f,0.0770929766f,0.0598145523f, 0.0402374883f,0.0191141202f, }; +/*Q31*/ +const Word32 rot_vec_syn_re_L16_fx[8] = +{ + 240023664 ,234262144 ,219498080 ,196298816 ,165555904 ,128450776 ,86409352 ,41047260 , +}; + + const float rot_vec_syn_im_L16[8] = { -0.0027437928f,-0.0244962633f,-0.0453073563f,-0.0643773129f,-0.0809732855f,-0.0944575001f, -0.1043117660f,-0.1101573893f, }; +/*Q31*/ +const Word32 rot_vec_syn_im_L16_fx[8] = +{ + -5892250 ,-52605324 ,-97296808 ,-138249232 ,-173888800 ,-202845936 ,-224007808 ,-236561200 , +}; + const float rot_vec_syn_re_L20[10] = { 0.1117818477f,0.1100622363f,0.1056325273f,0.0986017949f,0.0891431591f,0.0774895228f, 0.0639278374f,0.0487920364f,0.0324548136f,0.0153184455f, }; +/*Q31*/ +const Word32 rot_vec_syn_re_L20_fx[10] = +{ + 240049696 ,236356848 ,226844128 ,211745744 ,191433472 ,166407488 ,137283984 ,104780104 ,69696184 ,32896112 , +}; + const float rot_vec_syn_im_L20[10] = { -0.0021951135f,-0.0196546216f,-0.0366301676f,-0.0527037574f,-0.0674796057f,-0.0805938822f, -0.0917236698f,-0.1005949163f,-0.1069891821f,-0.1107490191f, }; +/*Q31*/ +const Word32 rot_vec_syn_im_L20_fx[10] = +{ + -4713971 ,-42207980 ,-78662688 ,-113180456 ,-144911344 ,-173074048 ,-196975088 ,-216025936 ,-229757520 ,-237831712 , +}; + const float rot_vec_syn_re_L30[15] = { 0.1117938204f,0.1110284288f,0.1090465865f,0.1058700070f,0.1015334935f,0.0960845578f, @@ -10012,6 +10050,13 @@ const float rot_vec_syn_re_L30[15] = 0.0331543560f,0.0218117611f,0.0102301920f, }; +/*Q31*/ +const Word32 rot_vec_syn_re_L30_fx[15] = +{ + 240075408 ,238431728 ,234175760 ,227354112 ,218041520 ,206340016 ,192377808 ,176307872 , + 158306272 ,138570240 ,117315992 ,94776408 ,71198440 ,46840400 ,21969170 , +}; + const float rot_vec_syn_im_L30[15] = { -0.0014634613f,-0.0131410805f,-0.0246747234f,-0.0359380248f,-0.0468075816f,-0.0571643048f, @@ -10019,6 +10064,13 @@ const float rot_vec_syn_im_L30[15] = -0.1067744758f,-0.1096551279f,-0.1113343755f, }; +/*Q31*/ +const Word32 rot_vec_syn_im_L30_fx[15] = +{ + -3142759 ,-28220256 ,-52988564 ,-77176320 ,-100518520 ,-122759408 ,-143655328 ,-162977328 , + -180513712 ,-196072352 ,-209482768 ,-220598064 ,-229296448 ,-235482592 ,-239088752 , +}; + const float rot_vec_syn_re_L32[16] = { 0.1117949803f,0.1111221774f,0.1093792072f,0.1065828555f,0.1027600526f,0.0979476142f, @@ -10026,6 +10078,13 @@ const float rot_vec_syn_re_L32[16] = 0.0415145243f,0.0311394479f,0.0204644816f,0.0095924311f, }; +/*Q31*/ +const Word32 rot_vec_syn_re_L32_fx[16] = +{ + 240077888 ,238633056 ,234890064 ,228884944 ,220675536 ,210340896 ,197980576 ,183713584 , + 167677328 ,150026240 ,130930336 ,110573488 ,89151760 ,66871456 ,43947140 ,20599588 , +}; + const float rot_vec_syn_im_L32[16] = { -0.0013719997f,-0.0123232174f,-0.0231557558f,-0.0337652916f,-0.0440496492f,-0.0539097846f, @@ -10033,6 +10092,13 @@ const float rot_vec_syn_im_L32[16] = -0.1038101357f,-0.1073793965f,-0.1099145349f,-0.1113911364f, }; +/*Q31*/ +const Word32 rot_vec_syn_im_L32_fx[16] = +{ + -2946347 ,-26463908 ,-49726608 ,-72510408 ,-94595904 ,-115770384 ,-135829936 ,-154581360 , + -171844080 ,-187451856 ,-201254368 ,-213118704 ,-222930576 ,-230595504 ,-236039664 ,-239210640 , +}; + const float rot_vec_syn_re_L40[20] = { 0.1117980110f,0.1113672575f,0.1102498879f,0.1084527911f,0.1059870468f,0.1028678571f, @@ -10041,6 +10107,14 @@ const float rot_vec_syn_re_L40[20] = 0.0164049658f,0.0076773447f, }; +/*Q31*/ +const Word32 rot_vec_syn_re_L40_fx[20] = +{ + 240084400 ,239159360 ,236759824 ,232900592 ,227605456 ,220907040 ,212846672 ,203474016 , + 192846896 ,181030800 ,168098592 ,154130000 ,139211136 ,123434000 ,106895848 ,89698648 , + 71948424 ,53754620 ,35229396 ,16486972 , +}; + const float rot_vec_syn_im_L40[20] = { -0.0010976097f,-0.0098657969f,-0.0185731583f,-0.0271660100f,-0.0355913742f,-0.0437973057f, @@ -10049,6 +10123,14 @@ const float rot_vec_syn_im_L40[20] = -0.1105932959f,-0.1115394925f, }; +/*Q31*/ +const Word32 rot_vec_syn_im_L40_fx[20] = +{ + -2357099 ,-21186638 ,-39885552 ,-58338564 ,-76431896 ,-94054000 ,-111096224 ,-127453512 , + -143025008 ,-157714704 ,-171432032 ,-184092416 ,-195617824 ,-205937184 ,-214986864 ,-222711088 , + -229062224 ,-234001104 ,-237497296 ,-239529232 , +}; + const float rot_vec_syn_re_L60[30] = { 0.1118010042f,0.1116094882f,0.1111120583f,0.1103100780f,0.1092057454f,0.1078020875f, @@ -10058,6 +10140,15 @@ const float rot_vec_syn_re_L60[30] = 0.0338524782f,0.0282294165f,0.0225289799f,0.0167667930f,0.0109586494f,0.0051204690f, }; +/*Q31*/ +const Word32 rot_vec_syn_re_L60_fx[30] = +{ + 240090832 ,239679552 ,238611328 ,236889088 ,234517552 ,231503216 ,227854352 ,223580960 ,218694736 , + 213209088 ,207139056 ,200501264 ,193313904 ,185596688 ,177370784 ,168658704 ,159484336 ,149872832 , + 139850544 ,129444936 ,118684528 ,107598816 ,96218184 ,84573816 ,72697640 ,60622212 ,48380616 , + 36006412 ,23533520 ,10996123 , +}; + const float rot_vec_syn_im_L60[30] = { -0.0007317463f,-0.0065819559f,-0.0124141249f,-0.0182122676f,-0.0239604917f,-0.0296430418f, @@ -10067,6 +10158,15 @@ const float rot_vec_syn_im_L60[30] = -0.1065551956f,-0.1081808673f,-0.1095100227f,-0.1105390187f,-0.1112650350f,-0.1116860815f, }; +/*Q31*/ +const Word32 rot_vec_syn_im_L60_fx[30] = +{ + -1571413 ,-14134643 ,-26659130 ,-39110548 ,-51454764 ,-63657948 ,-75686648 ,-87507896 ,-99089296 , + -110399096 ,-121406296 ,-132080736 ,-142393152 ,-152315264 ,-161819904 ,-170881008 ,-179473744 , + -187574544 ,-195161216 ,-202212960 ,-208710464 ,-214635904 ,-219973040 ,-224707248 ,-228825536 , + -232316640 ,-235170976 ,-237380736 ,-238939840 ,-239844032 , +}; + const float bpf_weights_16[CLDFB_NO_COL_MAX] = { @@ -10080,6 +10180,23 @@ const Word16 bpf_weights_16_Fx[16] = 9/*0.000270f Q15*/, 3/*0.000080f Q15*/, 1/*0.000030f Q15*/, 3/*0.000082f Q15*/, 3/*0.000081f Q15*/, 2/*0.000052f Q15*/, 1/*0.000017f Q15*/, 1/*0.000016f Q15*/ }; + +const Word16 bpf_weights_16_ivas_fx[16] = +{ + 32767/*0.999969f Q15*/, 23022/*0.702561f Q15*/, 6843/*0.208838f Q15*/, 51/*0.001553f Q15*/, + 58/*0.001777f Q15*/, 45/*0.001370f Q15*/, 30/*0.000926f Q15*/, 18/*0.000554f Q15*/, + 9/*0.000270f Q15*/, 3/*0.000080f Q15*/, 1/*0.000030f Q15*/, 3/*0.000082f Q15*/, + 3/*0.000081f Q15*/, 2/*0.000052f Q15*/, 1/*0.000017f Q15*/, 1/*0.000016f Q15*/ +}; +const Word16 bpf_weights_16_ivas_fx_32[16] = +{ + 1073784774/*0.999969f Q15*/, 754369130/*0.702561f Q15*/, 224238095/*0.208838f Q15*/, 1667521/*0.001553f Q15*/, + 1908039/*0.001777f Q15*/, 1435593/*0.001370f Q15*/, 994285/*0.000926f Q15*/, 594853/*0.000554f Q15*/, + 289910/*0.000270f Q15*/, 85899/*0.000080f Q15*/, 32212/*0.000030f Q15*/, 88047/*0.000082f Q15*/, + 86973/*0.000081f Q15*/, 55835/*0.000052f Q15*/, 18254/*0.000017f Q15*/, 17179/*0.000016f Q15*/ +}; + + /*-------------------------------------------------------------------* * LP CNG excitation details code book *-------------------------------------------------------------------*/ diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index b38fa2fe34315b981312e094b712b061b9c1b5c8..51523dddc810280c568f6992e09bbd246d20c93b 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -1604,8 +1604,25 @@ extern const float rot_vec_syn_im_L40[20]; extern const float rot_vec_syn_re_L60[30]; extern const float rot_vec_syn_im_L60[30]; +extern const Word32 rot_vec_syn_re_L10_fx[5]; +extern const Word32 rot_vec_syn_im_L10_fx[5]; +extern const Word32 rot_vec_syn_re_L16_fx[8]; +extern const Word32 rot_vec_syn_im_L16_fx[8]; +extern const Word32 rot_vec_syn_re_L20_fx[10]; +extern const Word32 rot_vec_syn_im_L20_fx[10]; +extern const Word32 rot_vec_syn_re_L30_fx[15]; +extern const Word32 rot_vec_syn_im_L30_fx[15]; +extern const Word32 rot_vec_syn_re_L32_fx[16]; +extern const Word32 rot_vec_syn_im_L32_fx[16]; +extern const Word32 rot_vec_syn_re_L40_fx[20]; +extern const Word32 rot_vec_syn_im_L40_fx[20]; +extern const Word32 rot_vec_syn_re_L60_fx[30]; +extern const Word32 rot_vec_syn_im_L60_fx[30]; + extern const float bpf_weights_16[CLDFB_NO_COL_MAX]; extern const Word16 bpf_weights_16_Fx[16]; +extern const Word16 bpf_weights_16_ivas_fx[16]; +extern const Word16 bpf_weights_16_ivas_fx_32[16]; extern const float CNG_details_codebook[64][NUM_ENV_CNG]; extern const Word16 CNG_details_codebook_fx[64][NUM_ENV_CNG]; diff --git a/lib_com/stat_com.h b/lib_com/stat_com.h index 5030f387f95768963f9a4b913b27637c3efbee97..ea9cb6670bf28aab945902124b80d83e0d2f8ed4 100644 --- a/lib_com/stat_com.h +++ b/lib_com/stat_com.h @@ -693,6 +693,13 @@ typedef struct cldfb_filter_bank_struct const float *rot_vec_syn_re; const float *rot_vec_syn_im; +#ifdef IVAS_FLOAT_FIXED + const Word32 *rot_vec_syn_re_fx; + const Word32 *rot_vec_syn_im_fx; + + const Word32 *rot_vec_syn_delay_re_fx; + const Word32 *rot_vec_syn_delay_im_fx; +#endif /* rotation vectors for delay */ const float *rot_vec_ana_delay_re; const float *rot_vec_ana_delay_im; diff --git a/lib_dec/bass_psfilter.c b/lib_dec/bass_psfilter.c index 97894841a35bcdef9eb2be8afc7aaf143361fdde..cd4a75705c3834ab97b91c29b3bb51779fdf1399 100644 --- a/lib_dec/bass_psfilter.c +++ b/lib_dec/bass_psfilter.c @@ -39,6 +39,7 @@ #include #include "prot.h" #include "prot_fx2.h" +#include "prot_fx1.h" #include "ivas_prot.h" #include "cnst.h" #include "stat_dec.h" @@ -514,6 +515,72 @@ void addBassPostFilter( return; } + +#ifdef IVAS_FLOAT_FIXED +void addBassPostFilter_fx( + const Word32 *harm_timeIn_fx, // Qx + const Word16 samplesToProcess, + Word32 **rAnalysis_fx, // Qx - 5 + Word32 **iAnalysis_fx, // Qx - 5 + HANDLE_CLDFB_FILTER_BANK cldfb ) +{ + Word32 *tmp_R_fx[CLDFB_NO_COL_MAX]; + Word32 *tmp_I_fx[CLDFB_NO_COL_MAX]; + Word32 cldfbBufferReal_fx[CLDFB_NO_COL_MAX][20]; + Word32 cldfbBufferImag_fx[CLDFB_NO_COL_MAX][20]; + Word16 i, b; + Word16 maxBand; + const Word16 *weights_fx; + Word16 nCol = cldfb->no_col; + Word16 nColToProcess = nCol; + Word16 nChan = cldfb->no_channels; + IF( GT_16( samplesToProcess, -1 ) ) + { + nColToProcess = ( ( samplesToProcess + cldfb->no_channels - 1 ) / cldfb->no_channels ); + move16(); + } + + assert( nCol == 16 ); + + weights_fx = bpf_weights_16_ivas_fx_32; + + IF( GT_16( nChan, BPF_STOP_STOPBAND_16 ) ) + { + maxBand = BPF_STOP_STOPBAND_16; + move16(); + } + ELSE + { + maxBand = nChan; + move16(); + } + + FOR( i = 0; i < nColToProcess; i++ ) + { + tmp_R_fx[i] = cldfbBufferReal_fx[i]; + tmp_I_fx[i] = cldfbBufferImag_fx[i]; + } + + cldfbAnalysis_ivas_fx( harm_timeIn_fx, tmp_R_fx, tmp_I_fx, samplesToProcess, cldfb ); + + /* now do the subtraction */ + FOR( i = 0; i < nColToProcess; i++ ) + { + /* loop over low frequency bands */ + FOR( b = 0; b < maxBand; b++ ) + { + rAnalysis_fx[i][b] = L_sub( rAnalysis_fx[i][b], Mpy_32_32( tmp_R_fx[i][b], weights_fx[b] ) ); // Qx - 6 + move32(); + iAnalysis_fx[i][b] = L_sub( iAnalysis_fx[i][b], Mpy_32_32( tmp_I_fx[i][b], weights_fx[b] ) ); // Qx - 6 + move32(); + } + } + + return; +} +#endif + + #ifndef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * res_bpf_adapt() diff --git a/lib_dec/core_switching_dec.c b/lib_dec/core_switching_dec.c index ac571678bd1a93d47f321336870ababb8bd59911..68ad62f4dfd39d37ef4122c074a64affb6c8463b 100644 --- a/lib_dec/core_switching_dec.c +++ b/lib_dec/core_switching_dec.c @@ -40,6 +40,8 @@ #include "cnst.h" #include "rom_com.h" #include "prot.h" +#include "prot_fx2.h" +#include "prot_fx1.h" #include "ivas_cnst.h" #include "wmc_auto.h" @@ -47,8 +49,13 @@ * Local prototypes *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void core_switch_lb_upsamp( Decoder_State *st, float *output ); static void smoothTransitionDtxToTcx( float synth[], const int16_t output_frame, const int16_t delay_comp ); +#else +static void core_switch_lb_upsamp_fx( Decoder_State *st, Word32 *output ); +static void smoothTransitionDtxToTcx_fx( Word32 synth[], const int16_t output_frame, const int16_t delay_comp ); +#endif /*---------------------------------------------------------------------* * core_switching_pre_dec() @@ -563,6 +570,10 @@ ivas_error core_switching_post_dec( ) { int16_t i, delay_comp, delta; +#ifdef IVAS_FLOAT_FIXED + Word32 synth_fx[960]; + Word32 output_fx[1500]; +#endif float tmpF; float tmpDelta; float synth_subfr_out[SWITCH_MAX_GAP], synth_subfr_bwe[SWITCH_MAX_GAP]; @@ -663,7 +674,75 @@ ivas_error core_switching_post_dec( /* if this is first active MDCT-Stereo frame after a CNG frame and output format is mono DMX, this should only be done for the zero-th channel, the other one will simply be copied over after this function */ if ( ( ( st->last_core_brate != SID_2k40 && st->last_core_brate != FRAME_NO_DATA ) || ( st->element_mode != IVAS_CPE_DFT && st->element_mode != IVAS_CPE_TD ) || nchan_out == 1 ) && !( st->element_mode == IVAS_CPE_MDCT && st->idchan == 1 && ( nchan_out == 1 || last_element_mode == IVAS_CPE_DFT ) ) ) { +#ifdef IVAS_FLOAT_FIXED + // float to fix + // cldfb size calculaions + Word16 no_channel_ana = st->cldfbAna->no_channels; + Word16 no_channel_bpf = st->cldfbBPF->no_channels; + Word16 no_col_ana = st->cldfbAna->no_col; + Word16 no_col_bpf = st->cldfbBPF->no_col; + Word16 p_filter_ana = st->cldfbAna->p_filter_length; + Word16 p_filter_bpf = st->cldfbBPF->p_filter_length; + Word32 sampling_rate = st->L_frame * FRAMES_PER_SEC; + if ( ( st->cldfbAna->no_channels * st->cldfbAna->no_col ) != st->L_frame ) + { + no_channel_ana = (Word16) ( sampling_rate * INV_CLDFB_BANDWIDTH + 0.5 ); + no_col_ana = 16; + p_filter_ana = 10 * no_channel_ana; + if ( st->cldfbBPF != NULL && st->L_frame <= L_FRAME16k ) + { + no_channel_bpf = (Word16) ( sampling_rate * INV_CLDFB_BANDWIDTH + 0.5 ); + no_col_bpf = 16; + p_filter_bpf = 10 * no_channel_bpf; + } + + if ( st->ini_frame > 0 ) + { + st->cldfbSyn->bandsToZero = st->cldfbSyn->no_channels - no_channel_ana; + } + } + // buffer sized calculations + Word16 size = 0; + Word16 no_col = st->cldfbSyn->no_col; + if ( CLDFB_OVRLP_MIN_SLOTS * st->cldfbSyn->no_channels > -1 ) + { + no_col = min( no_col, ( CLDFB_OVRLP_MIN_SLOTS * st->cldfbSyn->no_channels + st->cldfbSyn->no_channels - 1 ) / st->cldfbSyn->no_channels ); + } + if ( CLDFB_OVRLP_MIN_SLOTS * no_channel_ana > -1 ) + { + size = CLDFB_OVRLP_MIN_SLOTS * no_channel_ana; + } + else + { + size = no_channel_ana * no_col_ana; + } + size = max( size, no_col * st->cldfbSyn->no_channels ); + + Word16 size_ana_len = max( p_filter_ana - no_channel_ana, st->cldfbAna->p_filter_length - st->cldfbAna->no_channels ); + Word16 size_bpf_len = max( p_filter_bpf - no_channel_bpf, st->cldfbBPF->p_filter_length - st->cldfbBPF->no_channels ); + + floatToFixed_arrL( output, output_fx, 10, size ); + floatToFixed_arrL( st->bpf_noise_buf_float, st->bpf_noise_buf_32, 11, size ); + floatToFixed_arrL( st->cldfbAna->cldfb_state, st->cldfbAna->cldfb_state_fx, 10, size_ana_len ); + floatToFixed_arrL( st->cldfbBPF->cldfb_state, st->cldfbBPF->cldfb_state_fx, 11, size_bpf_len ); + floatToFixed_arrL( st->cldfbSyn->cldfb_state, st->cldfbSyn->cldfb_state_fx, 4, st->cldfbSyn->p_filter_length ); + + // ------- + core_switch_lb_upsamp_fx( st, output_fx ); + // ------- + + fixedToFloat_arrL( output_fx, output, 4, size ); + fixedToFloat_arrL( st->cldfbAna->cldfb_state_fx, st->cldfbAna->cldfb_state, 10, size_ana_len ); + fixedToFloat_arrL( st->cldfbBPF->cldfb_state_fx, st->cldfbBPF->cldfb_state, 11, size_bpf_len ); + fixedToFloat_arrL( st->cldfbSyn->cldfb_state_fx, st->cldfbSyn->cldfb_state, 4, st->cldfbSyn->p_filter_length ); + if ( st->hTcxDec != NULL ) + { + fixedToFloat_arrL( st->previoussynth_fx_32, st->previoussynth, 4, st->hTcxDec->L_frameTCX ); + } + +#else core_switch_lb_upsamp( st, output ); +#endif } mvr2r( st->previoussynth, synth, delay_comp ); @@ -678,7 +757,20 @@ ivas_error core_switching_post_dec( if ( ( st->element_mode == IVAS_CPE_MDCT || ( ivas_format == ISM_FORMAT && st->core == TCX_20_CORE /* <- means TCX in general, TCX10 is forbidden after ACELP */ ) ) && st->last_core_brate <= SID_2k40 && st->core_brate > SID_2k40 ) { /* smooth transitions to avoid pops in car noise items */ +#ifdef IVAS_FLOAT_FIXED + + for ( int lp = 0; lp < 960; lp++ ) + { + synth_fx[lp] = (Word32) ( synth[lp] * ( 1u << 4 ) ); + } + smoothTransitionDtxToTcx_fx( synth_fx, output_frame, delay_comp ); + for ( int lp = 0; lp < 2 * delay_comp; lp++ ) + { + synth[lp] = (float) synth_fx[lp] / ( 1u << 4 ); + } +#else smoothTransitionDtxToTcx( synth, output_frame, delay_comp ); +#endif } /* Reset memories of CLDFBs */ @@ -1174,6 +1266,7 @@ void bw_switching_pre_proc( * Resample HQ/TCX-LB to the output sampling rate (8/16/32/48 kHz) *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void core_switch_lb_upsamp( Decoder_State *st, /* i/o: Decoder state */ float *output /* i/o: LB synth/upsampled LB synth */ @@ -1241,6 +1334,77 @@ static void core_switch_lb_upsamp( return; } +#else +static void core_switch_lb_upsamp_fx( + Decoder_State *st, /* i/o: Decoder state */ + Word32 *output /* i/o: LB synth/upsampled LB synth */ +) +{ + Word16 i; + Word32 *realBuffer_fx[CLDFB_OVRLP_MIN_SLOTS], *imagBuffer_fx[CLDFB_OVRLP_MIN_SLOTS]; + Word32 realBufferTmp_fx[CLDFB_OVRLP_MIN_SLOTS][CLDFB_NO_CHANNELS_MAX]; + Word32 imagBufferTmp_fx[CLDFB_OVRLP_MIN_SLOTS][CLDFB_NO_CHANNELS_MAX]; + + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + FOR( i = 0; i < CLDFB_OVRLP_MIN_SLOTS; i++ ) + { + set32_fx( realBufferTmp_fx[i], 0, CLDFB_NO_CHANNELS_MAX ); + set32_fx( imagBufferTmp_fx[i], 0, CLDFB_NO_CHANNELS_MAX ); + realBuffer_fx[i] = realBufferTmp_fx[i]; + imagBuffer_fx[i] = imagBufferTmp_fx[i]; + } + + /* check if the CLDFB works on the right sample rate */ + IF( NE_16( ( st->cldfbAna->no_channels * st->cldfbAna->no_col ), st->L_frame ) ) + { + resampleCldfb_ivas( st->cldfbAna, L_mult0( st->L_frame, FRAMES_PER_SEC ) ); + + IF( st->cldfbBPF != NULL && LE_16( st->L_frame, L_FRAME16k ) ) + { + resampleCldfb_ivas( st->cldfbBPF, L_mult0( st->L_frame, FRAMES_PER_SEC ) ); + } + + IF( GT_16( st->ini_frame, 0 ) ) + { + st->cldfbSyn->bandsToZero = sub( st->cldfbSyn->no_channels, st->cldfbAna->no_channels ); + move16(); + } + } + /* analysis of the synthesis at internal sampling rate */ + cldfbAnalysis_ivas_fx( output, realBuffer_fx, imagBuffer_fx, i_mult( CLDFB_OVRLP_MIN_SLOTS, st->cldfbAna->no_channels ), st->cldfbAna ); + + /* analysis and add the BPF error signal */ + IF( st->p_bpf_noise_buf_32 ) + { + addBassPostFilter_fx( st->p_bpf_noise_buf_32, st->bpf_off ? 0 : i_mult( CLDFB_OVRLP_MIN_SLOTS, st->cldfbBPF->no_channels ), realBuffer_fx, imagBuffer_fx, st->cldfbBPF ); + } + + /* set output mask for upsampling */ + IF( EQ_16( st->bwidth, NB ) ) + { + /* set NB mask for upsampling */ + st->cldfbSyn->bandsToZero = sub( st->cldfbSyn->no_channels, 10 ); + } + ELSE IF( NE_16( st->cldfbSyn->bandsToZero, sub( st->cldfbSyn->no_channels, st->cldfbAna->no_channels ) ) ) + { + /* in case of BW switching, re-init to default */ + st->cldfbSyn->bandsToZero = sub( st->cldfbSyn->no_channels, st->cldfbAna->no_channels ); + move16(); + } + + /* synthesis of the combined signal */ + cldfbSynthesis_ivas_fx( realBuffer_fx, imagBuffer_fx, output, i_mult( CLDFB_OVRLP_MIN_SLOTS, st->cldfbSyn->no_channels ), st->cldfbSyn ); + + /* save synthesis - needed in case of core switching */ + IF( st->hTcxDec != NULL ) + { + Copy32( output, st->previoussynth_fx_32, st->hTcxDec->L_frameTCX ); + } + + return; +} +#endif + /*---------------------------------------------------------------------* * smoothTransitionDtxToTcx() @@ -1252,6 +1416,7 @@ static void core_switch_lb_upsamp( #define TRANSITION_SMOOTHING_LEN_32k 31 #define TRANSITION_SMOOTHING_LEN_48k 47 +#ifndef IVAS_FLOAT_FIXED static void smoothTransitionDtxToTcx( float synth[], /* i/o: synthesis */ const int16_t output_frame, /* i : output frame length */ @@ -1307,3 +1472,66 @@ static void smoothTransitionDtxToTcx( return; } +#else +static void smoothTransitionDtxToTcx_fx( + Word32 synth[], /* i/o: synthesis */ + const Word16 output_frame, /* i : output frame length */ + const Word16 delay_comp /* i : delay compensation in samples */ +) +{ + Word16 i, filter_len; + Word16 w, step, fade_in; + Word32 mem; + Word32 smoothing_input_buffer[2 * NS2SA( 48000, DELAY_CLDFB_NS ) + TRANSITION_SMOOTHING_LEN_48k]; + Word32 smoothing_out_buffer[2 * NS2SA( 48000, DELAY_CLDFB_NS ) + TRANSITION_SMOOTHING_LEN_48k]; + + filter_len = TRANSITION_SMOOTHING_LEN_16k; + IF( EQ_16( output_frame, L_FRAME32k ) ) + { + filter_len = TRANSITION_SMOOTHING_LEN_32k; + } + ELSE IF( EQ_16( output_frame, L_FRAME48k ) ) + { + filter_len = TRANSITION_SMOOTHING_LEN_48k; + } + + /* prepare buffer */ + FOR( i = 0; i < filter_len / 2; i++ ) + { + smoothing_input_buffer[i] = synth[0]; + } + Copy32( synth, smoothing_input_buffer + filter_len / 2, add( shl( delay_comp, 1 ), shr( filter_len, 1 ) ) ); + + /* apply Mean filter */ + w = div_s( 1, filter_len ); + mem = sum32_fx( smoothing_input_buffer, filter_len ); + FOR( i = 0; i < 2 * delay_comp; i++ ) + { + smoothing_out_buffer[i] = Mpy_32_16_1( mem, w ); + move32(); + mem = L_add( mem, L_sub( smoothing_input_buffer[i + filter_len], smoothing_input_buffer[i] ) ); + } + + /* apply fades around transition */ + step = div_s( 1, delay_comp ); + step = shr( step, 2 ); + fade_in = extract_l( 0 ); + FOR( i = 0; i < delay_comp; i++ ) + { + synth[i] = L_add( Mpy_32_16_1( smoothing_out_buffer[i], fade_in ), Mpy_32_16_1( synth[i], sub( ONE_IN_Q15 - 1, fade_in ) ) ); + move32(); + fade_in = add( fade_in, step ); + } + + fade_in = 0; + FOR( ; i < 2 * delay_comp; i++ ) + { + synth[i] = L_add( Mpy_32_16_1( synth[i], fade_in ), Mpy_32_16_1( smoothing_out_buffer[i], sub( ONE_IN_Q15 - 1, fade_in ) ) ); + move32(); + fade_in = add( fade_in, step ); + } + + + return; +} +#endif diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index 367cf1749e8e5788c46dea2efb54601fa9056976..1235c7b02173118c6209ee103d70805dd4d9666f 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -2142,6 +2142,7 @@ typedef struct Decoder_State float previoussynth[L_FRAME48k]; /* note: only 60+111 out of 960 samples are needed in IVAS (for ACELP->TCX switching */ Word16 previoussynth_fx[L_FRAME48k]; + Word32 previoussynth_fx_32[L_FRAME48k]; float old_synth_sw[NS2SA( 48000, FRAME_SIZE_NS - ACELP_LOOK_NS - DELAY_BWE_TOTAL_NS )]; /* note: buffer used only in EVS mono */ Word16 old_synth_sw_fx[NS2SA(48000, FRAME_SIZE_NS - ACELP_LOOK_NS - DELAY_BWE_TOTAL_NS)];