Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 :
6 : #include <stdint.h>
7 : #include <assert.h>
8 : #include "options.h"
9 : //#include "prot_fx.h"
10 : #include "basop_util.h"
11 : #include "cnst.h"
12 : #include "prot_fx.h" /* Function prototypes */
13 : #include "prot_fx_enc.h" /* Function prototypes */
14 : #include "stat_enc.h"
15 : #include "rom_com.h"
16 : #include "rom_com_fx.h"
17 : #include "rom_enc.h"
18 :
19 :
20 : #define _1_Q9 0x200
21 :
22 :
23 : /*
24 : * E_ACELP_toeplitz_mul_fx
25 : *
26 : * Parameters:
27 : * R I: coefficients of Toeplitz matrix (Q9)
28 : * c I: input vector Q_xn
29 : * d O: output vector, exponent = j
30 : *
31 : * Function:
32 : * Multiplication of Toeplitz matrix with vector c, such that
33 : * d = toeplitz(R)*c
34 : * Vector length is L_SUBFR
35 : */
36 407727 : Word16 E_ACELP_toeplitz_mul_fx(
37 : const Word16 R[], /* Q9 */
38 : const Word16 c[], /* Qx */
39 : Word16 d[], /* exp(j) */
40 : const Word16 L_subfr, /* Q0 */
41 : const Word16 highrate /* Q0 */
42 : )
43 : {
44 : static const Word16 step = 4;
45 : Word16 k, j, i;
46 : Word32 s;
47 : Word32 y32[L_SUBFR16k], L_maxloc, L_tot;
48 :
49 :
50 407727 : assert( L_subfr <= L_SUBFR16k );
51 :
52 :
53 : /* first keep the result on 32 bits and find absolute maximum */
54 407727 : L_tot = L_deposit_l( 1 );
55 :
56 2038635 : FOR( k = 0; k < step; k++ )
57 : {
58 1630908 : L_maxloc = L_deposit_l( 0 );
59 27725436 : FOR( i = k; i < L_subfr; i += step )
60 : {
61 26094528 : s = L_mult( R[i], c[0] ); /* Q10 + Qx */
62 822385359 : FOR( j = 1; j < i; j++ )
63 : {
64 796290831 : s = L_mac( s, R[i - j], c[j] ); /* Q10 + Qx */
65 : }
66 873758961 : FOR( ; j < L_subfr; j++ )
67 : {
68 847664433 : s = L_mac( s, R[j - i], c[j] ); /* Q10 + Qx */
69 : }
70 :
71 26094528 : y32[i] = s;
72 26094528 : move32();
73 26094528 : s = L_abs( s );
74 26094528 : L_maxloc = L_max( s, L_maxloc ); /* Q10 + Qx */
75 : }
76 : /* tot += 3*max / 8 */
77 1630908 : L_maxloc = L_shr( L_maxloc, 2 );
78 : /* Do not warn saturation of L_tot, since its for headroom estimation. */
79 : BASOP_SATURATE_WARNING_OFF_EVS
80 1630908 : L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/4 */
81 1630908 : L_maxloc = L_shr( L_maxloc, 1 );
82 1630908 : L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
83 1630908 : if ( highrate )
84 : {
85 1618668 : L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/8 */
86 : }
87 1630908 : L_maxloc = L_shr( L_maxloc, 1 );
88 1630908 : if ( highrate )
89 : {
90 1618668 : L_tot = L_add_sat( L_tot, L_maxloc ); /* +max/16 */
91 : }
92 : BASOP_SATURATE_WARNING_ON_EVS
93 : }
94 :
95 : /* Find the number of right shifts to do on y32[] so that */
96 : /* 6.0 x sumation of max of dn[] in each track not saturate. */
97 : /* high-rate: 9.0 x sumation of max of dn[] in each track */
98 :
99 : /* Limit exponent to avoid overflows elsewhere. */
100 407727 : j = s_min( sub( norm_l( L_tot ), 4 + 16 ), 15 - 16 ); /* 4 -> 16 x tot */
101 :
102 407727 : Copy_Scale_sig_32_16( y32, d, L_subfr, j ); /* exp(j) */
103 :
104 407727 : return j;
105 : }
106 :
107 64061 : void E_ACELP_weighted_code(
108 : const Word16 code[], /* i: code Q9*/
109 : const Word16 H[], /* i: impulse response Q*/
110 : Word16 Q, /* i: Q format of H */
111 : Word16 y[] /* o: weighted code Q9*/
112 : )
113 : {
114 : Word16 i, j, k, one, n, nz[L_SUBFR];
115 : Word32 L_tmp;
116 :
117 : /* Collect nonzeros */
118 64061 : n = 0;
119 64061 : move16();
120 4163965 : FOR( i = 0; i < L_SUBFR; ++i )
121 : {
122 4099904 : if ( code[i] != 0 )
123 : {
124 527080 : nz[n++] = i;
125 527080 : move16();
126 : }
127 : }
128 64061 : assert( n > 0 );
129 :
130 64061 : one = shl( 1, Q );
131 64061 : Q = sub( 15, Q );
132 :
133 : /* Generate weighted code */
134 64061 : j = nz[0];
135 64061 : move16();
136 64061 : set16_fx( y, 0, j );
137 3764663 : FOR( k = 0; k < L_SUBFR - j; k++ )
138 : {
139 3700602 : L_tmp = L_mult( code[j], H[k] ); /* Q10 + Q */
140 3700602 : y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9 */
141 : }
142 :
143 527080 : FOR( i = 1; i < n; ++i )
144 : {
145 463019 : j = nz[i];
146 463019 : move16();
147 13330594 : FOR( k = 0; k < L_SUBFR - j; k++ )
148 : {
149 12867575 : L_tmp = L_mult( y[j + k], one );
150 12867575 : L_tmp = L_mac( L_tmp, code[j], H[k] ); /* Q10 + Q */
151 12867575 : y[j + k] = extract_h( L_shl( L_tmp, Q ) ); /* Q9*/
152 : }
153 : }
154 64061 : }
155 :
156 407727 : void E_ACELP_conv(
157 : const Word16 xn2[], /* i Qx*/
158 : const Word16 h2[], /* i Q12*/
159 : Word16 cn2[] /* o Q0*/
160 : )
161 : {
162 : Word16 i, k;
163 : Word32 L_tmp;
164 : #ifndef ISSUE_1867_replace_overflow_libenc
165 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
166 : Flag Overflow = 0;
167 : #endif
168 : #endif
169 26502255 : FOR( k = 0; k < L_SUBFR; k++ )
170 : {
171 : /*cn2[k] = xn2[k]; */
172 : Word64 L_tmp_64;
173 26094528 : L_tmp_64 = W_deposit32_l( L_mult( xn2[k], 0x800 ) ); /* 4Q11 */
174 848072160 : FOR( i = 0; i < k; i++ )
175 : {
176 : /*cn2[k]-=cn2[i]*h2[k-i];*/
177 821977632 : L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*h2 4Q11*/
178 : }
179 26094528 : L_tmp = W_sat_l( L_tmp_64 ); /* 4Q11 */
180 : #ifdef ISSUE_1867_replace_overflow_libenc
181 26094528 : cn2[k] = round_fx_sat( L_shl_sat( L_tmp, 5 ) ); /* Q0 */
182 : #else
183 : cn2[k] = round_fx_o( L_shl_o( L_tmp, 5, &Overflow ), &Overflow ); /* Q0 */
184 : #endif
185 : }
186 407727 : }
187 :
188 0 : void E_ACELP_conv_ivas_fx(
189 : const Word16 xn2[], /* i Qnew - 1*/
190 : const Word16 h2[], /* i Q12*/
191 : Word16 cn2[] /* o Qnew*/
192 : )
193 : {
194 : Word16 i, k;
195 : Word32 L_tmp;
196 : #ifndef ISSUE_1867_replace_overflow_libenc
197 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
198 : Flag Overflow = 0;
199 : #endif
200 : #endif
201 0 : FOR( k = 0; k < L_SUBFR; k++ )
202 : {
203 : /*cn2[k] = xn2[k]; */
204 : Word64 L_tmp_64;
205 0 : L_tmp_64 = W_deposit32_l( L_mult0( xn2[k], 0x800 ) ); /* Qnew -1 + 12 */
206 0 : FOR( i = 0; i < k; i++ )
207 : {
208 : /*cn2[k]-=cn2[i]*h2[k-i];*/
209 0 : L_tmp_64 = W_msu0_16_16( L_tmp_64, cn2[i], h2[k - i] ); /*Qnew + 11*/
210 : }
211 0 : L_tmp = W_sat_l( L_tmp_64 ); /* Qnew + 11 */
212 : #ifdef ISSUE_1867_replace_overflow_libenc
213 0 : cn2[k] = round_fx_sat( L_shl_sat( L_tmp, 5 ) ); /* Qnew*/
214 : #else
215 : cn2[k] = round_fx_o( L_shl_o( L_tmp, 5, &Overflow ), &Overflow ); /* Qnew*/
216 : #endif
217 0 : move16();
218 : }
219 0 : }
220 190661 : void E_ACELP_build_code(
221 : Word16 nb_pulse, /* i Q0*/
222 : const Word16 codvec[], /* i Q0*/
223 : const Word16 sign[], /* i Q0*/
224 : Word16 code[], /* o Q9*/
225 : Word16 ind[] /* o Q0*/
226 : )
227 : {
228 : Word16 i, k, val, index, track, tmp, vec[4];
229 :
230 190661 : set16_fx( code, 0, L_SUBFR );
231 190661 : set16_fx( ind, -1, NPMAXPT * 4 );
232 :
233 : /* use vec to store point counter */
234 190661 : vec[0] = NPMAXPT * 0 - 1;
235 190661 : move16();
236 190661 : vec[1] = NPMAXPT * 1 - 1;
237 190661 : move16();
238 190661 : vec[2] = NPMAXPT * 2 - 1;
239 190661 : move16();
240 190661 : vec[3] = NPMAXPT * 3 - 1;
241 190661 : move16();
242 :
243 1265245 : FOR( k = 0; k < nb_pulse; ++k )
244 : {
245 1074584 : i = codvec[k]; /* read pulse position Q0*/
246 1074584 : move16();
247 1074584 : val = sign[i]; /* read sign Q0*/
248 1074584 : move16();
249 :
250 1074584 : index = shr( i, 2 ); /* pos of pulse (0..15) */
251 1074584 : track = s_and( i, 4 - 1 ); /* i % 4; */
252 :
253 1074584 : tmp = add( code[i], _1_Q9 ); /* Q9 */
254 1074584 : if ( val <= 0 )
255 : {
256 542646 : tmp = sub( code[i], _1_Q9 ); /* Q9 */
257 : }
258 1074584 : code[i] = tmp; /* Q9 */
259 1074584 : move16();
260 :
261 1074584 : if ( val <= 0 )
262 : {
263 542646 : index = add( index, 16 ); /* Q0 */
264 : }
265 :
266 : /* Calculate Current Store Index (we started at -1) so we increment first */
267 1074584 : i = add( vec[track], 1 ); /* Q0 */
268 : /* Save Next Store Index */
269 1074584 : vec[track] = i; /* Q0 */
270 1074584 : move16();
271 :
272 1074584 : ind[i] = index; /* Q0 */
273 1074584 : move16();
274 : }
275 190661 : }
276 :
277 2173053 : void E_ACELP_setup_pulse_search_pos(
278 : const PulseConfig *config, /* i: pulse configuration */
279 : Word16 k, /* i: interation number Q0*/
280 : UWord8 ipos[] /* o: pulse search positions Q0*/
281 : )
282 : {
283 : Word16 restpulses, iPulse;
284 :
285 : /* copy search order from hash-table */
286 2173053 : assert( config->nb_pulse + ( k * 4 ) <= 40 );
287 :
288 2173053 : copyWord8( (const Word8 *) E_ROM_tipos + ( k * 4 ), (Word8 *) ipos, config->nb_pulse );
289 :
290 : /* if all tracks do not have equal number of pulses */
291 2173053 : restpulses = s_and( config->nb_pulse, 3 );
292 :
293 2173053 : IF( restpulses )
294 : {
295 1594465 : SWITCH( config->codetrackpos )
296 : {
297 897943 : case TRACKPOS_FIXED_FIRST: /* fixed track positions, starting from left */
298 : /* add tracks from left */
299 2712964 : FOR( iPulse = 0; iPulse < restpulses; iPulse++ )
300 : {
301 1815021 : ipos[config->nb_pulse - restpulses + iPulse] = (UWord8) iPulse; /* Q0 */
302 1815021 : move16();
303 : }
304 : /* Put the same track on the next position, because the 1-pulse search
305 : * will access it to determine if this could be in any track. */
306 897943 : ipos[config->nb_pulse] = ipos[config->nb_pulse - 1]; /* Q0 */
307 897943 : move16();
308 897943 : BREAK;
309 0 : case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */
310 : /* odd tracks, switch order for every iteration */
311 0 : ipos[config->nb_pulse - restpulses] = (UWord8) s_and( lshl( k, 1 ), 2 ); /* Q0 */
312 0 : move16(); /* 0 for even k, 2 for odd */
313 0 : ipos[config->nb_pulse - restpulses + 1] = (UWord8) s_xor( ipos[config->nb_pulse - restpulses], 2 ); /* Q0 */
314 0 : move16(); /* 2 for even k, 0 for odd */
315 0 : BREAK;
316 293930 : case TRACKPOS_FIXED_TWO: /* two tracks instead of four */
317 : /* Put the next track on the next position, because the 1-pulse search
318 : * will access it to determine if this could be in any track. */
319 293930 : ipos[config->nb_pulse] = (UWord8) s_and( add( ipos[config->nb_pulse - 1], 1 ), 3 ); /* Q0 */
320 293930 : move16();
321 293930 : BREAK;
322 402592 : default: /* one or three free track positions */
323 : /* copy an extra position from table - 1pulse search will access this */
324 402592 : ipos[config->nb_pulse] = E_ROM_tipos[add( shl( k, 2 ), config->nb_pulse )]; /* Q0 */
325 402592 : move16();
326 402592 : BREAK;
327 : }
328 578588 : }
329 2173053 : }
|