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 9435 : 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 9435 : Flag Overflow = 0;
36 9435 : 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 160395 : FOR( i = 0; i < M; i++ )
52 : {
53 150960 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
54 150960 : move16();
55 : }
56 9435 : Syn_filt_s( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 ); /* error in Q_new -1 */
57 :
58 9435 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new -1*/
59 :
60 9435 : 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 9435 : IF( cn != NULL )
67 : {
68 : /* first half: xn[] --> cn[] */
69 9419 : temp[0] = 0;
70 9419 : move16();
71 9419 : preemph_copy_fx( xn, cn, tilt_fac, L_SUBFR / 2, temp );
72 9419 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_SUBFR / 2 ); /* Q-1 -> Q-2 */
73 9419 : Residu3_lc_fx( p_Aq, M, temp, cn, L_SUBFR / 2, 1 ); /* Q-2 -> Q-1 */
74 9419 : Scale_sig( cn, L_SUBFR / 2, 1 );
75 :
76 : /* second half: res[] --> cn[] (approximated and faster) */
77 9419 : 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 9435 : scale = norm_s( Ap[0] );
85 9435 : scaleq = norm_s( p_Aq[0] );
86 9435 : d = sub( scaleq, scale );
87 9435 : IF( d >= 0 )
88 : {
89 9432 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
90 9432 : s = add( scaleq, 1 );
91 9432 : s2 = shr( 16384, d );
92 : }
93 : ELSE
94 : {
95 3 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
96 3 : s = add( scale, 1 );
97 3 : s2 = 16384;
98 : }
99 9435 : Overflow = 0;
100 9435 : move16();
101 160395 : FOR( i = 0; i < M; i++ )
102 : {
103 150960 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
104 1283160 : FOR( j = 1; j <= i; j++ )
105 : {
106 1132200 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
107 : }
108 150960 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
109 : }
110 9435 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
111 160395 : FOR( j = 1; j <= M; j++ )
112 : {
113 150960 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
114 : }
115 9435 : 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 453904 : FOR( i = M + 1; i < L_subfr; i++ )
119 : {
120 444469 : Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); /* Q27 */
121 7111504 : FOR( j = 2; j <= M; j++ )
122 : {
123 6667035 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
124 : }
125 444469 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
126 : }
127 9435 : 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 : #ifdef ISSUE_1867_replace_overflow_libenc
138 0 : h1[i] = round_fx( L_shl_sat( Ltmp, s ) ); /* Q11 + s */
139 : #else
140 : h1[i] = round_fx( L_shl_o( Ltmp, s, &Overflow ) ); /* Q11 + s */
141 : #endif
142 : }
143 0 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
144 0 : FOR( j = 1; j <= M; j++ )
145 : {
146 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
147 : }
148 0 : h1[M] = round_fx( L_shl( Ltmp, s ) ); /* Q11 + s */
149 0 : FOR( i = M + 1; i < L_subfr; i++ )
150 : {
151 0 : Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); /* Q27 */
152 0 : FOR( j = 2; j <= M; j++ )
153 : {
154 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
155 : }
156 0 : h1[i] = round_fx( L_shl( Ltmp, s ) ); /* Q11 + s */
157 : }
158 : }
159 :
160 9435 : tmp = 0;
161 9435 : Deemph2( h1, tilt_fac, L_subfr, &tmp );
162 :
163 9435 : return;
164 : }
165 :
166 635982 : void find_targets_ivas_fx(
167 : const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/
168 : const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/
169 : const Word16 i_subfr, /* i : subframe index Q0*/
170 : Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/
171 : const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/
172 : const Word16 *res, /* i : residual signal Q_new*/
173 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0*/
174 : const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/
175 : Word16 tilt_fac, /* i : tilt factor Q15*/
176 : Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/
177 : Word16 *cn, /* o : target vector in residual domain Q_new*/
178 : Word16 *h1 /* o : impulse response of weighted synthesis filter Q(14 - norm_s(h1[0]))*/
179 : )
180 : {
181 : Word16 i;
182 : Word16 temp[M + 6 * L_SUBFR]; /* error of quantization */
183 : Word16 scale, scaleq, j, d, s, s2, tmp;
184 : Word16 Aqs[M + 1];
185 : Word32 h1_32[6 * L_SUBFR];
186 : Word16 sf;
187 : Word64 Ltmp64;
188 : #ifndef ISSUE_1867_replace_overflow_libenc
189 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
190 : Flag Overflow = 0;
191 : move16();
192 : #endif
193 : #endif
194 : /*------------------------------------------------------------------------*
195 : * Find the target vector for excitation search:
196 : *
197 : * |------| res[n]
198 : * speech[n]---| A(z) |--------
199 : * |------| | |--------| error[n] |------|
200 : * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
201 : * exc |--------| |------|
202 : *
203 : * Instead of subtracting the zero-input response of filters from
204 : * the weighted input speech, the above configuration is used to
205 : * compute the target vector.
206 : *-----------------------------------------------------------------------*/
207 10811694 : FOR( i = 0; i < M; i++ )
208 : {
209 10175712 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
210 10175712 : move16();
211 : }
212 :
213 635982 : syn_filt_fx( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 );
214 :
215 635982 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new - 1 */
216 :
217 635982 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new - 1 */
218 :
219 :
220 : /*-----------------------------------------------------------------*
221 : * Find target in residual domain (cn[]) for innovation search
222 : *--------------------------------------------------------------*/
223 635982 : IF( cn != NULL )
224 : {
225 : /* first half: xn[] --> cn[] */
226 635982 : temp[0] = 0;
227 635982 : move16();
228 635982 : preemph_copy_fx( xn, cn, tilt_fac, L_subfr / 2, temp );
229 635982 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_subfr / 2 ); /* Q-1 -> Q-2 */
230 635982 : Residu3_lc_fx( p_Aq, M, temp, cn, L_subfr / 2, 1 ); /* Q-2 -> Q-1 */
231 635982 : Scale_sig( cn, L_subfr / 2, 1 );
232 :
233 : /* second half: res[] --> cn[] (approximated and faster) */
234 635982 : Copy( &res[i_subfr + ( L_subfr / 2 )], cn + ( L_subfr / 2 ), L_subfr / 2 );
235 : }
236 :
237 : /*---------------------------------------------------------------*
238 : * Compute impulse response, h1[], of weighted synthesis filter *
239 : *---------------------------------------------------------------*/
240 :
241 635982 : scale = norm_s( Ap[0] );
242 635982 : scaleq = norm_s( p_Aq[0] );
243 635982 : d = sub( scaleq, scale );
244 635982 : IF( d >= 0 )
245 : {
246 635982 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
247 635982 : s = add( scaleq, 1 );
248 635982 : s2 = shr( 16384, d );
249 : }
250 : ELSE
251 : {
252 0 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
253 0 : s = add( scale, 1 );
254 0 : s2 = 16384;
255 0 : move16();
256 : }
257 :
258 635982 : set32_fx( h1_32, 0, L_subfr );
259 : #ifndef ISSUE_1867_replace_overflow_libenc
260 : Overflow = 0;
261 : move16();
262 : #endif
263 10811694 : FOR( i = 0; i < M; i++ )
264 : {
265 10175712 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
266 86493552 : FOR( j = 1; j <= i; j++ )
267 : {
268 : #ifdef ISSUE_1867_replace_overflow_libenc
269 76317840 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
270 : #else
271 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
272 : #endif
273 : }
274 10175712 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
275 10175712 : move32();
276 : }
277 :
278 635982 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
279 10811694 : FOR( j = 1; j <= M; j++ )
280 : {
281 : #ifdef ISSUE_1867_replace_overflow_libenc
282 10175712 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
283 : #else
284 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
285 : #endif
286 : }
287 635982 : h1_32[M] = W_extract_l( Ltmp64 ); /* Q27 */
288 635982 : move32();
289 :
290 32704736 : FOR( i = M + 1; i < L_subfr; i++ )
291 : {
292 : #ifdef ISSUE_1867_replace_overflow_libenc
293 32068754 : Ltmp64 = W_msu_16_16( 0, Aqs[1], extract_h( L_shl_sat( h1_32[i - 1], s ) ) ); /* Q27 */
294 : #else
295 : Ltmp64 = W_msu_16_16( 0, Aqs[1], extract_h( L_shl_o( h1_32[i - 1], s, &Overflow ) ) ); /* Q27 */
296 : #endif
297 513100064 : FOR( j = 2; j <= M; j++ )
298 : {
299 : #ifdef ISSUE_1867_replace_overflow_libenc
300 481031310 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
301 : #else
302 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_o( h1_32[i - j], s, &Overflow ) ) ); /* Q27 */
303 : #endif
304 : }
305 32068754 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
306 32068754 : move32();
307 : }
308 :
309 635982 : sf = sub( L_norm_arr( h1_32, L_subfr ), 1 );
310 635982 : Copy_Scale_sig32_16( h1_32, h1, L_subfr, sf ); // Q11 + sf
311 :
312 635982 : tmp = 0;
313 635982 : move16();
314 635982 : Deemph2( h1, tilt_fac, L_subfr, &tmp ); // Q11 + sf - 1
315 :
316 635982 : return;
317 : }
|