comparison intercom/gsm/rpe.c @ 2:13be24d74cd2

import intercom-0.4.1
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 09:57:52 +0200
parents
children
comparison
equal deleted inserted replaced
1:9cadc470e3da 2:13be24d74cd2
1 /*
2 * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
3 * Universitaet Berlin. See the accompanying file "COPYRIGHT" for
4 * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
5 */
6
7 /* $Header: /home/kbs/jutta/src/gsm/gsm-1.0/src/RCS/rpe.c,v 1.2 1994/01/25 22:21:15 jutta Exp $ */
8
9 #include <stdio.h>
10 #include <assert.h>
11
12 #include "private.h"
13
14 #include "gsm.h"
15 #include "proto.h"
16
17 /* 4.2.13 .. 4.2.17 RPE ENCODING SECTION
18 */
19
20 /* 4.2.13 */
21
22 static void Weighting_filter P2((e, x), register word * e, /* signal [-5..0.39.44] IN */
23 word * x /* signal [0..39] OUT */
24 )
25 /*
26 * The coefficients of the weighting filter are stored in a table
27 * (see table 4.4). The following scaling is used:
28 *
29 * H[0..10] = integer( real_H[ 0..10] * 8192 );
30 */
31 {
32 /* word wt[ 50 ]; */
33
34 register longword L_result;
35 register int k /* , i */ ;
36
37 /* Initialization of a temporary working array wt[0...49]
38 */
39
40 /* for (k = 0; k <= 4; k++) wt[k] = 0;
41 * for (k = 5; k <= 44; k++) wt[k] = *e++;
42 * for (k = 45; k <= 49; k++) wt[k] = 0;
43 *
44 * (e[-5..-1] and e[40..44] are allocated by the caller,
45 * are initially zero and are not written anywhere.)
46 */
47 e -= 5;
48
49 /* Compute the signal x[0..39]
50 */
51 for (k = 0; k <= 39; k++) {
52
53 L_result = 8192 >> 1;
54
55 /* for (i = 0; i <= 10; i++) {
56 * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] );
57 * L_result = GSM_L_ADD( L_result, L_temp );
58 * }
59 */
60
61 #ifdef STEP
62 #undef STEP
63 #endif
64 #define STEP( i, H ) (e[ k + i ] * (longword)H)
65
66 /* Every one of these multiplications is done twice --
67 * but I don't see an elegant way to optimize this.
68 * Do you?
69 */
70
71 #ifdef STUPID_COMPILER
72 L_result += STEP(0, -134);
73 L_result += STEP(1, -374);
74 /* + STEP( 2, 0 ) */
75 L_result += STEP(3, 2054);
76 L_result += STEP(4, 5741);
77 L_result += STEP(5, 8192);
78 L_result += STEP(6, 5741);
79 L_result += STEP(7, 2054);
80 /* + STEP( 8, 0 ) */
81 L_result += STEP(9, -374);
82 L_result += STEP(10, -134);
83 #else
84 L_result += STEP(0, -134)
85 + STEP(1, -374)
86 /* + STEP( 2, 0 ) */
87 + STEP(3, 2054)
88 + STEP(4, 5741)
89 + STEP(5, 8192)
90 + STEP(6, 5741)
91 + STEP(7, 2054)
92 /* + STEP( 8, 0 ) */
93 + STEP(9, -374)
94 + STEP(10, -134);
95 #endif
96
97 /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *)
98 * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *)
99 *
100 * x[k] = SASR( L_result, 16 );
101 */
102
103 /* 2 adds vs. >>16 => 14, minus one shift to compensate for
104 * those we lost when replacing L_MULT by '*'.
105 */
106
107 L_result = SASR(L_result, 13);
108 x[k] = (L_result < MIN_WORD ? MIN_WORD
109 : (L_result > MAX_WORD ? MAX_WORD : L_result));
110 }
111 }
112
113 /* 4.2.14 */
114
115 static void RPE_grid_selection P3((x, xM, Mc_out), word * x, /* [0..39] IN */
116 word * xM, /* [0..12] OUT */
117 word * Mc_out /* OUT */
118 )
119 /*
120 * The signal x[0..39] is used to select the RPE grid which is
121 * represented by Mc.
122 */
123 {
124 /* register word temp1; */
125 register int /* m, */ i;
126 /* register ulongword utmp; */
127 register longword L_result, L_temp;
128 longword EM; /* xxx should be L_EM? */
129 word Mc;
130
131 longword L_common_0_3;
132
133 EM = 0;
134 Mc = 0;
135
136 /* for (m = 0; m <= 3; m++) {
137 * L_result = 0;
138 *
139 *
140 * for (i = 0; i <= 12; i++) {
141 *
142 * temp1 = SASR( x[m + 3*i], 2 );
143 *
144 * assert(temp1 != MIN_WORD);
145 *
146 * L_temp = GSM_L_MULT( temp1, temp1 );
147 * L_result = GSM_L_ADD( L_temp, L_result );
148 * }
149 *
150 * if (L_result > EM) {
151 * Mc = m;
152 * EM = L_result;
153 * }
154 * }
155 */
156
157 #undef STEP
158 #define STEP( m, i ) L_temp = SASR( (longword)x[m + 3 * i], 2 ); \
159 L_result += L_temp * L_temp;
160
161 /* common part of 0 and 3 */
162
163 L_result = 0;
164 STEP(0, 1);
165 STEP(0, 2);
166 STEP(0, 3);
167 STEP(0, 4);
168 STEP(0, 5);
169 STEP(0, 6);
170 STEP(0, 7);
171 STEP(0, 8);
172 STEP(0, 9);
173 STEP(0, 10);
174 STEP(0, 11);
175 STEP(0, 12);
176 L_common_0_3 = L_result;
177
178 /* i = 0 */
179
180 STEP(0, 0);
181 L_result <<= 1; /* implicit in L_MULT */
182 EM = L_result;
183
184 /* i = 1 */
185
186 L_result = 0;
187 STEP(1, 0);
188 STEP(1, 1);
189 STEP(1, 2);
190 STEP(1, 3);
191 STEP(1, 4);
192 STEP(1, 5);
193 STEP(1, 6);
194 STEP(1, 7);
195 STEP(1, 8);
196 STEP(1, 9);
197 STEP(1, 10);
198 STEP(1, 11);
199 STEP(1, 12);
200 L_result <<= 1;
201 if (L_result > EM) {
202 Mc = 1;
203 EM = L_result;
204 }
205
206 /* i = 2 */
207
208 L_result = 0;
209 STEP(2, 0);
210 STEP(2, 1);
211 STEP(2, 2);
212 STEP(2, 3);
213 STEP(2, 4);
214 STEP(2, 5);
215 STEP(2, 6);
216 STEP(2, 7);
217 STEP(2, 8);
218 STEP(2, 9);
219 STEP(2, 10);
220 STEP(2, 11);
221 STEP(2, 12);
222 L_result <<= 1;
223 if (L_result > EM) {
224 Mc = 2;
225 EM = L_result;
226 }
227
228 /* i = 3 */
229
230 L_result = L_common_0_3;
231 STEP(3, 12);
232 L_result <<= 1;
233 if (L_result > EM) {
234 Mc = 3;
235 EM = L_result;
236 }
237
238 /**/
239 /* Down-sampling by a factor 3 to get the selected xM[0..12]
240 * RPE sequence.
241 */
242 for (i = 0; i <= 12; i++)
243 xM[i] = x[Mc + 3 * i];
244 *Mc_out = Mc;
245 }
246
247 /* 4.12.15 */
248
249 static void APCM_quantization_xmaxc_to_exp_mant P3((xmaxc, exp_out, mant_out), word xmaxc, /* IN */
250 word * exp_out, /* OUT */
251 word * mant_out)
252 { /* OUT */
253 word exp, mant;
254
255 /* Compute exponent and mantissa of the decoded version of xmaxc
256 */
257
258 exp = 0;
259 if (xmaxc > 15)
260 exp = SASR(xmaxc, 3) - 1;
261 mant = xmaxc - (exp << 3);
262
263 if (mant == 0) {
264 exp = -4;
265 mant = 7;
266 } else {
267 while (mant <= 7) {
268 mant = mant << 1 | 1;
269 exp--;
270 }
271 mant -= 8;
272 }
273
274 assert(exp >= -4 && exp <= 6);
275 assert(mant >= 0 && mant <= 7);
276
277 *exp_out = exp;
278 *mant_out = mant;
279 }
280
281 static void APCM_quantization P5((xM, xMc, mant_out, exp_out, xmaxc_out), word * xM, /* [0..12] IN */
282 word * xMc, /* [0..12] OUT */
283 word * mant_out, /* OUT */
284 word * exp_out, /* OUT */
285 word * xmaxc_out /* OUT */
286 )
287 {
288 int i, itest;
289
290 /* register longword ltmp; / * for GSM_ADD */
291 word xmax, xmaxc, temp, temp1, temp2;
292 word exp, mant;
293
294
295 /* Find the maximum absolute value xmax of xM[0..12].
296 */
297
298 xmax = 0;
299 for (i = 0; i <= 12; i++) {
300 temp = xM[i];
301 temp = GSM_ABS(temp);
302 if (temp > xmax)
303 xmax = temp;
304 }
305
306 /* Qantizing and coding of xmax to get xmaxc.
307 */
308
309 exp = 0;
310 temp = SASR(xmax, 9);
311 itest = 0;
312
313 for (i = 0; i <= 5; i++) {
314
315 itest |= (temp <= 0);
316 temp = SASR(temp, 1);
317
318 assert(exp <= 5);
319 if (itest == 0)
320 exp++; /* exp = add (exp, 1) */
321 }
322
323 assert(exp <= 6 && exp >= 0);
324 temp = exp + 5;
325
326 assert(temp <= 11 && temp >= 0);
327 xmaxc = gsm_add(SASR(xmax, temp), exp << 3);
328
329 /* Quantizing and coding of the xM[0..12] RPE sequence
330 * to get the xMc[0..12]
331 */
332
333 APCM_quantization_xmaxc_to_exp_mant(xmaxc, &exp, &mant);
334
335 /* This computation uses the fact that the decoded version of xmaxc
336 * can be calculated by using the exponent and the mantissa part of
337 * xmaxc (logarithmic table).
338 * So, this method avoids any division and uses only a scaling
339 * of the RPE samples by a function of the exponent. A direct
340 * multiplication by the inverse of the mantissa (NRFAC[0..7]
341 * found in table 4.5) gives the 3 bit coded version xMc[0..12]
342 * of the RPE samples.
343 */
344
345
346 /* Direct computation of xMc[0..12] using table 4.5
347 */
348
349 assert(exp <= 4096 && exp >= -4096);
350 assert(mant >= 0 && mant <= 7);
351
352 temp1 = 6 - exp; /* normalization by the exponent */
353 temp2 = gsm_NRFAC[mant]; /* inverse mantissa */
354
355 for (i = 0; i <= 12; i++) {
356
357 assert(temp1 >= 0 && temp1 < 16);
358
359 temp = xM[i] << temp1;
360 temp = GSM_MULT(temp, temp2);
361 temp = SASR(temp, 12);
362 xMc[i] = temp + 4; /* see note below */
363 }
364
365 /* NOTE: This equation is used to make all the xMc[i] positive.
366 */
367
368 *mant_out = mant;
369 *exp_out = exp;
370 *xmaxc_out = xmaxc;
371 }
372
373 /* 4.2.16 */
374
375 static void APCM_inverse_quantization P4((xMc, mant, exp, xMp), register word * xMc, /* [0..12] IN */
376 word mant, word exp, register word * xMp)
377 { /* [0..12] OUT */
378 /*
379 * This part is for decoding the RPE sequence of coded xMc[0..12]
380 * samples to obtain the xMp[0..12] array. Table 4.6 is used to get
381 * the mantissa of xmaxc (FAC[0..7]).
382 */
383 int i;
384 word temp, temp1, temp2, temp3;
385 /* ulongword utmp; */
386 longword ltmp;
387
388 assert(mant >= 0 && mant <= 7);
389
390 temp1 = gsm_FAC[mant]; /* see 4.2-15 for mant */
391 temp2 = gsm_sub(6, exp); /* see 4.2-15 for exp */
392 temp3 = gsm_asl(1, gsm_sub(temp2, 1));
393
394 for (i = 13; i--;) {
395
396 assert(*xMc <= 7 && *xMc >= 0); /* 3 bit unsigned */
397
398 /* temp = gsm_sub( *xMc++ << 1, 7 ); */
399 temp = (*xMc++ << 1) - 7; /* restore sign */
400 assert(temp <= 7 && temp >= -7); /* 4 bit signed */
401
402 temp <<= 12; /* 16 bit signed */
403 temp = GSM_MULT_R(temp1, temp);
404 temp = GSM_ADD(temp, temp3);
405 *xMp++ = gsm_asr(temp, temp2);
406 }
407 }
408
409 /* 4.2.17 */
410
411 static void RPE_grid_positioning P3((Mc, xMp, ep), word Mc, /* grid position IN */
412 register word * xMp, /* [0..12] IN */
413 register word * ep /* [0..39] OUT */
414 )
415 /*
416 * This procedure computes the reconstructed long term residual signal
417 * ep[0..39] for the LTP analysis filter. The inputs are the Mc
418 * which is the grid position selection and the xMp[0..12] decoded
419 * RPE samples which are upsampled by a factor of 3 by inserting zero
420 * values.
421 */
422 {
423 #if defined(VMS) || defined(__TURBOC__)
424 int k;
425 #endif
426 int i = 13;
427
428 assert(0 <= Mc && Mc <= 3);
429
430 #if defined(VMS) || defined(__TURBOC__)
431 for (k = 0; k <= 39; k++)
432 ep[k] = 0;
433 for (i = 0; i <= 12; i++) {
434 ep[Mc + (3 * i)] = xMp[i];
435 }
436 #else
437 switch (Mc) {
438 case 3:
439 *ep++ = 0;
440 case 2:
441 do {
442 *ep++ = 0;
443 case 1:
444 *ep++ = 0;
445 case 0:
446 *ep++ = *xMp++;
447 } while (--i);
448 }
449 while (++Mc < 4)
450 *ep++ = 0;
451 #endif
452 }
453
454 /* 4.2.18 */
455
456 /* This procedure adds the reconstructed long term residual signal
457 * ep[0..39] to the estimated signal dpp[0..39] from the long term
458 * analysis filter to compute the reconstructed short term residual
459 * signal dp[-40..-1]; also the reconstructed short term residual
460 * array dp[-120..-41] is updated.
461 */
462
463 #if 0 /* Has been inlined in code.c */
464 void Gsm_Update_of_reconstructed_short_time_residual_signal P3((dpp, ep, dp), word * dpp, /* [0...39] IN */
465 word * ep, /* [0...39] IN */
466 word * dp)
467 { /* [-120...-1] IN/OUT */
468 int k;
469
470 for (k = 0; k <= 79; k++)
471 dp[-120 + k] = dp[-80 + k];
472
473 for (k = 0; k <= 39; k++)
474 dp[-40 + k] = gsm_add(ep[k], dpp[k]);
475 }
476 #endif /* Has been inlined in code.c */
477
478 void Gsm_RPE_Encoding P5((S, e, xmaxc, Mc, xMc), struct gsm_state *S, word * e, /* -5..-1][0..39][40..44 IN/OUT */
479 word * xmaxc, /* OUT */
480 word * Mc, /* OUT */
481 word * xMc)
482 { /* [0..12] OUT */
483 word x[40];
484 word xM[13], xMp[13];
485 word mant, exp;
486
487 Weighting_filter(e, x);
488 RPE_grid_selection(x, xM, Mc);
489
490 APCM_quantization(xM, xMc, &mant, &exp, xmaxc);
491 APCM_inverse_quantization(xMc, mant, exp, xMp);
492
493 RPE_grid_positioning(*Mc, xMp, e);
494
495 }
496
497 void Gsm_RPE_Decoding P5((S, xmaxcr, Mcr, xMcr, erp), struct gsm_state *S, word xmaxcr, word Mcr, word * xMcr, /* [0..12], 3 bits IN */
498 word * erp /* [0..39] OUT */
499 )
500 {
501 word exp, mant;
502 word xMp[13];
503
504 APCM_quantization_xmaxc_to_exp_mant(xmaxcr, &exp, &mant);
505 APCM_inverse_quantization(xMcr, mant, exp, xMp);
506 RPE_grid_positioning(Mcr, xMp, erp);
507
508 }

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.