Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h" /* Compilation switches */
6 : // #include "prot_fx.h" /* Function prototypes */
7 : #include "prot_fx.h" /* Function prototypes */
8 : #include "prot_fx_enc.h" /* Function prototypes */
9 : #include "cnst.h" /* Common constants */
10 : #include "basop_util.h"
11 : #include "stl.h"
12 :
13 :
14 9458 : void find_targets_fx(
15 : const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/
16 : const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/
17 : const Word16 i_subfr, /* i : subframe index Q0*/
18 : Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/
19 : const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/
20 : const Word16 *res, /* i : residual signal Q_new*/
21 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0*/
22 : const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/
23 : Word16 tilt_fac, /* i : tilt factor Q15*/
24 : Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/
25 : Word16 *cn, /* o : target vector in residual domain Q_new*/
26 : Word16 *h1 /* o : impulse response of weighted synthesis filter Q14*/
27 : )
28 : {
29 : Word16 i;
30 : Word16 temp[M + 6 * L_SUBFR]; /* error of quantization */
31 : Word16 scale, scaleq, j, d, s, s2, tmp;
32 : Word16 Aqs[M + 1];
33 : Word32 Ltmp;
34 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
35 9458 : Flag Overflow = 0;
36 9458 : move32();
37 : #endif
38 : /*------------------------------------------------------------------------*
39 : * Find the target vector for excitation search:
40 : *
41 : * |------| res[n]
42 : * speech[n]---| A(z) |--------
43 : * |------| | |--------| error[n] |------|
44 : * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
45 : * exc |--------| |------|
46 : *
47 : * Instead of subtracting the zero-input response of filters from
48 : * the weighted input speech, the above configuration is used to
49 : * compute the target vector.
50 : *-----------------------------------------------------------------------*/
51 160786 : FOR( i = 0; i < M; i++ )
52 : {
53 151328 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
54 151328 : move16();
55 : }
56 9458 : Syn_filt_s( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 ); /* error in Q_new -1 */
57 :
58 9458 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new -1*/
59 :
60 9458 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new -1 */
61 :
62 :
63 : /*-----------------------------------------------------------------*
64 : * Find target in residual domain (cn[]) for innovation search
65 : *--------------------------------------------------------------*/
66 9458 : IF( cn != NULL )
67 : {
68 : /* first half: xn[] --> cn[] */
69 9448 : temp[0] = 0;
70 9448 : move16();
71 9448 : preemph_copy_fx( xn, cn, tilt_fac, L_SUBFR / 2, temp );
72 9448 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_SUBFR / 2 ); /* Q-1 -> Q-2 */
73 9448 : Residu3_lc_fx( p_Aq, M, temp, cn, L_SUBFR / 2, 1 ); /* Q-2 -> Q-1 */
74 9448 : Scale_sig( cn, L_SUBFR / 2, 1 );
75 :
76 : /* second half: res[] --> cn[] (approximated and faster) */
77 9448 : Copy( &res[i_subfr + ( L_SUBFR / 2 )], cn + ( L_SUBFR / 2 ), L_SUBFR / 2 ); /* Q_new */
78 : }
79 :
80 : /*---------------------------------------------------------------*
81 : * Compute impulse response, h1[], of weighted synthesis filter *
82 : *---------------------------------------------------------------*/
83 :
84 9458 : scale = norm_s( Ap[0] );
85 9458 : scaleq = norm_s( p_Aq[0] );
86 9458 : d = sub( scaleq, scale );
87 9458 : IF( d >= 0 )
88 : {
89 9452 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
90 9452 : s = add( scaleq, 1 );
91 9452 : s2 = shr( 16384, d );
92 : }
93 : ELSE
94 : {
95 6 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
96 6 : s = add( scale, 1 );
97 6 : s2 = 16384;
98 : }
99 9458 : Overflow = 0;
100 9458 : move16();
101 160786 : FOR( i = 0; i < M; i++ )
102 : {
103 151328 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
104 1286288 : FOR( j = 1; j <= i; j++ )
105 : {
106 1134960 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
107 : }
108 151328 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
109 : }
110 9458 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
111 160786 : FOR( j = 1; j <= M; j++ )
112 : {
113 151328 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
114 : }
115 9458 : h1[M] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
116 :
117 : // PMT("should we used extended basop here for when the L_subfr > L_SUBFR, to prevent saturation/overflow and the subsequent loop\n")
118 454624 : FOR( i = M + 1; i < L_subfr; i++ )
119 : {
120 445166 : Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); /* Q27 */
121 7122656 : FOR( j = 2; j <= M; j++ )
122 : {
123 6677490 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
124 : }
125 445166 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
126 : }
127 9458 : IF( Overflow )
128 : {
129 0 : s2 = shr( s2, 1 );
130 0 : FOR( i = 0; i < M; i++ )
131 : {
132 0 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
133 0 : FOR( j = 1; j <= i; j++ )
134 : {
135 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
136 : }
137 0 : h1[i] = round_fx( L_shl_o( Ltmp, s, &Overflow ) ); /* Q11 + s */
138 : }
139 0 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
140 0 : FOR( j = 1; j <= M; j++ )
141 : {
142 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
143 : }
144 0 : h1[M] = round_fx( L_shl( Ltmp, s ) ); /* Q11 + s */
145 0 : FOR( i = M + 1; i < L_subfr; i++ )
146 : {
147 0 : Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); /* Q27 */
148 0 : FOR( j = 2; j <= M; j++ )
149 : {
150 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
151 : }
152 0 : h1[i] = round_fx( L_shl( Ltmp, s ) ); /* Q11 + s */
153 : }
154 : }
155 :
156 9458 : tmp = 0;
157 9458 : Deemph2( h1, tilt_fac, L_subfr, &tmp );
158 :
159 9458 : return;
160 : }
161 :
162 634227 : void find_targets_ivas_fx(
163 : const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/
164 : const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/
165 : const Word16 i_subfr, /* i : subframe index Q0*/
166 : Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/
167 : const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/
168 : const Word16 *res, /* i : residual signal Q_new*/
169 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0*/
170 : const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/
171 : Word16 tilt_fac, /* i : tilt factor Q15*/
172 : Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/
173 : Word16 *cn, /* o : target vector in residual domain Q_new*/
174 : Word16 *h1 /* o : impulse response of weighted synthesis filter Q(14 - norm_s(h1[0]))*/
175 : )
176 : {
177 : Word16 i;
178 : Word16 temp[M + 6 * L_SUBFR]; /* error of quantization */
179 : Word16 scale, scaleq, j, d, s, s2, tmp;
180 : Word16 Aqs[M + 1];
181 : Word32 h1_32[6 * L_SUBFR];
182 : Word16 sf;
183 : Word64 Ltmp64;
184 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
185 634227 : Flag Overflow = 0;
186 634227 : move16();
187 : #endif
188 : /*------------------------------------------------------------------------*
189 : * Find the target vector for excitation search:
190 : *
191 : * |------| res[n]
192 : * speech[n]---| A(z) |--------
193 : * |------| | |--------| error[n] |------|
194 : * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
195 : * exc |--------| |------|
196 : *
197 : * Instead of subtracting the zero-input response of filters from
198 : * the weighted input speech, the above configuration is used to
199 : * compute the target vector.
200 : *-----------------------------------------------------------------------*/
201 10781859 : FOR( i = 0; i < M; i++ )
202 : {
203 10147632 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
204 10147632 : move16();
205 : }
206 :
207 634227 : syn_filt_fx( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 );
208 :
209 634227 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new - 1 */
210 :
211 634227 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new - 1 */
212 :
213 :
214 : /*-----------------------------------------------------------------*
215 : * Find target in residual domain (cn[]) for innovation search
216 : *--------------------------------------------------------------*/
217 634227 : IF( cn != NULL )
218 : {
219 : /* first half: xn[] --> cn[] */
220 634227 : temp[0] = 0;
221 634227 : move16();
222 634227 : preemph_copy_fx( xn, cn, tilt_fac, L_subfr / 2, temp );
223 634227 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_subfr / 2 ); /* Q-1 -> Q-2 */
224 634227 : Residu3_lc_fx( p_Aq, M, temp, cn, L_subfr / 2, 1 ); /* Q-2 -> Q-1 */
225 634227 : Scale_sig( cn, L_subfr / 2, 1 );
226 :
227 : /* second half: res[] --> cn[] (approximated and faster) */
228 634227 : Copy( &res[i_subfr + ( L_subfr / 2 )], cn + ( L_subfr / 2 ), L_subfr / 2 );
229 : }
230 :
231 : /*---------------------------------------------------------------*
232 : * Compute impulse response, h1[], of weighted synthesis filter *
233 : *---------------------------------------------------------------*/
234 :
235 634227 : scale = norm_s( Ap[0] );
236 634227 : scaleq = norm_s( p_Aq[0] );
237 634227 : d = sub( scaleq, scale );
238 634227 : IF( d >= 0 )
239 : {
240 634227 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
241 634227 : s = add( scaleq, 1 );
242 634227 : s2 = shr( 16384, d );
243 : }
244 : ELSE
245 : {
246 0 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
247 0 : s = add( scale, 1 );
248 0 : s2 = 16384;
249 0 : move16();
250 : }
251 :
252 634227 : set32_fx( h1_32, 0, L_subfr );
253 634227 : Overflow = 0;
254 634227 : move16();
255 10781859 : FOR( i = 0; i < M; i++ )
256 : {
257 10147632 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
258 86254872 : FOR( j = 1; j <= i; j++ )
259 : {
260 76107240 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
261 : }
262 10147632 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
263 10147632 : move32();
264 : }
265 :
266 634227 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
267 10781859 : FOR( j = 1; j <= M; j++ )
268 : {
269 10147632 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
270 : }
271 634227 : h1_32[M] = W_extract_l( Ltmp64 ); /* Q27 */
272 634227 : move32();
273 :
274 32622096 : FOR( i = M + 1; i < L_subfr; i++ )
275 : {
276 31987869 : Ltmp64 = W_msu_16_16( 0, Aqs[1], extract_h( L_shl_o( h1_32[i - 1], s, &Overflow ) ) ); /* Q27 */
277 511805904 : FOR( j = 2; j <= M; j++ )
278 : {
279 479818035 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
280 : }
281 31987869 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
282 31987869 : move32();
283 : }
284 :
285 634227 : sf = sub( L_norm_arr( h1_32, L_subfr ), 1 );
286 634227 : Copy_Scale_sig32_16( h1_32, h1, L_subfr, sf ); // Q11 + sf
287 :
288 634227 : tmp = 0;
289 634227 : move16();
290 634227 : Deemph2( h1, tilt_fac, L_subfr, &tmp ); // Q11 + sf - 1
291 :
292 634227 : return;
293 : }
|