summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c')
-rw-r--r--lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c99
1 files changed, 42 insertions, 57 deletions
diff --git a/lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c b/lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c
index dd14d4bca6..a3746a6ef9 100644
--- a/lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c
+++ b/lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c
@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
30#endif 30#endif
31 31
32#include "SigProc_FIX.h" 32#include "SigProc_FIX.h"
33#include "define.h"
33 34
34#define QA 24 35#define QA 24
35#define A_LIMIT SILK_FIX_CONST( 0.99975, QA ) 36#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
@@ -38,119 +39,103 @@ POSSIBILITY OF SUCH DAMAGE.
38 39
39/* Compute inverse of LPC prediction gain, and */ 40/* Compute inverse of LPC prediction gain, and */
40/* test if LPC coefficients are stable (all poles within unit circle) */ 41/* test if LPC coefficients are stable (all poles within unit circle) */
41static opus_int32 LPC_inverse_pred_gain_QA( /* O Returns inverse prediction gain in energy domain, Q30 */ 42static opus_int32 LPC_inverse_pred_gain_QA_c( /* O Returns inverse prediction gain in energy domain, Q30 */
42 opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */ 43 opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
43 const opus_int order /* I Prediction order */ 44 const opus_int order /* I Prediction order */
44) 45)
45{ 46{
46 opus_int k, n, mult2Q; 47 opus_int k, n, mult2Q;
47 opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA; 48 opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
48 opus_int32 *Aold_QA, *Anew_QA;
49 49
50 Anew_QA = A_QA[ order & 1 ]; 50 invGain_Q30 = SILK_FIX_CONST( 1, 30 );
51
52 invGain_Q30 = (opus_int32)1 << 30;
53 for( k = order - 1; k > 0; k-- ) { 51 for( k = order - 1; k > 0; k-- ) {
54 /* Check for stability */ 52 /* Check for stability */
55 if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { 53 if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
56 return 0; 54 return 0;
57 } 55 }
58 56
59 /* Set RC equal to negated AR coef */ 57 /* Set RC equal to negated AR coef */
60 rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA ); 58 rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
61 59
62 /* rc_mult1_Q30 range: [ 1 : 2^30 ] */ 60 /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
63 rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); 61 rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
64 silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */ 62 silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
65 silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) ); 63 silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
66 64
67 /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
68 mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
69 rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
70
71 /* Update inverse gain */ 65 /* Update inverse gain */
72 /* invGain_Q30 range: [ 0 : 2^30 ] */ 66 /* invGain_Q30 range: [ 0 : 2^30 ] */
73 invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); 67 invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
74 silk_assert( invGain_Q30 >= 0 ); 68 silk_assert( invGain_Q30 >= 0 );
75 silk_assert( invGain_Q30 <= ( 1 << 30 ) ); 69 silk_assert( invGain_Q30 <= ( 1 << 30 ) );
70 if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
71 return 0;
72 }
76 73
77 /* Swap pointers */ 74 /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
78 Aold_QA = Anew_QA; 75 mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
79 Anew_QA = A_QA[ k & 1 ]; 76 rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
80 77
81 /* Update AR coefficient */ 78 /* Update AR coefficient */
82 for( n = 0; n < k; n++ ) { 79 for( n = 0; n < (k + 1) >> 1; n++ ) {
83 tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 ); 80 opus_int64 tmp64;
84 Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q ); 81 tmp1 = A_QA[ n ];
82 tmp2 = A_QA[ k - n - 1 ];
83 tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
84 MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
85 if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
86 return 0;
87 }
88 A_QA[ n ] = ( opus_int32 )tmp64;
89 tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
90 MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
91 if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
92 return 0;
93 }
94 A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
85 } 95 }
86 } 96 }
87 97
88 /* Check for stability */ 98 /* Check for stability */
89 if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { 99 if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
90 return 0; 100 return 0;
91 } 101 }
92 102
93 /* Set RC equal to negated AR coef */ 103 /* Set RC equal to negated AR coef */
94 rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA ); 104 rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
95 105
96 /* Range: [ 1 : 2^30 ] */ 106 /* Range: [ 1 : 2^30 ] */
97 rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); 107 rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
98 108
99 /* Update inverse gain */ 109 /* Update inverse gain */
100 /* Range: [ 0 : 2^30 ] */ 110 /* Range: [ 0 : 2^30 ] */
101 invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); 111 invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
102 silk_assert( invGain_Q30 >= 0 ); 112 silk_assert( invGain_Q30 >= 0 );
103 silk_assert( invGain_Q30 <= 1<<30 ); 113 silk_assert( invGain_Q30 <= ( 1 << 30 ) );
114 if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
115 return 0;
116 }
104 117
105 return invGain_Q30; 118 return invGain_Q30;
106} 119}
107 120
108/* For input in Q12 domain */ 121/* For input in Q12 domain */
109opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */ 122opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
110 const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */ 123 const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
111 const opus_int order /* I Prediction order */ 124 const opus_int order /* I Prediction order */
112) 125)
113{ 126{
114 opus_int k; 127 opus_int k;
115 opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; 128 opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
116 opus_int32 *Anew_QA;
117 opus_int32 DC_resp = 0; 129 opus_int32 DC_resp = 0;
118 130
119 Anew_QA = Atmp_QA[ order & 1 ];
120
121 /* Increase Q domain of the AR coefficients */ 131 /* Increase Q domain of the AR coefficients */
122 for( k = 0; k < order; k++ ) { 132 for( k = 0; k < order; k++ ) {
123 DC_resp += (opus_int32)A_Q12[ k ]; 133 DC_resp += (opus_int32)A_Q12[ k ];
124 Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 ); 134 Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
125 } 135 }
126 /* If the DC is unstable, we don't even need to do the full calculations */ 136 /* If the DC is unstable, we don't even need to do the full calculations */
127 if( DC_resp >= 4096 ) { 137 if( DC_resp >= 4096 ) {
128 return 0; 138 return 0;
129 } 139 }
130 return LPC_inverse_pred_gain_QA( Atmp_QA, order ); 140 return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
131} 141}
132
133#ifdef FIXED_POINT
134
135#if 0
136/* For input in Q24 domain */
137opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */
138 const opus_int32 *A_Q24, /* I Prediction coefficients [order] */
139 const opus_int order /* I Prediction order */
140)
141{
142 opus_int k;
143 opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
144 opus_int32 *Anew_QA;
145
146 Anew_QA = Atmp_QA[ order & 1 ];
147
148 /* Increase Q domain of the AR coefficients */
149 for( k = 0; k < order; k++ ) {
150 Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA );
151 }
152
153 return LPC_inverse_pred_gain_QA( Atmp_QA, order );
154}
155#endif
156#endif