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 0 : h1[i] = round_fx( L_shl_sat( Ltmp, s ) ); /* 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 9435 : tmp = 0;
157 9435 : Deemph2( h1, tilt_fac, L_subfr, &tmp );
158 :
159 9435 : return;
160 : }
161 :
162 635786 : 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 :
185 : /*------------------------------------------------------------------------*
186 : * Find the target vector for excitation search:
187 : *
188 : * |------| res[n]
189 : * speech[n]---| A(z) |--------
190 : * |------| | |--------| error[n] |------|
191 : * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
192 : * exc |--------| |------|
193 : *
194 : * Instead of subtracting the zero-input response of filters from
195 : * the weighted input speech, the above configuration is used to
196 : * compute the target vector.
197 : *-----------------------------------------------------------------------*/
198 10808362 : FOR( i = 0; i < M; i++ )
199 : {
200 10172576 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
201 10172576 : move16();
202 : }
203 :
204 635786 : syn_filt_fx( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 );
205 :
206 635786 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new - 1 */
207 :
208 635786 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new - 1 */
209 :
210 :
211 : /*-----------------------------------------------------------------*
212 : * Find target in residual domain (cn[]) for innovation search
213 : *--------------------------------------------------------------*/
214 635786 : IF( cn != NULL )
215 : {
216 : /* first half: xn[] --> cn[] */
217 635786 : temp[0] = 0;
218 635786 : move16();
219 635786 : preemph_copy_fx( xn, cn, tilt_fac, L_subfr / 2, temp );
220 635786 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_subfr / 2 ); /* Q-1 -> Q-2 */
221 635786 : Residu3_lc_fx( p_Aq, M, temp, cn, L_subfr / 2, 1 ); /* Q-2 -> Q-1 */
222 635786 : Scale_sig( cn, L_subfr / 2, 1 );
223 :
224 : /* second half: res[] --> cn[] (approximated and faster) */
225 635786 : Copy( &res[i_subfr + ( L_subfr / 2 )], cn + ( L_subfr / 2 ), L_subfr / 2 );
226 : }
227 :
228 : /*---------------------------------------------------------------*
229 : * Compute impulse response, h1[], of weighted synthesis filter *
230 : *---------------------------------------------------------------*/
231 :
232 635786 : scale = norm_s( Ap[0] );
233 635786 : scaleq = norm_s( p_Aq[0] );
234 635786 : d = sub( scaleq, scale );
235 635786 : IF( d >= 0 )
236 : {
237 635786 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
238 635786 : s = add( scaleq, 1 );
239 635786 : s2 = shr( 16384, d );
240 : }
241 : ELSE
242 : {
243 0 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
244 0 : s = add( scale, 1 );
245 0 : s2 = 16384;
246 0 : move16();
247 : }
248 :
249 635786 : set32_fx( h1_32, 0, L_subfr );
250 10808362 : FOR( i = 0; i < M; i++ )
251 : {
252 10172576 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
253 86466896 : FOR( j = 1; j <= i; j++ )
254 : {
255 76294320 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
256 : }
257 10172576 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
258 10172576 : move32();
259 : }
260 :
261 635786 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
262 10808362 : FOR( j = 1; j <= M; j++ )
263 : {
264 10172576 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
265 : }
266 635786 : h1_32[M] = W_extract_l( Ltmp64 ); /* Q27 */
267 635786 : move32();
268 :
269 32699168 : FOR( i = M + 1; i < L_subfr; i++ )
270 : {
271 32063382 : Ltmp64 = W_msu_16_16( 0, Aqs[1], extract_h( L_shl_sat( h1_32[i - 1], s ) ) ); /* Q27 */
272 513014112 : FOR( j = 2; j <= M; j++ )
273 : {
274 480950730 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
275 : }
276 32063382 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
277 32063382 : move32();
278 : }
279 :
280 635786 : sf = sub( L_norm_arr( h1_32, L_subfr ), 1 );
281 635786 : Copy_Scale_sig32_16( h1_32, h1, L_subfr, sf ); // Q11 + sf
282 :
283 635786 : tmp = 0;
284 635786 : move16();
285 635786 : Deemph2( h1, tilt_fac, L_subfr, &tmp ); // Q11 + sf - 1
286 :
287 635786 : return;
288 : }
|