Loading lib_com/cnst.h +1 −0 Original line number Diff line number Diff line Loading @@ -1233,6 +1233,7 @@ enum #define SPC 0.0234952f #define SPC_plus SPC * 1.001f #define ALPHA_SQ ( ( 0.5f / PI2 ) * ( 0.5f / PI2 ) ) #define ALPHA_SQ_Q30 (6799549) /* ( ( 0.5f / PI2 ) * ( 0.5f / PI2 ) ) in Q30 */ #define NC M / 2 #define LSF_GAP 50.0f Loading lib_com/fft_rel.c +162 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,168 @@ void fft_rel( return; } void fft_rel_16_32fx( Word16 x[], /* i/o: input/output vector Qx */ Word16 *q_x, /* extra scaling added on speech buffer*/ Word16 i_subfr, const Word16 n, /* i : vector length */ const Word16 m /* i : log2 of vector length */ ) { Word16 i, j, k, n1, n2, n4; Word16 step; Word32 xt, t1, t2; Word32 *x0, *x1, *x2; const Word16 *s, *c; Word32 *xi2, *xi3, *xi4, *xi1; Word32 fft_bff32[L_FFT]; Copy_Scale_sig_16_32_no_sat( x, fft_bff32, L_FFT, 0 ); // copying x to fft_bff32 without scaling /*-----------------------------------------------------------------* * Digit reverse counter *-----------------------------------------------------------------*/ j = 0; move16(); x0 = &fft_bff32[0]; // Qx FOR( i = 0; i < n - 1; i++ ) { IF( LT_16( i, j ) ) { xt = fft_bff32[j]; // Qx move32(); fft_bff32[j] = *x0; // Qx move32(); *x0 = xt; // Qx move32(); } x0++; k = shr( n, 1 ); WHILE( ( k <= j ) ) { j = sub( j, k ); k = shr( k, 1 ); } j = add( j, k ); } /*-----------------------------------------------------------------* * Length two butterflies *-----------------------------------------------------------------*/ x0 = &fft_bff32[0]; x1 = &fft_bff32[1]; FOR( i = 0; i < ( n >> 1 ); i++ ) { xt = *x0; move32(); *x0 = L_add( xt, *x1 ); move32(); *x1 = L_sub( xt, *x1 ); move32(); x0++; x0++; x1++; x1++; } /*-----------------------------------------------------------------* * Other butterflies * * The implementation described in [1] has been changed by using * table lookup for evaluating sine and cosine functions. The * variable ind and its increment step are needed to access table * entries. Note that this implementation assumes n4 to be so * small that ind will never exceed the table. Thus the input * argument n and the constant N_MAX_SAS must be set properly. *-----------------------------------------------------------------*/ n2 = 1; move16(); /* step = N_MAX_SAS/4; */ FOR( k = 2; k <= m; k++ ) { n4 = n2; move16(); n2 = shl( n4, 1 ); n1 = shl( n2, 1 ); step = idiv1616( N_MAX_SAS, n1 ); x0 = fft_bff32; x1 = fft_bff32 + n2; x2 = fft_bff32 + add( n2, n4 ); FOR( i = 0; i < n; i += n1 ) { xt = *x0; move32(); /* xt = x[i]; */ *x0 = L_add( xt, *x1 ); move32(); /* x[i] = xt + x[i+n2]; */ *x1 = L_sub( xt, *x1 ); move32(); /* x[i+n2] = xt - x[i+n2]; */ *x2 = L_negate( *x2 ); move32(); /* x[i+n2+n4] = -x[i+n2+n4]; */ s = sincos_t_fx + step; // Q15 c = s + 64; // Q15 xi1 = fft_bff32 + add( i, 1 ); xi3 = xi1 + n2; xi2 = xi3 - 2; xi4 = xi1 + sub( n1, 2 ); FOR( j = 1; j < n4; j++ ) { t1 = L_add( Mpy_32_16_1( *xi3, *c ), Mpy_32_16_1( *xi4, *s ) ); /* t1 = *xi3**(pt_c+ind) + *xi4**(pt_s+ind); Qx */ t2 = L_sub( Mpy_32_16_1( *xi3, *s ), Mpy_32_16_1( *xi4, *c ) ); /* t2 = *xi3**(pt_s+ind) - *xi4**(pt_c+ind); Qx */ *xi4 = L_sub( *xi2, t2 ); move32(); *xi3 = L_negate( L_add( *xi2, t2 ) ); move32(); *xi2 = L_sub( *xi1, t1 ); move32(); *xi1 = L_add( *xi1, t1 ); move32(); xi4--; xi2--; xi3++; xi1++; c += step; s += step; /* autoincrement by ar0 */ } x0 += n1; x1 += n1; x2 += n1; } /* step = shr(step, 1); */ } Word16 norm = L_norm_arr( fft_bff32, L_FFT ); IF( i_subfr == 0 ) { Copy_Scale_sig32_16( fft_bff32, x, L_FFT, norm ); *q_x = sub( norm, 16 ); move16(); } ELSE { IF( LT_16( sub( norm, 16 ), *q_x ) ) { scale_sig( x - L_FFT, L_FFT, sub( sub( norm, 16 ), *q_x ) ); Copy_Scale_sig32_16( fft_bff32, x, L_FFT, norm ); *q_x = sub( norm, 16 ); move16(); } ELSE { Copy_Scale_sig32_16( fft_bff32, x, L_FFT, add( 16, *q_x ) ); } } return; } void fft_rel_fx( Word16 x[], /* i/o: input/output vector Qx */ Loading lib_com/lsf_tools_fx.c +74 −0 Original line number Diff line number Diff line Loading @@ -1505,6 +1505,80 @@ void lsp_weights_fx( move16(); } void lsp_weights_ivas_fx( Word16 lsp_nq_fx[], Word16 w[], Word16 Order, Word16 *Qout ) { Word16 i; Word16 q_weight[20]; Word32 weight[20]; Word16 delta1, delta2; Word32 L_tmp; Word16 q_min; delta1 = lsp_nq_fx[0]; // Q15 move16(); delta2 = sub( lsp_nq_fx[1], lsp_nq_fx[0] ); // Q15 L_tmp = L_mult0( delta1, delta2 ); // Q30 // Q30 L_tmp = root_a_over_b_ivas_fx( ALPHA_SQ_Q30, Q30, L_tmp, Q30, &q_weight[0] ); // q_weight[0] weight[0] = Mpy_32_16_1( L_tmp, 32000 /* 250 in Q7*/ ); // q_weight[0]-8 q_weight[0] = sub( q_weight[0], 8 ); move32(); move16(); q_min = q_weight[0]; move16(); FOR( i = 1; i < Order - 1; i++ ) { delta1 = sub( lsp_nq_fx[i], lsp_nq_fx[i - 1] ); // Q15 delta2 = sub( lsp_nq_fx[i + 1], lsp_nq_fx[i] ); // Q15 L_tmp = L_mult0( delta1, delta2 ); // Q30 L_tmp = root_a_over_b_ivas_fx( ALPHA_SQ_Q30, Q30, L_tmp, Q30, &q_weight[i] ); // q_weight[i] weight[i] = Mpy_32_16_1( L_tmp, 32000 /* 250 in Q7*/ ); // q_weight[i] q_weight[i] = sub( q_weight[i], 8 ); move32(); move16(); q_min = s_min( q_min, q_weight[i] ); } delta1 = sub( lsp_nq_fx[i], lsp_nq_fx[i - 1] ); // Q15 delta2 = sub( 16384 /* 0.5 in Q15*/, lsp_nq_fx[i] ); // Q15 L_tmp = L_mult0( delta1, delta2 ); // Q30 L_tmp = root_a_over_b_ivas_fx( ALPHA_SQ_Q30, Q30, L_tmp, Q30, &q_weight[i] ); // q_weight[i] weight[i] = Mpy_32_16_1( L_tmp, 32000 /* 250 in Q7*/ ); // q_weight[i] q_weight[i] = sub( q_weight[i], 8 ); move32(); move16(); q_min = s_min( q_min, q_weight[i] ); FOR( i = 0; i < Order; i++ ) { w[i] = round_fx( L_shl( weight[i], sub( q_min, q_weight[i] ) ) ); /* q_min-16 */ move16(); } IF( Order != LPC_SHB_ORDER_WB ) { w[3] = round_fx( L_shl( L_mult( w[3], 18022 ), 1 ) ); /* q_min-16 */ w[4] = round_fx( L_shl( L_mult( w[4], 18022 ), 1 ) ); /* q_min-16 */ move16(); move16(); } *Qout = sub( q_min, 16 ); move16(); } /* * E_LPC_isf_isp_conversion * Loading lib_com/prot_fx.h +20 −0 Original line number Diff line number Diff line Loading @@ -1084,6 +1084,12 @@ void lsp_weights_fx( Word16 Order, Word16 *Qout ); void lsp_weights_ivas_fx( Word16 lsp_nq_fx[], Word16 w[], Word16 Order, Word16 *Qout ); void space_lsfs_fx( Word16 *lsfs, /* i/o: Line spectral frequencies */ const Word16 order /* i : order of LP analysis */ Loading Loading @@ -1472,6 +1478,13 @@ void fft_rel_fx( const Word16 n, /* i : vector length */ const Word16 m /* i : log2 of vector length */ ); void fft_rel_16_32fx( Word16 x[], /* i/o: input/output vector Qx */ Word16 *q_x, /* extra scaling added on speech buffer*/ Word16 i_subfr, const Word16 n, /* i : vector length */ const Word16 m /* i : log2 of vector length */ ); void fft_rel_fx32( Word32 x[], /* i/o: i /output vector */ const Word16 n, /* i : vector length */ Loading Loading @@ -10297,6 +10310,13 @@ Word32 root_a_over_b_fx( Word16 Q_b, Word16 *exp_out ); Word32 root_a_over_b_ivas_fx( Word32 a, /* Q(Q_a) */ Word16 Q_a, Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *exp_out ); void fir_fx( const Word16 x[], /* i : input vector Qx*/ const Word16 h[], /* i : impulse response of the FIR filter Q12*/ Word16 y[], /* o : output vector (result of filtering) Qx*/ lib_com/tools_fx.c +103 −0 Original line number Diff line number Diff line Loading @@ -2505,6 +2505,109 @@ Word32 root_a_over_b_fx( return L_tmp; } Word32 root_a_over_b_ivas_fx( Word32 a, /* Q(Q_a) */ Word16 Q_a, Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *q_out ) { Word16 shift_a, shift_b, shift; Word32 mod_a, mod_b, one_in_Q_a, one_in_Q_b, half_in_Q_a, half_in_Q_b; Word32 a_sqr, b_sqr, p0, p1, p2, approx; Word16 exp; test(); IF( ( a <= 0 ) || ( b <= 0 ) ) { *q_out = 0; move16(); return 0; } one_in_Q_a = L_shl( 1, Q_a ); // 1.0f in Q_a one_in_Q_b = L_shl( 1, Q_b ); // 1.0f in Q_b half_in_Q_a = L_shr( one_in_Q_a, 1 ); // 0.5f in Q_a half_in_Q_b = L_shr( one_in_Q_b, 1 ); // 0.5f in Q_b a = L_add( a, one_in_Q_a ); b = L_add( b, one_in_Q_b ); /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "a" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ /* giving a value between 0.5 & 1.0. */ mod_a = a; move32(); shift_a = 0; move16(); WHILE( GT_32( mod_a, one_in_Q_a ) ) { mod_a = L_shr( mod_a, 1 ); shift_a = sub( shift_a, 1 ); } WHILE( LT_32( mod_a, half_in_Q_a ) ) { mod_a = L_shl( mod_a, 1 ); shift_a = add( shift_a, 1 ); } shift_a = s_and( shift_a, -2 ); mod_a = L_shl( a, shift_a ); // Q_a /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "b" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ /* giving a value between 0.5 & 1.0. */ mod_b = b; move32(); shift_b = 0; move16(); WHILE( GT_32( mod_b, one_in_Q_b ) ) { mod_b = L_shr( mod_b, 1 ); shift_b = sub( shift_b, 1 ); } WHILE( LT_32( mod_b, half_in_Q_b ) ) { mod_b = L_shl( mod_b, 1 ); shift_b = add( shift_b, 1 ); } shift_b = s_and( shift_b, -2 ); mod_b = L_shl( b, shift_b ); // Q_b shift = shr( sub( shift_b, shift_a ), 1 ); a_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_a, mod_a ), sub( 32, Q_a ) ) ); // Q_a b_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_b, mod_b ), sub( 32, Q_b ) ) ); // Q_b p2 = L_shl( -408505077 /* -0.7609f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 p1 = L_shl( 1444612250 /* 2.6908f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 p0 = L_shl( 385258566 /* 0.7176f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 p2 = Madd_32_32( Madd_32_32( p2, 501759554 /* 0.9346f in Q29*/, mod_b ), -252060893 /* -0.4695f in Q29 */, b_sqr ); // Q_b-2 p1 = Madd_32_32( Madd_32_32( p1, -1774680487 /* -3.3056f in Q29 */, mod_b ), 891635211 /* 1.6608f in Q29 */, b_sqr ); // Q_b-2 p0 = Madd_32_32( Madd_32_32( p0, -473251709 /* -0.8815f in Q29 */, mod_b ), 237780127 /* 0.4429f in Q29 */, b_sqr ); // Q_b-2 /* approx = p0 + p1 * mod_a + p2 * mod_a * mod_a; */ approx = Madd_32_32( Mpy_32_32( p1, mod_a ), p2, a_sqr ); // Q_a+Q_b-33 approx = L_add( approx, L_shl( p0, sub( Q_a, 31 ) ) ); // Q_a+Q_b-33 exp = sub( norm_l( approx ), 1 ); approx = L_shl( approx, exp ); // // Q_a+Q_b-33+exp *q_out = sub( add( sub( add( Q_a, Q_b ), 33 ), exp ), shift ); move16(); return approx; } /*===================================================================*/ /* FUNCTION : fir_fx () */ /*-------------------------------------------------------------------*/ Loading Loading
lib_com/cnst.h +1 −0 Original line number Diff line number Diff line Loading @@ -1233,6 +1233,7 @@ enum #define SPC 0.0234952f #define SPC_plus SPC * 1.001f #define ALPHA_SQ ( ( 0.5f / PI2 ) * ( 0.5f / PI2 ) ) #define ALPHA_SQ_Q30 (6799549) /* ( ( 0.5f / PI2 ) * ( 0.5f / PI2 ) ) in Q30 */ #define NC M / 2 #define LSF_GAP 50.0f Loading
lib_com/fft_rel.c +162 −0 Original line number Diff line number Diff line Loading @@ -301,6 +301,168 @@ void fft_rel( return; } void fft_rel_16_32fx( Word16 x[], /* i/o: input/output vector Qx */ Word16 *q_x, /* extra scaling added on speech buffer*/ Word16 i_subfr, const Word16 n, /* i : vector length */ const Word16 m /* i : log2 of vector length */ ) { Word16 i, j, k, n1, n2, n4; Word16 step; Word32 xt, t1, t2; Word32 *x0, *x1, *x2; const Word16 *s, *c; Word32 *xi2, *xi3, *xi4, *xi1; Word32 fft_bff32[L_FFT]; Copy_Scale_sig_16_32_no_sat( x, fft_bff32, L_FFT, 0 ); // copying x to fft_bff32 without scaling /*-----------------------------------------------------------------* * Digit reverse counter *-----------------------------------------------------------------*/ j = 0; move16(); x0 = &fft_bff32[0]; // Qx FOR( i = 0; i < n - 1; i++ ) { IF( LT_16( i, j ) ) { xt = fft_bff32[j]; // Qx move32(); fft_bff32[j] = *x0; // Qx move32(); *x0 = xt; // Qx move32(); } x0++; k = shr( n, 1 ); WHILE( ( k <= j ) ) { j = sub( j, k ); k = shr( k, 1 ); } j = add( j, k ); } /*-----------------------------------------------------------------* * Length two butterflies *-----------------------------------------------------------------*/ x0 = &fft_bff32[0]; x1 = &fft_bff32[1]; FOR( i = 0; i < ( n >> 1 ); i++ ) { xt = *x0; move32(); *x0 = L_add( xt, *x1 ); move32(); *x1 = L_sub( xt, *x1 ); move32(); x0++; x0++; x1++; x1++; } /*-----------------------------------------------------------------* * Other butterflies * * The implementation described in [1] has been changed by using * table lookup for evaluating sine and cosine functions. The * variable ind and its increment step are needed to access table * entries. Note that this implementation assumes n4 to be so * small that ind will never exceed the table. Thus the input * argument n and the constant N_MAX_SAS must be set properly. *-----------------------------------------------------------------*/ n2 = 1; move16(); /* step = N_MAX_SAS/4; */ FOR( k = 2; k <= m; k++ ) { n4 = n2; move16(); n2 = shl( n4, 1 ); n1 = shl( n2, 1 ); step = idiv1616( N_MAX_SAS, n1 ); x0 = fft_bff32; x1 = fft_bff32 + n2; x2 = fft_bff32 + add( n2, n4 ); FOR( i = 0; i < n; i += n1 ) { xt = *x0; move32(); /* xt = x[i]; */ *x0 = L_add( xt, *x1 ); move32(); /* x[i] = xt + x[i+n2]; */ *x1 = L_sub( xt, *x1 ); move32(); /* x[i+n2] = xt - x[i+n2]; */ *x2 = L_negate( *x2 ); move32(); /* x[i+n2+n4] = -x[i+n2+n4]; */ s = sincos_t_fx + step; // Q15 c = s + 64; // Q15 xi1 = fft_bff32 + add( i, 1 ); xi3 = xi1 + n2; xi2 = xi3 - 2; xi4 = xi1 + sub( n1, 2 ); FOR( j = 1; j < n4; j++ ) { t1 = L_add( Mpy_32_16_1( *xi3, *c ), Mpy_32_16_1( *xi4, *s ) ); /* t1 = *xi3**(pt_c+ind) + *xi4**(pt_s+ind); Qx */ t2 = L_sub( Mpy_32_16_1( *xi3, *s ), Mpy_32_16_1( *xi4, *c ) ); /* t2 = *xi3**(pt_s+ind) - *xi4**(pt_c+ind); Qx */ *xi4 = L_sub( *xi2, t2 ); move32(); *xi3 = L_negate( L_add( *xi2, t2 ) ); move32(); *xi2 = L_sub( *xi1, t1 ); move32(); *xi1 = L_add( *xi1, t1 ); move32(); xi4--; xi2--; xi3++; xi1++; c += step; s += step; /* autoincrement by ar0 */ } x0 += n1; x1 += n1; x2 += n1; } /* step = shr(step, 1); */ } Word16 norm = L_norm_arr( fft_bff32, L_FFT ); IF( i_subfr == 0 ) { Copy_Scale_sig32_16( fft_bff32, x, L_FFT, norm ); *q_x = sub( norm, 16 ); move16(); } ELSE { IF( LT_16( sub( norm, 16 ), *q_x ) ) { scale_sig( x - L_FFT, L_FFT, sub( sub( norm, 16 ), *q_x ) ); Copy_Scale_sig32_16( fft_bff32, x, L_FFT, norm ); *q_x = sub( norm, 16 ); move16(); } ELSE { Copy_Scale_sig32_16( fft_bff32, x, L_FFT, add( 16, *q_x ) ); } } return; } void fft_rel_fx( Word16 x[], /* i/o: input/output vector Qx */ Loading
lib_com/lsf_tools_fx.c +74 −0 Original line number Diff line number Diff line Loading @@ -1505,6 +1505,80 @@ void lsp_weights_fx( move16(); } void lsp_weights_ivas_fx( Word16 lsp_nq_fx[], Word16 w[], Word16 Order, Word16 *Qout ) { Word16 i; Word16 q_weight[20]; Word32 weight[20]; Word16 delta1, delta2; Word32 L_tmp; Word16 q_min; delta1 = lsp_nq_fx[0]; // Q15 move16(); delta2 = sub( lsp_nq_fx[1], lsp_nq_fx[0] ); // Q15 L_tmp = L_mult0( delta1, delta2 ); // Q30 // Q30 L_tmp = root_a_over_b_ivas_fx( ALPHA_SQ_Q30, Q30, L_tmp, Q30, &q_weight[0] ); // q_weight[0] weight[0] = Mpy_32_16_1( L_tmp, 32000 /* 250 in Q7*/ ); // q_weight[0]-8 q_weight[0] = sub( q_weight[0], 8 ); move32(); move16(); q_min = q_weight[0]; move16(); FOR( i = 1; i < Order - 1; i++ ) { delta1 = sub( lsp_nq_fx[i], lsp_nq_fx[i - 1] ); // Q15 delta2 = sub( lsp_nq_fx[i + 1], lsp_nq_fx[i] ); // Q15 L_tmp = L_mult0( delta1, delta2 ); // Q30 L_tmp = root_a_over_b_ivas_fx( ALPHA_SQ_Q30, Q30, L_tmp, Q30, &q_weight[i] ); // q_weight[i] weight[i] = Mpy_32_16_1( L_tmp, 32000 /* 250 in Q7*/ ); // q_weight[i] q_weight[i] = sub( q_weight[i], 8 ); move32(); move16(); q_min = s_min( q_min, q_weight[i] ); } delta1 = sub( lsp_nq_fx[i], lsp_nq_fx[i - 1] ); // Q15 delta2 = sub( 16384 /* 0.5 in Q15*/, lsp_nq_fx[i] ); // Q15 L_tmp = L_mult0( delta1, delta2 ); // Q30 L_tmp = root_a_over_b_ivas_fx( ALPHA_SQ_Q30, Q30, L_tmp, Q30, &q_weight[i] ); // q_weight[i] weight[i] = Mpy_32_16_1( L_tmp, 32000 /* 250 in Q7*/ ); // q_weight[i] q_weight[i] = sub( q_weight[i], 8 ); move32(); move16(); q_min = s_min( q_min, q_weight[i] ); FOR( i = 0; i < Order; i++ ) { w[i] = round_fx( L_shl( weight[i], sub( q_min, q_weight[i] ) ) ); /* q_min-16 */ move16(); } IF( Order != LPC_SHB_ORDER_WB ) { w[3] = round_fx( L_shl( L_mult( w[3], 18022 ), 1 ) ); /* q_min-16 */ w[4] = round_fx( L_shl( L_mult( w[4], 18022 ), 1 ) ); /* q_min-16 */ move16(); move16(); } *Qout = sub( q_min, 16 ); move16(); } /* * E_LPC_isf_isp_conversion * Loading
lib_com/prot_fx.h +20 −0 Original line number Diff line number Diff line Loading @@ -1084,6 +1084,12 @@ void lsp_weights_fx( Word16 Order, Word16 *Qout ); void lsp_weights_ivas_fx( Word16 lsp_nq_fx[], Word16 w[], Word16 Order, Word16 *Qout ); void space_lsfs_fx( Word16 *lsfs, /* i/o: Line spectral frequencies */ const Word16 order /* i : order of LP analysis */ Loading Loading @@ -1472,6 +1478,13 @@ void fft_rel_fx( const Word16 n, /* i : vector length */ const Word16 m /* i : log2 of vector length */ ); void fft_rel_16_32fx( Word16 x[], /* i/o: input/output vector Qx */ Word16 *q_x, /* extra scaling added on speech buffer*/ Word16 i_subfr, const Word16 n, /* i : vector length */ const Word16 m /* i : log2 of vector length */ ); void fft_rel_fx32( Word32 x[], /* i/o: i /output vector */ const Word16 n, /* i : vector length */ Loading Loading @@ -10297,6 +10310,13 @@ Word32 root_a_over_b_fx( Word16 Q_b, Word16 *exp_out ); Word32 root_a_over_b_ivas_fx( Word32 a, /* Q(Q_a) */ Word16 Q_a, Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *exp_out ); void fir_fx( const Word16 x[], /* i : input vector Qx*/ const Word16 h[], /* i : impulse response of the FIR filter Q12*/ Word16 y[], /* o : output vector (result of filtering) Qx*/
lib_com/tools_fx.c +103 −0 Original line number Diff line number Diff line Loading @@ -2505,6 +2505,109 @@ Word32 root_a_over_b_fx( return L_tmp; } Word32 root_a_over_b_ivas_fx( Word32 a, /* Q(Q_a) */ Word16 Q_a, Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *q_out ) { Word16 shift_a, shift_b, shift; Word32 mod_a, mod_b, one_in_Q_a, one_in_Q_b, half_in_Q_a, half_in_Q_b; Word32 a_sqr, b_sqr, p0, p1, p2, approx; Word16 exp; test(); IF( ( a <= 0 ) || ( b <= 0 ) ) { *q_out = 0; move16(); return 0; } one_in_Q_a = L_shl( 1, Q_a ); // 1.0f in Q_a one_in_Q_b = L_shl( 1, Q_b ); // 1.0f in Q_b half_in_Q_a = L_shr( one_in_Q_a, 1 ); // 0.5f in Q_a half_in_Q_b = L_shr( one_in_Q_b, 1 ); // 0.5f in Q_b a = L_add( a, one_in_Q_a ); b = L_add( b, one_in_Q_b ); /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "a" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ /* giving a value between 0.5 & 1.0. */ mod_a = a; move32(); shift_a = 0; move16(); WHILE( GT_32( mod_a, one_in_Q_a ) ) { mod_a = L_shr( mod_a, 1 ); shift_a = sub( shift_a, 1 ); } WHILE( LT_32( mod_a, half_in_Q_a ) ) { mod_a = L_shl( mod_a, 1 ); shift_a = add( shift_a, 1 ); } shift_a = s_and( shift_a, -2 ); mod_a = L_shl( a, shift_a ); // Q_a /* This next piece of code implements a "norm" function */ /* and returns the shift needed to scale "b" to have a */ /* 1 in the (MSB-1) position. This is equivalent to */ /* giving a value between 0.5 & 1.0. */ mod_b = b; move32(); shift_b = 0; move16(); WHILE( GT_32( mod_b, one_in_Q_b ) ) { mod_b = L_shr( mod_b, 1 ); shift_b = sub( shift_b, 1 ); } WHILE( LT_32( mod_b, half_in_Q_b ) ) { mod_b = L_shl( mod_b, 1 ); shift_b = add( shift_b, 1 ); } shift_b = s_and( shift_b, -2 ); mod_b = L_shl( b, shift_b ); // Q_b shift = shr( sub( shift_b, shift_a ), 1 ); a_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_a, mod_a ), sub( 32, Q_a ) ) ); // Q_a b_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_b, mod_b ), sub( 32, Q_b ) ) ); // Q_b p2 = L_shl( -408505077 /* -0.7609f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 p1 = L_shl( 1444612250 /* 2.6908f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 p0 = L_shl( 385258566 /* 0.7176f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 p2 = Madd_32_32( Madd_32_32( p2, 501759554 /* 0.9346f in Q29*/, mod_b ), -252060893 /* -0.4695f in Q29 */, b_sqr ); // Q_b-2 p1 = Madd_32_32( Madd_32_32( p1, -1774680487 /* -3.3056f in Q29 */, mod_b ), 891635211 /* 1.6608f in Q29 */, b_sqr ); // Q_b-2 p0 = Madd_32_32( Madd_32_32( p0, -473251709 /* -0.8815f in Q29 */, mod_b ), 237780127 /* 0.4429f in Q29 */, b_sqr ); // Q_b-2 /* approx = p0 + p1 * mod_a + p2 * mod_a * mod_a; */ approx = Madd_32_32( Mpy_32_32( p1, mod_a ), p2, a_sqr ); // Q_a+Q_b-33 approx = L_add( approx, L_shl( p0, sub( Q_a, 31 ) ) ); // Q_a+Q_b-33 exp = sub( norm_l( approx ), 1 ); approx = L_shl( approx, exp ); // // Q_a+Q_b-33+exp *q_out = sub( add( sub( add( Q_a, Q_b ), 33 ), exp ), shift ); move16(); return approx; } /*===================================================================*/ /* FUNCTION : fir_fx () */ /*-------------------------------------------------------------------*/ Loading