Line | Count | Source (jump to first uncovered line) |
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 "main.h" |
33 | | #include "stack_alloc.h" |
34 | | |
35 | | /* Generates excitation for CNG LPC synthesis */ |
36 | | static OPUS_INLINE void silk_CNG_exc( |
37 | | opus_int32 exc_Q14[], /* O CNG excitation signal Q10 */ |
38 | | opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */ |
39 | | opus_int length, /* I Length */ |
40 | | opus_int32 *rand_seed /* I/O Seed to random index generator */ |
41 | | ) |
42 | 0 | { |
43 | 0 | opus_int32 seed; |
44 | 0 | opus_int i, idx, exc_mask; |
45 | |
|
46 | 0 | exc_mask = CNG_BUF_MASK_MAX; |
47 | 0 | while( exc_mask > length ) { |
48 | 0 | exc_mask = silk_RSHIFT( exc_mask, 1 ); |
49 | 0 | } |
50 | |
|
51 | 0 | seed = *rand_seed; |
52 | 0 | for( i = 0; i < length; i++ ) { |
53 | 0 | seed = silk_RAND( seed ); |
54 | 0 | idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask ); |
55 | 0 | silk_assert( idx >= 0 ); |
56 | 0 | silk_assert( idx <= CNG_BUF_MASK_MAX ); |
57 | 0 | exc_Q14[ i ] = exc_buf_Q14[ idx ]; |
58 | 0 | } |
59 | 0 | *rand_seed = seed; |
60 | 0 | } |
61 | | |
62 | | void silk_CNG_Reset( |
63 | | silk_decoder_state *psDec /* I/O Decoder state */ |
64 | | ) |
65 | 0 | { |
66 | 0 | opus_int i, NLSF_step_Q15, NLSF_acc_Q15; |
67 | |
|
68 | 0 | NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 ); |
69 | 0 | NLSF_acc_Q15 = 0; |
70 | 0 | for( i = 0; i < psDec->LPC_order; i++ ) { |
71 | 0 | NLSF_acc_Q15 += NLSF_step_Q15; |
72 | 0 | psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15; |
73 | 0 | } |
74 | 0 | psDec->sCNG.CNG_smth_Gain_Q16 = 0; |
75 | 0 | psDec->sCNG.rand_seed = 3176576; |
76 | 0 | } |
77 | | |
78 | | /* Updates CNG estimate, and applies the CNG when packet was lost */ |
79 | | void silk_CNG( |
80 | | silk_decoder_state *psDec, /* I/O Decoder state */ |
81 | | silk_decoder_control *psDecCtrl, /* I/O Decoder control */ |
82 | | opus_int16 frame[], /* I/O Signal */ |
83 | | opus_int length /* I Length of residual */ |
84 | | ) |
85 | 0 | { |
86 | 0 | opus_int i, subfr; |
87 | 0 | opus_int32 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10; |
88 | 0 | opus_int16 A_Q12[ MAX_LPC_ORDER ]; |
89 | 0 | silk_CNG_struct *psCNG = &psDec->sCNG; |
90 | 0 | SAVE_STACK; |
91 | |
|
92 | 0 | if( psDec->fs_kHz != psCNG->fs_kHz ) { |
93 | | /* Reset state */ |
94 | 0 | silk_CNG_Reset( psDec ); |
95 | |
|
96 | 0 | psCNG->fs_kHz = psDec->fs_kHz; |
97 | 0 | } |
98 | 0 | if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) { |
99 | | /* Update CNG parameters */ |
100 | | |
101 | | /* Smoothing of LSF's */ |
102 | 0 | for( i = 0; i < psDec->LPC_order; i++ ) { |
103 | 0 | psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( (opus_int32)psDec->prevNLSF_Q15[ i ] - (opus_int32)psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 ); |
104 | 0 | } |
105 | | /* Find the subframe with the highest gain */ |
106 | 0 | max_Gain_Q16 = 0; |
107 | 0 | subfr = 0; |
108 | 0 | for( i = 0; i < psDec->nb_subfr; i++ ) { |
109 | 0 | if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) { |
110 | 0 | max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ]; |
111 | 0 | subfr = i; |
112 | 0 | } |
113 | 0 | } |
114 | | /* Update CNG excitation buffer with excitation from this subframe */ |
115 | 0 | silk_memmove( &psCNG->CNG_exc_buf_Q14[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q14, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) ); |
116 | 0 | silk_memcpy( psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) ); |
117 | | |
118 | | /* Smooth gains */ |
119 | 0 | for( i = 0; i < psDec->nb_subfr; i++ ) { |
120 | 0 | psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 ); |
121 | | /* If the smoothed gain is 3 dB greater than this subframe's gain, use this subframe's gain to adapt faster. */ |
122 | 0 | if( silk_SMULWW( psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_THRESHOLD_Q16 ) > psDecCtrl->Gains_Q16[ i ] ) { |
123 | 0 | psCNG->CNG_smth_Gain_Q16 = psDecCtrl->Gains_Q16[ i ]; |
124 | 0 | } |
125 | 0 | } |
126 | 0 | } |
127 | | |
128 | | /* Add CNG when packet is lost or during DTX */ |
129 | 0 | if( psDec->lossCnt ) { |
130 | 0 | VARDECL( opus_int32, CNG_sig_Q14 ); |
131 | 0 | ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 ); |
132 | | |
133 | | /* Generate CNG excitation */ |
134 | 0 | gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] ); |
135 | 0 | if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) { |
136 | 0 | gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 ); |
137 | 0 | gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 ); |
138 | 0 | gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 ); |
139 | 0 | } else { |
140 | 0 | gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 ); |
141 | 0 | gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 ); |
142 | 0 | gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 ); |
143 | 0 | } |
144 | 0 | gain_Q10 = silk_RSHIFT( gain_Q16, 6 ); |
145 | |
|
146 | 0 | silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed ); |
147 | | |
148 | | /* Convert CNG NLSF to filter representation */ |
149 | 0 | silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch ); |
150 | | |
151 | | /* Generate CNG signal, by synthesis filtering */ |
152 | 0 | silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); |
153 | 0 | celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); |
154 | 0 | for( i = 0; i < length; i++ ) { |
155 | | /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ |
156 | 0 | LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 ); |
157 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); |
158 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); |
159 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); |
160 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); |
161 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); |
162 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); |
163 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); |
164 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); |
165 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); |
166 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); |
167 | 0 | if( psDec->LPC_order == 16 ) { |
168 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] ); |
169 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] ); |
170 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] ); |
171 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] ); |
172 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] ); |
173 | 0 | LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] ); |
174 | 0 | } |
175 | | |
176 | | /* Update states */ |
177 | 0 | CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) ); |
178 | | |
179 | | /* Scale with Gain and add to input signal */ |
180 | 0 | frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) ); |
181 | |
|
182 | 0 | } |
183 | 0 | silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); |
184 | 0 | } else { |
185 | 0 | silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) ); |
186 | 0 | } |
187 | 0 | RESTORE_STACK; |
188 | 0 | } |