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