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