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 9410 : 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 9410 : Flag Overflow = 0;
36 9410 : 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 159970 : FOR( i = 0; i < M; i++ )
52 : {
53 150560 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
54 150560 : move16();
55 : }
56 9410 : Syn_filt_s( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 ); /* error in Q_new -1 */
57 :
58 9410 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new -1*/
59 :
60 9410 : 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 9410 : IF( cn != NULL )
67 : {
68 : /* first half: xn[] --> cn[] */
69 9396 : temp[0] = 0;
70 9396 : move16();
71 9396 : preemph_copy_fx( xn, cn, tilt_fac, L_SUBFR / 2, temp );
72 9396 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_SUBFR / 2 ); /* Q-1 -> Q-2 */
73 9396 : Residu3_lc_fx( p_Aq, M, temp, cn, L_SUBFR / 2, 1 ); /* Q-2 -> Q-1 */
74 9396 : Scale_sig( cn, L_SUBFR / 2, 1 );
75 :
76 : /* second half: res[] --> cn[] (approximated and faster) */
77 9396 : 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 9410 : scale = norm_s( Ap[0] );
85 9410 : scaleq = norm_s( p_Aq[0] );
86 9410 : d = sub( scaleq, scale );
87 9410 : IF( d >= 0 )
88 : {
89 9403 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
90 9403 : s = add( scaleq, 1 );
91 9403 : s2 = shr( 16384, d );
92 : }
93 : ELSE
94 : {
95 7 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
96 7 : s = add( scale, 1 );
97 7 : s2 = 16384;
98 : }
99 9410 : Overflow = 0;
100 9410 : move16();
101 159970 : FOR( i = 0; i < M; i++ )
102 : {
103 150560 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
104 1279760 : FOR( j = 1; j <= i; j++ )
105 : {
106 1129200 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
107 : }
108 150560 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
109 : }
110 9410 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
111 159970 : FOR( j = 1; j <= M; j++ )
112 : {
113 150560 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
114 : }
115 9410 : 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 452576 : FOR( i = M + 1; i < L_subfr; i++ )
119 : {
120 443166 : Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); /* Q27 */
121 7090656 : FOR( j = 2; j <= M; j++ )
122 : {
123 6647490 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
124 : }
125 443166 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
126 : }
127 9410 : 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 9410 : tmp = 0;
157 9410 : Deemph2( h1, tilt_fac, L_subfr, &tmp );
158 :
159 9410 : return;
160 : }
161 :
162 8010 : 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 8010 : Flag Overflow = 0;
186 8010 : 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 136170 : FOR( i = 0; i < M; i++ )
202 : {
203 128160 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
204 128160 : move16();
205 : }
206 8010 : Scale_sig( temp, M, 1 ); // scaling to make belong function output alligned //Qnew
207 :
208 8010 : syn_filt_fx( 0, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 );
209 :
210 8010 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new */
211 :
212 8010 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new */
213 :
214 8010 : *mem_w0 = shr( *mem_w0, 1 ); // Q_new - 1
215 :
216 : /*-----------------------------------------------------------------*
217 : * Find target in residual domain (cn[]) for innovation search
218 : *--------------------------------------------------------------*/
219 8010 : IF( cn != NULL )
220 : {
221 : /* first half: xn[] --> cn[] */
222 8010 : temp[0] = 0;
223 8010 : move16();
224 8010 : preemph_copy_fx( xn, cn, tilt_fac, shr( L_subfr, 1 ), temp );
225 8010 : syn_filt_s_lc_fx( 1, Ap, cn, temp, shr( L_subfr, 1 ) ); /* Q_new -> Q_new - 1 */
226 8010 : Residu3_lc_fx( p_Aq, M, temp, cn, shr( L_subfr, 1 ), 1 ); /* Q_new - 1 -> Q_new */
227 :
228 : /* second half: res[] --> cn[] (approximated and faster) */
229 8010 : Copy( &res[i_subfr + shr( L_subfr, 1 )], cn + shr( L_subfr, 1 ), shr( L_subfr, 1 ) ); /* Q_new */
230 : }
231 8010 : scale_sig( xn, L_subfr, -1 ); // Q_new - 1
232 :
233 : /*---------------------------------------------------------------*
234 : * Compute impulse response, h1[], of weighted synthesis filter *
235 : *---------------------------------------------------------------*/
236 :
237 8010 : scale = norm_s( Ap[0] );
238 8010 : scaleq = norm_s( p_Aq[0] );
239 8010 : d = sub( scaleq, scale );
240 8010 : IF( d >= 0 )
241 : {
242 8010 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
243 8010 : s = add( scaleq, 1 );
244 8010 : s2 = shr( 16384, d );
245 : }
246 : ELSE
247 : {
248 0 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
249 0 : s = add( scale, 1 );
250 0 : s2 = 16384;
251 0 : move16();
252 : }
253 :
254 8010 : set32_fx( h1_32, 0, L_subfr );
255 8010 : Overflow = 0;
256 8010 : move16();
257 136170 : FOR( i = 0; i < M; i++ )
258 : {
259 128160 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
260 1089360 : FOR( j = 1; j <= i; j++ )
261 : {
262 961200 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
263 : }
264 128160 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
265 128160 : move32();
266 : }
267 :
268 8010 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
269 136170 : FOR( j = 1; j <= M; j++ )
270 : {
271 128160 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
272 : }
273 8010 : h1_32[M] = W_extract_l( Ltmp64 ); /* Q27 */
274 8010 : move32();
275 :
276 385120 : FOR( i = M + 1; i < L_subfr; i++ )
277 : {
278 377110 : Ltmp64 = W_msu_16_16( 0, Aqs[1], extract_h( L_shl_o( h1_32[i - 1], s, &Overflow ) ) ); /* Q27 */
279 6033760 : FOR( j = 2; j <= M; j++ )
280 : {
281 5656650 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
282 : }
283 377110 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
284 377110 : move32();
285 : }
286 :
287 8010 : sf = sub( L_norm_arr( h1_32, L_subfr ), 1 );
288 8010 : Copy_Scale_sig32_16( h1_32, h1, L_subfr, sf ); // Q11 + sf
289 :
290 8010 : tmp = 0;
291 8010 : move16();
292 8010 : Deemph2( h1, tilt_fac, L_subfr, &tmp ); // Q11 + sf - 1
293 :
294 8010 : return;
295 : }
296 :
297 624522 : void find_targets_ivas_new_fx(
298 : const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/
299 : const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/
300 : const Word16 i_subfr, /* i : subframe index Q0*/
301 : Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/
302 : const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/
303 : const Word16 *res, /* i : residual signal Q_new*/
304 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0*/
305 : const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/
306 : Word16 tilt_fac, /* i : tilt factor Q15*/
307 : Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/
308 : Word16 *cn, /* o : target vector in residual domain Q_new*/
309 : Word16 *h1 /* o : impulse response of weighted synthesis filter Q(14 - norm_s(h1[0]))*/
310 : )
311 : {
312 : Word16 i;
313 : Word16 temp[M + 6 * L_SUBFR]; /* error of quantization */
314 : Word16 scale, scaleq, j, d, s, s2, tmp;
315 : Word16 Aqs[M + 1];
316 : Word32 h1_32[6 * L_SUBFR];
317 : Word16 sf;
318 : Word64 Ltmp64;
319 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
320 624522 : Flag Overflow = 0;
321 624522 : move16();
322 : #endif
323 : /*------------------------------------------------------------------------*
324 : * Find the target vector for excitation search:
325 : *
326 : * |------| res[n]
327 : * speech[n]---| A(z) |--------
328 : * |------| | |--------| error[n] |------|
329 : * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
330 : * exc |--------| |------|
331 : *
332 : * Instead of subtracting the zero-input response of filters from
333 : * the weighted input speech, the above configuration is used to
334 : * compute the target vector.
335 : *-----------------------------------------------------------------------*/
336 10616874 : FOR( i = 0; i < M; i++ )
337 : {
338 9992352 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
339 9992352 : move16();
340 : }
341 :
342 624522 : syn_filt_fx( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 );
343 :
344 624522 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new - 1 */
345 :
346 624522 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new - 1 */
347 :
348 :
349 : /*-----------------------------------------------------------------*
350 : * Find target in residual domain (cn[]) for innovation search
351 : *--------------------------------------------------------------*/
352 624522 : IF( cn != NULL )
353 : {
354 : /* first half: xn[] --> cn[] */
355 624522 : temp[0] = 0;
356 624522 : move16();
357 624522 : preemph_copy_fx( xn, cn, tilt_fac, L_SUBFR / 2, temp );
358 624522 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_SUBFR / 2 ); /* Q-1 -> Q-2 */
359 624522 : Residu3_lc_fx( p_Aq, M, temp, cn, L_SUBFR / 2, 1 ); /* Q-2 -> Q-1 */
360 624522 : Scale_sig( cn, L_SUBFR / 2, 1 );
361 :
362 : /* second half: res[] --> cn[] (approximated and faster) */
363 624522 : Copy( &res[i_subfr + ( L_SUBFR / 2 )], cn + ( L_SUBFR / 2 ), L_SUBFR / 2 );
364 : }
365 :
366 : /*---------------------------------------------------------------*
367 : * Compute impulse response, h1[], of weighted synthesis filter *
368 : *---------------------------------------------------------------*/
369 :
370 624522 : scale = norm_s( Ap[0] );
371 624522 : scaleq = norm_s( p_Aq[0] );
372 624522 : d = sub( scaleq, scale );
373 624522 : IF( d >= 0 )
374 : {
375 624522 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
376 624522 : s = add( scaleq, 1 );
377 624522 : s2 = shr( 16384, d );
378 : }
379 : ELSE
380 : {
381 0 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
382 0 : s = add( scale, 1 );
383 0 : s2 = 16384;
384 0 : move16();
385 : }
386 :
387 624522 : set32_fx( h1_32, 0, L_subfr );
388 624522 : Overflow = 0;
389 624522 : move16();
390 10616874 : FOR( i = 0; i < M; i++ )
391 : {
392 9992352 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
393 84934992 : FOR( j = 1; j <= i; j++ )
394 : {
395 74942640 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
396 : }
397 9992352 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
398 9992352 : move32();
399 : }
400 :
401 624522 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
402 10616874 : FOR( j = 1; j <= M; j++ )
403 : {
404 9992352 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
405 : }
406 624522 : h1_32[M] = W_extract_l( Ltmp64 ); /* Q27 */
407 624522 : move32();
408 :
409 32163808 : FOR( i = M + 1; i < L_subfr; i++ )
410 : {
411 31539286 : Ltmp64 = W_msu_16_16( 0, Aqs[1], extract_h( L_shl_o( h1_32[i - 1], s, &Overflow ) ) ); /* Q27 */
412 504628576 : FOR( j = 2; j <= M; j++ )
413 : {
414 473089290 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
415 : }
416 31539286 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
417 31539286 : move32();
418 : }
419 :
420 624522 : sf = sub( L_norm_arr( h1_32, L_subfr ), 1 );
421 624522 : Copy_Scale_sig32_16( h1_32, h1, L_subfr, sf ); // Q11 + sf
422 :
423 624522 : tmp = 0;
424 624522 : move16();
425 624522 : Deemph2( h1, tilt_fac, L_subfr, &tmp ); // Q11 + sf - 1
426 :
427 624522 : return;
428 : }
|