|
1 /*********************************************************************** |
|
2 Copyright (c) 2006-2011, Skype Limited. All rights reserved. |
|
3 Redistribution and use in source and binary forms, with or without |
|
4 modification, are permitted provided that the following conditions |
|
5 are met: |
|
6 - Redistributions of source code must retain the above copyright notice, |
|
7 this list of conditions and the following disclaimer. |
|
8 - Redistributions in binary form must reproduce the above copyright |
|
9 notice, this list of conditions and the following disclaimer in the |
|
10 documentation and/or other materials provided with the distribution. |
|
11 - Neither the name of Internet Society, IETF or IETF Trust, nor the |
|
12 names of specific contributors, may be used to endorse or promote |
|
13 products derived from this software without specific prior written |
|
14 permission. |
|
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
18 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
|
19 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
21 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
22 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
23 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
24 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
25 POSSIBILITY OF SUCH DAMAGE. |
|
26 ***********************************************************************/ |
|
27 |
|
28 #ifdef HAVE_CONFIG_H |
|
29 #include "config.h" |
|
30 #endif |
|
31 |
|
32 #include "SigProc_FIX.h" |
|
33 |
|
34 #define QA 24 |
|
35 #define A_LIMIT SILK_FIX_CONST( 0.99975, QA ) |
|
36 |
|
37 #define MUL32_FRAC_Q(a32, b32, Q) ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q))) |
|
38 |
|
39 /* Compute inverse of LPC prediction gain, and */ |
|
40 /* 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 opus_int32 A_QA[ 2 ][ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */ |
|
43 const opus_int order /* I Prediction order */ |
|
44 ) |
|
45 { |
|
46 opus_int k, n, mult2Q; |
|
47 opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA; |
|
48 opus_int32 *Aold_QA, *Anew_QA; |
|
49 |
|
50 Anew_QA = A_QA[ order & 1 ]; |
|
51 |
|
52 invGain_Q30 = (opus_int32)1 << 30; |
|
53 for( k = order - 1; k > 0; k-- ) { |
|
54 /* Check for stability */ |
|
55 if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { |
|
56 return 0; |
|
57 } |
|
58 |
|
59 /* Set RC equal to negated AR coef */ |
|
60 rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA ); |
|
61 |
|
62 /* rc_mult1_Q30 range: [ 1 : 2^30 ] */ |
|
63 rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); |
|
64 silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */ |
|
65 silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) ); |
|
66 |
|
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 */ |
|
72 /* invGain_Q30 range: [ 0 : 2^30 ] */ |
|
73 invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); |
|
74 silk_assert( invGain_Q30 >= 0 ); |
|
75 silk_assert( invGain_Q30 <= ( 1 << 30 ) ); |
|
76 |
|
77 /* Swap pointers */ |
|
78 Aold_QA = Anew_QA; |
|
79 Anew_QA = A_QA[ k & 1 ]; |
|
80 |
|
81 /* Update AR coefficient */ |
|
82 for( n = 0; n < k; n++ ) { |
|
83 tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 ); |
|
84 Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q ); |
|
85 } |
|
86 } |
|
87 |
|
88 /* Check for stability */ |
|
89 if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { |
|
90 return 0; |
|
91 } |
|
92 |
|
93 /* Set RC equal to negated AR coef */ |
|
94 rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA ); |
|
95 |
|
96 /* Range: [ 1 : 2^30 ] */ |
|
97 rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); |
|
98 |
|
99 /* Update inverse gain */ |
|
100 /* Range: [ 0 : 2^30 ] */ |
|
101 invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); |
|
102 silk_assert( invGain_Q30 >= 0 ); |
|
103 silk_assert( invGain_Q30 <= 1<<30 ); |
|
104 |
|
105 return invGain_Q30; |
|
106 } |
|
107 |
|
108 /* For input in Q12 domain */ |
|
109 opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */ |
|
110 const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */ |
|
111 const opus_int order /* I Prediction order */ |
|
112 ) |
|
113 { |
|
114 opus_int k; |
|
115 opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; |
|
116 opus_int32 *Anew_QA; |
|
117 opus_int32 DC_resp = 0; |
|
118 |
|
119 Anew_QA = Atmp_QA[ order & 1 ]; |
|
120 |
|
121 /* Increase Q domain of the AR coefficients */ |
|
122 for( k = 0; k < order; k++ ) { |
|
123 DC_resp += (opus_int32)A_Q12[ k ]; |
|
124 Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 ); |
|
125 } |
|
126 /* If the DC is unstable, we don't even need to do the full calculations */ |
|
127 if( DC_resp >= 4096 ) { |
|
128 return 0; |
|
129 } |
|
130 return LPC_inverse_pred_gain_QA( Atmp_QA, order ); |
|
131 } |
|
132 |
|
133 #ifdef FIXED_POINT |
|
134 |
|
135 /* For input in Q24 domain */ |
|
136 opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */ |
|
137 const opus_int32 *A_Q24, /* I Prediction coefficients [order] */ |
|
138 const opus_int order /* I Prediction order */ |
|
139 ) |
|
140 { |
|
141 opus_int k; |
|
142 opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; |
|
143 opus_int32 *Anew_QA; |
|
144 |
|
145 Anew_QA = Atmp_QA[ order & 1 ]; |
|
146 |
|
147 /* Increase Q domain of the AR coefficients */ |
|
148 for( k = 0; k < order; k++ ) { |
|
149 Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA ); |
|
150 } |
|
151 |
|
152 return LPC_inverse_pred_gain_QA( Atmp_QA, order ); |
|
153 } |
|
154 #endif |