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 15201 : 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 15201 : Flag Overflow = 0;
35 15201 : move32();
36 : /*------------------------------------------------------------------------*
37 : * Find the target vector for excitation search:
38 : *
39 : * |------| res[n]
40 : * speech[n]---| A(z) |--------
41 : * |------| | |--------| error[n] |------|
42 : * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
43 : * exc |--------| |------|
44 : *
45 : * Instead of subtracting the zero-input response of filters from
46 : * the weighted input speech, the above configuration is used to
47 : * compute the target vector.
48 : *-----------------------------------------------------------------------*/
49 258417 : FOR( i = 0; i < M; i++ )
50 : {
51 243216 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
52 243216 : move16();
53 : }
54 15201 : Syn_filt_s( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 ); /* error in Q_new -1 */
55 :
56 15201 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new -1*/
57 :
58 15201 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new -1 */
59 :
60 :
61 : /*-----------------------------------------------------------------*
62 : * Find target in residual domain (cn[]) for innovation search
63 : *--------------------------------------------------------------*/
64 15201 : IF( cn != NULL )
65 : {
66 : /* first half: xn[] --> cn[] */
67 15185 : temp[0] = 0;
68 15185 : move16();
69 15185 : preemph_copy_fx( xn, cn, tilt_fac, L_SUBFR / 2, temp );
70 15185 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_SUBFR / 2 ); /* Q-1 -> Q-2 */
71 15185 : Residu3_lc_fx( p_Aq, M, temp, cn, L_SUBFR / 2, 1 ); /* Q-2 -> Q-1 */
72 15185 : Scale_sig( cn, L_SUBFR / 2, 1 );
73 :
74 : /* second half: res[] --> cn[] (approximated and faster) */
75 15185 : Copy( &res[i_subfr + ( L_SUBFR / 2 )], cn + ( L_SUBFR / 2 ), L_SUBFR / 2 ); /* Q_new */
76 : }
77 :
78 : /*---------------------------------------------------------------*
79 : * Compute impulse response, h1[], of weighted synthesis filter *
80 : *---------------------------------------------------------------*/
81 :
82 15201 : scale = norm_s( Ap[0] );
83 15201 : scaleq = norm_s( p_Aq[0] );
84 15201 : d = sub( scaleq, scale );
85 15201 : IF( d >= 0 )
86 : {
87 15195 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
88 15195 : s = add( scaleq, 1 );
89 15195 : s2 = shr( 16384, d );
90 : }
91 : ELSE
92 : {
93 6 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
94 6 : s = add( scale, 1 );
95 6 : s2 = 16384;
96 : }
97 15201 : Overflow = 0;
98 15201 : move16();
99 258417 : FOR( i = 0; i < M; i++ )
100 : {
101 243216 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
102 2067336 : FOR( j = 1; j <= i; j++ )
103 : {
104 1824120 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
105 : }
106 243216 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
107 : }
108 15201 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
109 258417 : FOR( j = 1; j <= M; j++ )
110 : {
111 243216 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
112 : }
113 15201 : h1[M] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
114 :
115 730672 : FOR( i = M + 1; i < L_subfr; i++ )
116 : {
117 715471 : Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); /* Q27 */
118 11447536 : FOR( j = 2; j <= M; j++ )
119 : {
120 10732065 : Ltmp = L_msu_o( Ltmp, Aqs[j], h1[i - j], &Overflow ); /* Q27 */
121 : }
122 715471 : h1[i] = round_fx_o( L_shl_o( Ltmp, s, &Overflow ), &Overflow ); /* Q11 + s */
123 : }
124 15201 : IF( Overflow )
125 : {
126 0 : s2 = shr( s2, 1 );
127 0 : FOR( i = 0; i < M; i++ )
128 : {
129 0 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
130 0 : FOR( j = 1; j <= i; j++ )
131 : {
132 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
133 : }
134 0 : h1[i] = round_fx( L_shl_sat( Ltmp, s ) ); /* Q11 + s */
135 : }
136 0 : Ltmp = L_mult( Ap[i], s2 ); /* Q27 */
137 0 : FOR( j = 1; j <= M; j++ )
138 : {
139 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
140 : }
141 0 : h1[M] = round_fx( L_shl( Ltmp, s ) ); /* Q11 + s */
142 0 : FOR( i = M + 1; i < L_subfr; i++ )
143 : {
144 0 : Ltmp = L_msu( 0, Aqs[1], h1[i - 1] ); /* Q27 */
145 0 : FOR( j = 2; j <= M; j++ )
146 : {
147 0 : Ltmp = L_msu( Ltmp, Aqs[j], h1[i - j] ); /* Q27 */
148 : }
149 0 : h1[i] = round_fx( L_shl( Ltmp, s ) ); /* Q11 + s */
150 : }
151 : }
152 :
153 15201 : tmp = 0;
154 15201 : Deemph2( h1, tilt_fac, L_subfr, &tmp );
155 :
156 15201 : return;
157 : }
158 :
159 783679 : void find_targets_ivas_fx(
160 : const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/
161 : const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/
162 : const Word16 i_subfr, /* i : subframe index Q0*/
163 : Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/
164 : const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/
165 : const Word16 *res, /* i : residual signal Q_new*/
166 : const Word16 L_subfr, /* i : length of vectors for gain quantization Q0*/
167 : const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/
168 : Word16 tilt_fac, /* i : tilt factor Q15*/
169 : Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/
170 : Word16 *cn, /* o : target vector in residual domain Q_new*/
171 : Word16 *h1 /* o : impulse response of weighted synthesis filter Q(14 - norm_s(h1[0]))*/
172 : )
173 : {
174 : Word16 i;
175 : Word16 temp[M + 6 * L_SUBFR]; /* error of quantization */
176 : Word16 scale, scaleq, j, d, s, s2, tmp;
177 : Word16 Aqs[M + 1];
178 : Word32 h1_32[6 * L_SUBFR];
179 : Word16 sf;
180 : Word64 Ltmp64;
181 :
182 : /*------------------------------------------------------------------------*
183 : * Find the target vector for excitation search:
184 : *
185 : * |------| res[n]
186 : * speech[n]---| A(z) |--------
187 : * |------| | |--------| error[n] |------|
188 : * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
189 : * exc |--------| |------|
190 : *
191 : * Instead of subtracting the zero-input response of filters from
192 : * the weighted input speech, the above configuration is used to
193 : * compute the target vector.
194 : *-----------------------------------------------------------------------*/
195 13322543 : FOR( i = 0; i < M; i++ )
196 : {
197 12538864 : temp[i] = sub_sat( speech[i + i_subfr - M], mem_syn[i] ); /* Q_new - 1 */
198 12538864 : move16();
199 : }
200 :
201 783679 : syn_filt_fx( 1, p_Aq, M, &res[i_subfr], temp + M, L_subfr, temp, 0 );
202 :
203 783679 : Residu3_fx( Ap, temp + M, xn, L_subfr, 0 ); /* xn in Q_new - 1 */
204 :
205 783679 : deemph_fx( xn, tilt_fac, L_subfr, mem_w0 ); /* xn in Q_new - 1 */
206 :
207 :
208 : /*-----------------------------------------------------------------*
209 : * Find target in residual domain (cn[]) for innovation search
210 : *--------------------------------------------------------------*/
211 783679 : IF( cn != NULL )
212 : {
213 : /* first half: xn[] --> cn[] */
214 783679 : temp[0] = 0;
215 783679 : move16();
216 783679 : preemph_copy_fx( xn, cn, tilt_fac, L_subfr / 2, temp );
217 783679 : syn_filt_s_lc_fx( 1, Ap, cn, temp, L_subfr / 2 ); /* Q-1 -> Q-2 */
218 783679 : Residu3_lc_fx( p_Aq, M, temp, cn, L_subfr / 2, 1 ); /* Q-2 -> Q-1 */
219 783679 : Scale_sig( cn, L_subfr / 2, 1 );
220 :
221 : /* second half: res[] --> cn[] (approximated and faster) */
222 783679 : Copy( &res[i_subfr + ( L_subfr / 2 )], cn + ( L_subfr / 2 ), L_subfr / 2 );
223 : }
224 :
225 : /*---------------------------------------------------------------*
226 : * Compute impulse response, h1[], of weighted synthesis filter *
227 : *---------------------------------------------------------------*/
228 :
229 783679 : scale = norm_s( Ap[0] );
230 783679 : scaleq = norm_s( p_Aq[0] );
231 783679 : d = sub( scaleq, scale );
232 783679 : IF( d >= 0 )
233 : {
234 783679 : Copy( p_Aq, Aqs, M + 1 ); /* Q12 */
235 783679 : s = add( scaleq, 1 );
236 783679 : s2 = shr( 16384, d );
237 : }
238 : ELSE
239 : {
240 0 : Copy_Scale_sig( p_Aq, Aqs, M + 1, d ); /* Q12 */
241 0 : s = add( scale, 1 );
242 0 : s2 = 16384;
243 0 : move16();
244 : }
245 :
246 783679 : set32_fx( h1_32, 0, L_subfr );
247 13322543 : FOR( i = 0; i < M; i++ )
248 : {
249 12538864 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
250 106580344 : FOR( j = 1; j <= i; j++ )
251 : {
252 94041480 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
253 : }
254 12538864 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
255 12538864 : move32();
256 : }
257 :
258 783679 : Ltmp64 = W_mult_16_16( Ap[i], s2 ); /* Q27 */
259 13322543 : FOR( j = 1; j <= M; j++ )
260 : {
261 12538864 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
262 : }
263 783679 : h1_32[M] = W_extract_l( Ltmp64 ); /* Q27 */
264 783679 : move32();
265 :
266 39907984 : FOR( i = M + 1; i < L_subfr; i++ )
267 : {
268 39124305 : Ltmp64 = W_msu_16_16( 0, Aqs[1], extract_h( L_shl_sat( h1_32[i - 1], s ) ) ); /* Q27 */
269 625988880 : FOR( j = 2; j <= M; j++ )
270 : {
271 586864575 : Ltmp64 = W_msu_16_16( Ltmp64, Aqs[j], extract_h( L_shl_sat( h1_32[i - j], s ) ) ); /* Q27 */
272 : }
273 39124305 : h1_32[i] = W_extract_l( Ltmp64 ); /* Q27 */
274 39124305 : move32();
275 : }
276 :
277 783679 : sf = sub( L_norm_arr( h1_32, L_subfr ), 1 );
278 783679 : Copy_Scale_sig32_16( h1_32, h1, L_subfr, sf ); // Q11 + sf
279 :
280 783679 : tmp = 0;
281 783679 : move16();
282 783679 : Deemph2( h1, tilt_fac, L_subfr, &tmp ); // Q11 + sf - 1
283 :
284 783679 : return;
285 : }
|