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 }