diff options
author | William Wilgus <me.theuser@yahoo.com> | 2019-01-04 02:01:18 -0600 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2021-04-23 14:23:04 +0000 |
commit | 14c6bb798d6bebc80f07e863236adbaf8d156a9c (patch) | |
tree | 551a4b641906c2626af844fa3239c1b2b1ff0ad3 /lib/rbcodec/codecs/libopus/silk/LPC_inv_pred_gain.c | |
parent | 75d93937965ec4df70d37df6d4feea04577c996b (diff) | |
download | rockbox-14c6bb798d6bebc80f07e863236adbaf8d156a9c.tar.gz rockbox-14c6bb798d6bebc80f07e863236adbaf8d156a9c.zip |
Sync opus codec to upstream git
Change-Id: I0cfcc0005c4ad7bfbb1aaf454188ce70fb043dc1
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.c | 99 |
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) */ |
41 | static opus_int32 LPC_inverse_pred_gain_QA( /* O Returns inverse prediction gain in energy domain, Q30 */ | 42 | static 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 */ |
109 | opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */ | 122 | opus_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 */ | ||
137 | opus_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 | ||