FreeCalypso > hg > gsm-codec-lib
comparison libtwamr/c4_17pf.c @ 322:fc82b113977f
libtwamr: integrate c4_17pf.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 18 Apr 2024 19:41:41 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
321:5fc9a2d12048 | 322:fc82b113977f |
---|---|
1 /* | |
2 ******************************************************************************** | |
3 * | |
4 * GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 | |
5 * R99 Version 3.3.0 | |
6 * REL-4 Version 4.1.0 | |
7 * | |
8 ******************************************************************************** | |
9 * | |
10 * File : c4_17pf.c | |
11 * Purpose : Searches a 17 bit algebraic codebook containing 4 pulses | |
12 * in a frame of 40 samples. | |
13 * | |
14 ******************************************************************************** | |
15 */ | |
16 | |
17 /* | |
18 ******************************************************************************** | |
19 * MODULE INCLUDE FILE AND VERSION ID | |
20 ******************************************************************************** | |
21 */ | |
22 #include "namespace.h" | |
23 #include "c4_17pf.h" | |
24 | |
25 /* | |
26 ******************************************************************************** | |
27 * INCLUDE FILES | |
28 ******************************************************************************** | |
29 */ | |
30 #include "typedef.h" | |
31 #include "basic_op.h" | |
32 #include "no_count.h" | |
33 #include "inv_sqrt.h" | |
34 #include "cnst.h" | |
35 #include "cor_h.h" | |
36 #include "set_sign.h" | |
37 #include "graytab.h" | |
38 | |
39 /* | |
40 ******************************************************************************** | |
41 * LOCAL VARIABLES AND TABLES | |
42 ******************************************************************************** | |
43 */ | |
44 #define NB_PULSE 4 | |
45 | |
46 /* | |
47 ******************************************************************************** | |
48 * DECLARATION OF PROTOTYPES | |
49 ******************************************************************************** | |
50 */ | |
51 static void search_4i40( | |
52 Word16 dn[], /* i : correlation between target and h[] */ | |
53 Word16 dn2[], /* i : maximum of corr. in each track. */ | |
54 Word16 rr[][L_CODE],/* i : matrix of autocorrelation */ | |
55 Word16 codvec[] /* o : algebraic codebook vector */ | |
56 ); | |
57 | |
58 static Word16 build_code( | |
59 Word16 codvec[], /* i : algebraic codebook vector */ | |
60 Word16 dn_sign[], /* i : sign of dn[] */ | |
61 Word16 cod[], /* o : algebraic (fixed) codebook excitation */ | |
62 Word16 h[], /* i : impulse response of weighted synthesis filter */ | |
63 Word16 y[], /* o : filtered fixed codebook excitation */ | |
64 Word16 sign[] /* o : index of 4 pulses (position+sign+ampl)*4 */ | |
65 ); | |
66 | |
67 | |
68 /* | |
69 ******************************************************************************** | |
70 * PUBLIC PROGRAM CODE | |
71 ******************************************************************************** | |
72 */ | |
73 /************************************************************************* | |
74 * | |
75 * FUNCTION: code_4i40_17bits() | |
76 * | |
77 * PURPOSE: Searches a 17 bit algebraic codebook containing 4 pulses | |
78 * in a frame of 40 samples. | |
79 * | |
80 * DESCRIPTION: | |
81 * The code length is 40, containing 4 nonzero pulses: i0...i3. | |
82 * All pulses can have two possible amplitudes: +1 or -1. | |
83 * Pulse i0 to i2 can have 8 possible positions, pulse i3 can have | |
84 * 2x8=16 positions. | |
85 * | |
86 * i0 : 0, 5, 10, 15, 20, 25, 30, 35. | |
87 * i1 : 1, 6, 11, 16, 21, 26, 31, 36. | |
88 * i2 : 2, 7, 12, 17, 22, 27, 32, 37. | |
89 * i3 : 3, 8, 13, 18, 23, 28, 33, 38. | |
90 * 4, 9, 14, 19, 24, 29, 34, 39. | |
91 * | |
92 *************************************************************************/ | |
93 | |
94 Word16 code_4i40_17bits( | |
95 Word16 x[], /* i : target vector */ | |
96 Word16 h[], /* i : impulse response of weighted synthesis filter */ | |
97 /* h[-L_subfr..-1] must be set to zero. */ | |
98 Word16 T0, /* i : Pitch lag */ | |
99 Word16 pitch_sharp, /* i : Last quantized pitch gain */ | |
100 Word16 code[], /* o : Innovative codebook */ | |
101 Word16 y[], /* o : filtered fixed codebook excitation */ | |
102 Word16 * sign /* o : Signs of 4 pulses */ | |
103 ) | |
104 { | |
105 Word16 codvec[NB_PULSE]; | |
106 Word16 dn[L_CODE], dn2[L_CODE], dn_sign[L_CODE]; | |
107 Word16 rr[L_CODE][L_CODE]; | |
108 Word16 i, index, sharp; | |
109 | |
110 sharp = shl(pitch_sharp, 1); | |
111 test (); | |
112 if (sub(T0, L_CODE) < 0) | |
113 { | |
114 for (i = T0; i < L_CODE; i++) { | |
115 h[i] = add(h[i], mult(h[i - T0], sharp)); move16 (); | |
116 } | |
117 } | |
118 | |
119 cor_h_x(h, x, dn, 1); | |
120 set_sign(dn, dn_sign, dn2, 4); | |
121 cor_h(h, dn_sign, rr); | |
122 search_4i40(dn, dn2, rr, codvec); | |
123 move16 (); /* function result */ | |
124 index = build_code(codvec, dn_sign, code, h, y, sign); | |
125 | |
126 /*-----------------------------------------------------------------* | |
127 * Compute innovation vector gain. * | |
128 * Include fixed-gain pitch contribution into code[]. * | |
129 *-----------------------------------------------------------------*/ | |
130 | |
131 test (); | |
132 if (sub(T0, L_CODE) < 0) | |
133 { | |
134 for (i = T0; i < L_CODE; i++) { | |
135 code[i] = add(code[i], mult(code[i - T0], sharp)); move16 (); | |
136 } | |
137 } | |
138 return index; | |
139 } | |
140 | |
141 /* | |
142 ******************************************************************************** | |
143 * PRIVATE PROGRAM CODE | |
144 ******************************************************************************** | |
145 */ | |
146 | |
147 /************************************************************************* | |
148 * | |
149 * FUNCTION search_4i40() | |
150 * | |
151 * PURPOSE: Search the best codevector; determine positions of the 4 pulses | |
152 * in the 40-sample frame. | |
153 * | |
154 *************************************************************************/ | |
155 | |
156 #define _1_2 (Word16)(32768L/2) | |
157 #define _1_4 (Word16)(32768L/4) | |
158 #define _1_8 (Word16)(32768L/8) | |
159 #define _1_16 (Word16)(32768L/16) | |
160 | |
161 static void search_4i40( | |
162 Word16 dn[], /* i : correlation between target and h[] */ | |
163 Word16 dn2[], /* i : maximum of corr. in each track. */ | |
164 Word16 rr[][L_CODE], /* i : matrix of autocorrelation */ | |
165 Word16 codvec[] /* o : algebraic codebook vector */ | |
166 ) | |
167 { | |
168 Word16 i0, i1, i2, i3; | |
169 Word16 ix = 0; /* initialization only needed to keep gcc silent */ | |
170 Word16 ps = 0; /* initialization only needed to keep gcc silent */ | |
171 Word16 i, pos, track, ipos[NB_PULSE]; | |
172 Word16 psk, ps0, ps1, sq, sq1; | |
173 Word16 alpk, alp, alp_16; | |
174 Word32 s, alp0, alp1; | |
175 | |
176 /* Default value */ | |
177 psk = -1; move16 (); | |
178 alpk = 1; move16 (); | |
179 for (i = 0; i < NB_PULSE; i++) | |
180 { | |
181 codvec[i] = i; move16 (); | |
182 } | |
183 | |
184 for (track = 3; track < 5; track++) { | |
185 /* fix starting position */ | |
186 | |
187 ipos[0] = 0; move16 (); | |
188 ipos[1] = 1; move16 (); | |
189 ipos[2] = 2; move16 (); | |
190 ipos[3] = track; move16 (); | |
191 | |
192 /*------------------------------------------------------------------* | |
193 * main loop: try 4 tracks. * | |
194 *------------------------------------------------------------------*/ | |
195 | |
196 for (i = 0; i < NB_PULSE; i++) | |
197 { | |
198 /*----------------------------------------------------------------* | |
199 * i0 loop: try 4 positions (use position with max of corr.). * | |
200 *----------------------------------------------------------------*/ | |
201 | |
202 move16 (); /* account for ptr. init. (rr[io]) */ | |
203 for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) | |
204 { | |
205 test (); move16 (); | |
206 if (dn2[i0] >= 0) | |
207 { | |
208 ps0 = dn[i0]; move16 (); | |
209 alp0 = L_mult(rr[i0][i0], _1_4); | |
210 | |
211 /*----------------------------------------------------------------* | |
212 * i1 loop: 8 positions. * | |
213 *----------------------------------------------------------------*/ | |
214 | |
215 sq = -1; move16 (); | |
216 alp = 1; move16 (); | |
217 ps = 0; move16 (); | |
218 ix = ipos[1]; move16 (); | |
219 | |
220 /* initialize 4 index for next loop. */ | |
221 /*-------------------------------------------------------------------* | |
222 * These index have low complexity address computation because * | |
223 * they are, in fact, pointers with fixed increment. For example, * | |
224 * "rr[i0][i3]" is a pointer initialized to "&rr[i0][ipos[3]]" * | |
225 * and incremented by "STEP". * | |
226 *-------------------------------------------------------------------*/ | |
227 | |
228 move16 (); /* account for ptr. init. (rr[i1]) */ | |
229 move16 (); /* account for ptr. init. (dn[i1]) */ | |
230 move16 (); /* account for ptr. init. (rr[io]) */ | |
231 for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) | |
232 { | |
233 ps1 = add(ps0, dn[i1]); /* idx increment = STEP */ | |
234 | |
235 /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */ | |
236 | |
237 alp1 = L_mac(alp0, rr[i1][i1], _1_4); /* idx incr = STEP */ | |
238 alp1 = L_mac(alp1, rr[i0][i1], _1_2); /* idx incr = STEP */ | |
239 | |
240 sq1 = mult(ps1, ps1); | |
241 | |
242 alp_16 = round(alp1); | |
243 | |
244 s = L_msu(L_mult(alp, sq1), sq, alp_16); | |
245 | |
246 test (); | |
247 if (s > 0) | |
248 { | |
249 sq = sq1; move16 (); | |
250 ps = ps1; move16 (); | |
251 alp = alp_16; move16 (); | |
252 ix = i1; move16 (); | |
253 } | |
254 } | |
255 i1 = ix; move16 (); | |
256 | |
257 /*----------------------------------------------------------------* | |
258 * i2 loop: 8 positions. * | |
259 *----------------------------------------------------------------*/ | |
260 | |
261 ps0 = ps; move16 (); | |
262 alp0 = L_mult(alp, _1_4); | |
263 | |
264 sq = -1; move16 (); | |
265 alp = 1; move16 (); | |
266 ps = 0; move16 (); | |
267 ix = ipos[2]; move16 (); | |
268 | |
269 /* initialize 4 index for next loop (see i1 loop) */ | |
270 | |
271 move16 (); /* account for ptr. init. (rr[i2]) */ | |
272 move16 (); /* account for ptr. init. (rr[i1]) */ | |
273 move16 (); /* account for ptr. init. (dn[i2]) */ | |
274 move16 (); /* account for ptr. init. (rr[io]) */ | |
275 for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP) | |
276 { | |
277 ps1 = add(ps0, dn[i2]); /* index increment = STEP */ | |
278 | |
279 /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */ | |
280 | |
281 alp1 = L_mac(alp0, rr[i2][i2], _1_16); /* idx incr = STEP */ | |
282 alp1 = L_mac(alp1, rr[i1][i2], _1_8); /* idx incr = STEP */ | |
283 alp1 = L_mac(alp1, rr[i0][i2], _1_8); /* idx incr = STEP */ | |
284 | |
285 sq1 = mult(ps1, ps1); | |
286 | |
287 alp_16 = round(alp1); | |
288 | |
289 s = L_msu(L_mult(alp, sq1), sq, alp_16); | |
290 | |
291 test (); | |
292 if (s > 0) | |
293 { | |
294 sq = sq1; move16 (); | |
295 ps = ps1; move16 (); | |
296 alp = alp_16; move16 (); | |
297 ix = i2; move16 (); | |
298 } | |
299 } | |
300 i2 = ix; move16 (); | |
301 | |
302 /*----------------------------------------------------------------* | |
303 * i3 loop: 8 positions. * | |
304 *----------------------------------------------------------------*/ | |
305 | |
306 ps0 = ps; move16 (); | |
307 alp0 = L_deposit_h(alp); | |
308 | |
309 sq = -1; move16 (); | |
310 alp = 1; move16 (); | |
311 ps = 0; move16 (); | |
312 ix = ipos[3]; move16 (); | |
313 | |
314 /* initialize 5 index for next loop (see i1 loop) */ | |
315 | |
316 move16 (); /* account for ptr. init. (rr[i3]) */ | |
317 move16 (); /* account for ptr. init. (rr[i2]) */ | |
318 move16 (); /* account for ptr. init. (rr[i1]) */ | |
319 move16 (); /* account for ptr. init. (dn[i3]) */ | |
320 move16 (); /* account for ptr. init. (rr[io]) */ | |
321 for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP) | |
322 { | |
323 ps1 = add(ps0, dn[i3]); /* index increment = STEP */ | |
324 | |
325 /* alp1 = alp0 + rr[i0][i3] + rr[i1][i3] + rr[i2][i3] + 1/2*rr[i3][i3]; */ | |
326 | |
327 alp1 = L_mac(alp0, rr[i3][i3], _1_16); /* idx incr = STEP */ | |
328 alp1 = L_mac(alp1, rr[i2][i3], _1_8); /* idx incr = STEP */ | |
329 alp1 = L_mac(alp1, rr[i1][i3], _1_8); /* idx incr = STEP */ | |
330 alp1 = L_mac(alp1, rr[i0][i3], _1_8); /* idx incr = STEP */ | |
331 | |
332 sq1 = mult(ps1, ps1); | |
333 | |
334 alp_16 = round(alp1); | |
335 | |
336 s = L_msu(L_mult(alp, sq1), sq, alp_16); | |
337 | |
338 test (); | |
339 if (s > 0) | |
340 { | |
341 sq = sq1; move16 (); | |
342 ps = ps1; move16 (); | |
343 alp = alp_16; move16 (); | |
344 ix = i3; move16 (); | |
345 } | |
346 } | |
347 | |
348 | |
349 /*----------------------------------------------------------------* | |
350 * memorise codevector if this one is better than the last one. * | |
351 *----------------------------------------------------------------*/ | |
352 | |
353 s = L_msu(L_mult(alpk, sq), psk, alp); | |
354 | |
355 test (); | |
356 if (s > 0) | |
357 { | |
358 psk = sq; move16 (); | |
359 alpk = alp; move16 (); | |
360 codvec[0] = i0; move16 (); | |
361 codvec[1] = i1; move16 (); | |
362 codvec[2] = i2; move16 (); | |
363 codvec[3] = ix; move16 (); | |
364 } | |
365 } | |
366 } | |
367 | |
368 /*----------------------------------------------------------------* | |
369 * Cyclic permutation of i0,i1,i2 and i3. * | |
370 *----------------------------------------------------------------*/ | |
371 | |
372 pos = ipos[3]; move16 (); | |
373 ipos[3] = ipos[2]; move16 (); | |
374 ipos[2] = ipos[1]; move16 (); | |
375 ipos[1] = ipos[0]; move16 (); | |
376 ipos[0] = pos; move16 (); | |
377 } | |
378 } | |
379 | |
380 return; | |
381 } | |
382 | |
383 /************************************************************************* | |
384 * | |
385 * FUNCTION: build_code() | |
386 * | |
387 * PURPOSE: Builds the codeword, the filtered codeword and index of the | |
388 * codevector, based on the signs and positions of 4 pulses. | |
389 * | |
390 *************************************************************************/ | |
391 | |
392 static Word16 | |
393 build_code( | |
394 Word16 codvec[], /* i : position of pulses */ | |
395 Word16 dn_sign[], /* i : sign of pulses */ | |
396 Word16 cod[], /* o : innovative code vector */ | |
397 Word16 h[], /* i : impulse response of weighted synthesis filter */ | |
398 Word16 y[], /* o : filtered innovative code */ | |
399 Word16 sign[] /* o : index of 4 pulses (sign+position) */ | |
400 ) | |
401 { | |
402 Word16 i, j, k, track, index, _sign[NB_PULSE], indx, rsign; | |
403 Word16 *p0, *p1, *p2, *p3; | |
404 Word32 s; | |
405 | |
406 for (i = 0; i < L_CODE; i++) | |
407 { | |
408 cod[i] = 0; move16 (); | |
409 } | |
410 | |
411 indx = 0; move16 (); | |
412 rsign = 0; move16 (); | |
413 for (k = 0; k < NB_PULSE; k++) | |
414 { | |
415 i = codvec[k]; move16 (); /* read pulse position */ | |
416 j = dn_sign[i]; move16 (); /* read sign */ | |
417 | |
418 index = mult(i, 6554); /* index = pos/5 */ | |
419 /* track = pos%5 */ | |
420 track = sub(i, extract_l(L_shr(L_mult(index, 5), 1))); | |
421 | |
422 | |
423 index = gray[index]; move16 (); | |
424 | |
425 test (); | |
426 if (sub(track, 1) == 0) | |
427 index = shl(index, 3); | |
428 else if (sub(track, 2) == 0) | |
429 { | |
430 test (); | |
431 index = shl(index, 6); | |
432 } | |
433 else if (sub(track, 3) == 0) | |
434 { | |
435 test ();test (); | |
436 index = shl(index, 10); | |
437 } | |
438 else if (sub(track, 4) == 0) | |
439 { | |
440 test ();test ();test (); | |
441 track = 3; move16 (); | |
442 index = add(shl(index, 10), 512); | |
443 } | |
444 | |
445 test (); | |
446 if (j > 0) | |
447 { | |
448 cod[i] = 8191; move16 (); | |
449 _sign[k] = 32767; move16 (); | |
450 rsign = add(rsign, shl(1, track)); | |
451 } else { | |
452 cod[i] = -8192; move16 (); | |
453 _sign[k] = (Word16) - 32768L; move16 (); | |
454 } | |
455 | |
456 indx = add(indx, index); | |
457 } | |
458 *sign = rsign; move16 (); | |
459 | |
460 p0 = h - codvec[0]; move16 (); | |
461 p1 = h - codvec[1]; move16 (); | |
462 p2 = h - codvec[2]; move16 (); | |
463 p3 = h - codvec[3]; move16 (); | |
464 | |
465 for (i = 0; i < L_CODE; i++) | |
466 { | |
467 s = 0; move32 (); | |
468 s = L_mac(s, *p0++, _sign[0]); | |
469 s = L_mac(s, *p1++, _sign[1]); | |
470 s = L_mac(s, *p2++, _sign[2]); | |
471 s = L_mac(s, *p3++, _sign[3]); | |
472 y[i] = round(s); move16 (); | |
473 } | |
474 | |
475 return indx; | |
476 } |