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