Mercurial > hg > audiostuff
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 } |
