Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/gsm0610_rpe.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Fri, 25 Jun 2010 15:50:58 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
|---|---|
| 1 /* | |
| 2 * SpanDSP - a series of DSP components for telephony | |
| 3 * | |
| 4 * gsm0610_rpe.c - GSM 06.10 full rate speech codec. | |
| 5 * | |
| 6 * Written by Steve Underwood <steveu@coppice.org> | |
| 7 * | |
| 8 * Copyright (C) 2006 Steve Underwood | |
| 9 * | |
| 10 * All rights reserved. | |
| 11 * | |
| 12 * This program is free software; you can redistribute it and/or modify | |
| 13 * it under the terms of the GNU Lesser General Public License version 2.1, | |
| 14 * as published by the Free Software Foundation. | |
| 15 * | |
| 16 * This program is distributed in the hope that it will be useful, | |
| 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 * GNU Lesser General Public License for more details. | |
| 20 * | |
| 21 * You should have received a copy of the GNU Lesser General Public | |
| 22 * License along with this program; if not, write to the Free Software | |
| 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 24 * | |
| 25 * This code is based on the widely used GSM 06.10 code available from | |
| 26 * http://kbs.cs.tu-berlin.de/~jutta/toast.html | |
| 27 * | |
| 28 * $Id: gsm0610_rpe.c,v 1.25.4.2 2009/12/28 11:54:58 steveu Exp $ | |
| 29 */ | |
| 30 | |
| 31 /*! \file */ | |
| 32 | |
| 33 #if defined(HAVE_CONFIG_H) | |
| 34 #include "config.h" | |
| 35 #endif | |
| 36 | |
| 37 #include <assert.h> | |
| 38 #include <inttypes.h> | |
| 39 #if defined(HAVE_TGMATH_H) | |
| 40 #include <tgmath.h> | |
| 41 #endif | |
| 42 #if defined(HAVE_MATH_H) | |
| 43 #include <math.h> | |
| 44 #endif | |
| 45 #include "floating_fudge.h" | |
| 46 #include <stdlib.h> | |
| 47 | |
| 48 #include "mmx_sse_decs.h" | |
| 49 | |
| 50 #include "spandsp/telephony.h" | |
| 51 #include "spandsp/fast_convert.h" | |
| 52 #include "spandsp/bitstream.h" | |
| 53 #include "spandsp/saturated.h" | |
| 54 #include "spandsp/gsm0610.h" | |
| 55 | |
| 56 #include "gsm0610_local.h" | |
| 57 | |
| 58 /* 4.2.13 .. 4.2.17 RPE ENCODING SECTION */ | |
| 59 | |
| 60 /* 4.2.13 */ | |
| 61 static void weighting_filter(int16_t x[40], | |
| 62 const int16_t *e) // signal [-5..0.39.44] IN) | |
| 63 { | |
| 64 #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__x86_64__) | |
| 65 /* Table 4.4 Coefficients of the weighting filter */ | |
| 66 /* This must be padded to a multiple of 4 for MMX to work */ | |
| 67 static const union | |
| 68 { | |
| 69 int16_t gsm_H[12]; | |
| 70 __m64 x[3]; | |
| 71 } gsm_H = | |
| 72 { | |
| 73 { | |
| 74 -134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134, 0 | |
| 75 } | |
| 76 | |
| 77 }; | |
| 78 | |
| 79 __asm__ __volatile__( | |
| 80 " emms;\n" | |
| 81 " addq $-10,%%rcx;\n" | |
| 82 " leaq %[gsm_H],%%rax;\n" | |
| 83 " movq (%%rax),%%mm1;\n" | |
| 84 " movq 8(%%rax),%%mm2;\n" | |
| 85 " movq 16(%%rax),%%mm3;\n" | |
| 86 " movq $0x1000,%%rax;\n" | |
| 87 " movq %%rax,%%mm5;\n" /* For rounding */ | |
| 88 " xorq %%rsi,%%rsi;\n" | |
| 89 " .p2align 2;\n" | |
| 90 "1:\n" | |
| 91 " movq (%%rcx,%%rsi,2),%%mm0;\n" | |
| 92 " pmaddwd %%mm1,%%mm0;\n" | |
| 93 | |
| 94 " movq 8(%%rcx,%%rsi,2),%%mm4;\n" | |
| 95 " pmaddwd %%mm2,%%mm4;\n" | |
| 96 " paddd %%mm4,%%mm0;\n" | |
| 97 | |
| 98 " movq 16(%%rcx,%%rsi,2),%%mm4;\n" | |
| 99 " pmaddwd %%mm3,%%mm4;\n" | |
| 100 " paddd %%mm4,%%mm0;\n" | |
| 101 | |
| 102 " movq %%mm0,%%mm4;\n" | |
| 103 " punpckhdq %%mm0,%%mm4;\n" /* mm4 has high int32 of mm0 dup'd */ | |
| 104 " paddd %%mm4,%%mm0;\n" | |
| 105 | |
| 106 " paddd %%mm5,%%mm0;\n" /* Add for roundoff */ | |
| 107 " psrad $13,%%mm0;\n" | |
| 108 " packssdw %%mm0,%%mm0;\n" | |
| 109 " movd %%mm0,%%eax;\n" /* eax has result */ | |
| 110 " movw %%ax,(%%rdi,%%rsi,2);\n" | |
| 111 " incq %%rsi;\n" | |
| 112 " cmpq $39,%%rsi;\n" | |
| 113 " jle 1b;\n" | |
| 114 " emms;\n" | |
| 115 : | |
| 116 : "c" (e), "D" (x), [gsm_H] "X" (gsm_H) | |
| 117 : "rax", "rdx", "rsi", "memory" | |
| 118 ); | |
| 119 #elif defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__i386__) | |
| 120 /* Table 4.4 Coefficients of the weighting filter */ | |
| 121 /* This must be padded to a multiple of 4 for MMX to work */ | |
| 122 static const union | |
| 123 { | |
| 124 int16_t gsm_H[12]; | |
| 125 __m64 x[3]; | |
| 126 } gsm_H = | |
| 127 { | |
| 128 { | |
| 129 -134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134, 0 | |
| 130 } | |
| 131 | |
| 132 }; | |
| 133 | |
| 134 __asm__ __volatile__( | |
| 135 " emms;\n" | |
| 136 " addl $-10,%%ecx;\n" | |
| 137 " leal %[gsm_H],%%eax;\n" | |
| 138 " movq (%%eax),%%mm1;\n" | |
| 139 " movq 8(%%eax),%%mm2;\n" | |
| 140 " movq 16(%%eax),%%mm3;\n" | |
| 141 " movl $0x1000,%%eax;\n" | |
| 142 " movd %%eax,%%mm5;\n" /* For rounding */ | |
| 143 " xorl %%esi,%%esi;\n" | |
| 144 " .p2align 2;\n" | |
| 145 "1:\n" | |
| 146 " movq (%%ecx,%%esi,2),%%mm0;\n" | |
| 147 " pmaddwd %%mm1,%%mm0;\n" | |
| 148 | |
| 149 " movq 8(%%ecx,%%esi,2),%%mm4;\n" | |
| 150 " pmaddwd %%mm2,%%mm4;\n" | |
| 151 " paddd %%mm4,%%mm0;\n" | |
| 152 | |
| 153 " movq 16(%%ecx,%%esi,2),%%mm4;\n" | |
| 154 " pmaddwd %%mm3,%%mm4;\n" | |
| 155 " paddd %%mm4,%%mm0;\n" | |
| 156 | |
| 157 " movq %%mm0,%%mm4;\n" | |
| 158 " punpckhdq %%mm0,%%mm4;\n" /* mm4 has high int32 of mm0 dup'd */ | |
| 159 " paddd %%mm4,%%mm0;\n" | |
| 160 | |
| 161 " paddd %%mm5,%%mm0;\n" /* Add for roundoff */ | |
| 162 " psrad $13,%%mm0;\n" | |
| 163 " packssdw %%mm0,%%mm0;\n" | |
| 164 " movd %%mm0,%%eax;\n" /* eax has result */ | |
| 165 " movw %%ax,(%%edi,%%esi,2);\n" | |
| 166 " incl %%esi;\n" | |
| 167 " cmpl $39,%%esi;\n" | |
| 168 " jle 1b;\n" | |
| 169 " emms;\n" | |
| 170 : | |
| 171 : "c" (e), "D" (x), [gsm_H] "X" (gsm_H) | |
| 172 : "eax", "edx", "esi", "memory" | |
| 173 ); | |
| 174 #else | |
| 175 int32_t L_result; | |
| 176 int k; | |
| 177 | |
| 178 /* The coefficients of the weighting filter are stored in a table | |
| 179 (see table 4.4). The following scaling is used: | |
| 180 | |
| 181 H[0..10] = integer(real_H[0..10] * 8192); | |
| 182 */ | |
| 183 /* Initialization of a temporary working array wt[0...49] */ | |
| 184 | |
| 185 /* for (k = 0; k <= 4; k++) wt[k] = 0; | |
| 186 * for (k = 5; k <= 44; k++) wt[k] = *e++; | |
| 187 * for (k = 45; k <= 49; k++) wt[k] = 0; | |
| 188 * | |
| 189 * (e[-5..-1] and e[40..44] are allocated by the caller, | |
| 190 * are initially zero and are not written anywhere.) | |
| 191 */ | |
| 192 e -= 5; | |
| 193 | |
| 194 /* Compute the signal x[0..39] */ | |
| 195 for (k = 0; k < 40; k++) | |
| 196 { | |
| 197 L_result = 8192 >> 1; | |
| 198 | |
| 199 /* for (i = 0; i <= 10; i++) | |
| 200 * { | |
| 201 * L_temp = saturated_mul_16_32(wt[k + i], gsm_H[i]); | |
| 202 * L_result = saturated_add32(L_result, L_temp); | |
| 203 * } | |
| 204 */ | |
| 205 | |
| 206 #undef STEP | |
| 207 #define STEP(i,H) (e[k + i] * (int32_t) H) | |
| 208 | |
| 209 /* Every one of these multiplications is done twice, | |
| 210 but I don't see an elegant way to optimize this. | |
| 211 Do you? | |
| 212 */ | |
| 213 L_result += STEP( 0, -134); | |
| 214 L_result += STEP( 1, -374); | |
| 215 /* += STEP( 2, 0 ); */ | |
| 216 L_result += STEP( 3, 2054); | |
| 217 L_result += STEP( 4, 5741); | |
| 218 L_result += STEP( 5, 8192); | |
| 219 L_result += STEP( 6, 5741); | |
| 220 L_result += STEP( 7, 2054); | |
| 221 /* += STEP( 8, 0 ); */ | |
| 222 L_result += STEP( 9, -374); | |
| 223 L_result += STEP(10, -134); | |
| 224 | |
| 225 /* 2 adds vs. >> 16 => 14, minus one shift to compensate for | |
| 226 those we lost when replacing L_MULT by '*'. */ | |
| 227 L_result >>= 13; | |
| 228 x[k] = saturate(L_result); | |
| 229 } | |
| 230 /*endfor*/ | |
| 231 #endif | |
| 232 } | |
| 233 /*- End of function --------------------------------------------------------*/ | |
| 234 | |
| 235 /* 4.2.14 */ | |
| 236 static void rpe_grid_selection(int16_t x[40], int16_t xM[13], int16_t *Mc_out) | |
| 237 { | |
| 238 int i; | |
| 239 int32_t L_result; | |
| 240 int32_t L_temp; | |
| 241 int32_t EM; /* xxx should be L_EM? */ | |
| 242 int16_t Mc; | |
| 243 int32_t L_common_0_3; | |
| 244 | |
| 245 /* The signal x[0..39] is used to select the RPE grid which is | |
| 246 represented by Mc. */ | |
| 247 | |
| 248 EM = 0; | |
| 249 Mc = 0; | |
| 250 | |
| 251 #undef STEP | |
| 252 #define STEP(m,i) \ | |
| 253 L_temp = x[m + 3*i] >> 2; \ | |
| 254 L_result += L_temp*L_temp; | |
| 255 | |
| 256 /* Common part of 0 and 3 */ | |
| 257 L_result = 0; | |
| 258 STEP(0, 1); | |
| 259 STEP(0, 2); | |
| 260 STEP(0, 3); | |
| 261 STEP(0, 4); | |
| 262 STEP(0, 5); | |
| 263 STEP(0, 6); | |
| 264 STEP(0, 7); | |
| 265 STEP(0, 8); | |
| 266 STEP(0, 9); | |
| 267 STEP(0, 10); | |
| 268 STEP(0, 11); | |
| 269 STEP(0, 12); | |
| 270 L_common_0_3 = L_result; | |
| 271 | |
| 272 /* i = 0 */ | |
| 273 | |
| 274 STEP(0, 0); | |
| 275 L_result <<= 1; /* implicit in L_MULT */ | |
| 276 EM = L_result; | |
| 277 | |
| 278 /* i = 1 */ | |
| 279 | |
| 280 L_result = 0; | |
| 281 STEP(1, 0); | |
| 282 STEP(1, 1); | |
| 283 STEP(1, 2); | |
| 284 STEP(1, 3); | |
| 285 STEP(1, 4); | |
| 286 STEP(1, 5); | |
| 287 STEP(1, 6); | |
| 288 STEP(1, 7); | |
| 289 STEP(1, 8); | |
| 290 STEP(1, 9); | |
| 291 STEP(1, 10); | |
| 292 STEP(1, 11); | |
| 293 STEP(1, 12); | |
| 294 L_result <<= 1; | |
| 295 if (L_result > EM) | |
| 296 { | |
| 297 Mc = 1; | |
| 298 EM = L_result; | |
| 299 } | |
| 300 /*endif*/ | |
| 301 | |
| 302 /* i = 2 */ | |
| 303 | |
| 304 L_result = 0; | |
| 305 STEP(2, 0); | |
| 306 STEP(2, 1); | |
| 307 STEP(2, 2); | |
| 308 STEP(2, 3); | |
| 309 STEP(2, 4); | |
| 310 STEP(2, 5); | |
| 311 STEP(2, 6); | |
| 312 STEP(2, 7); | |
| 313 STEP(2, 8); | |
| 314 STEP(2, 9); | |
| 315 STEP(2, 10); | |
| 316 STEP(2, 11); | |
| 317 STEP(2, 12); | |
| 318 L_result <<= 1; | |
| 319 if (L_result > EM) | |
| 320 { | |
| 321 Mc = 2; | |
| 322 EM = L_result; | |
| 323 } | |
| 324 /*endif*/ | |
| 325 | |
| 326 /* i = 3 */ | |
| 327 | |
| 328 L_result = L_common_0_3; | |
| 329 STEP(3, 12); | |
| 330 L_result <<= 1; | |
| 331 if (L_result > EM) | |
| 332 { | |
| 333 Mc = 3; | |
| 334 EM = L_result; | |
| 335 } | |
| 336 /*endif*/ | |
| 337 | |
| 338 /* Down-sampling by a factor 3 to get the selected xM[0..12] | |
| 339 RPE sequence. */ | |
| 340 for (i = 0; i < 13; i++) | |
| 341 xM[i] = x[Mc + 3*i]; | |
| 342 /*endfor*/ | |
| 343 *Mc_out = Mc; | |
| 344 } | |
| 345 /*- End of function --------------------------------------------------------*/ | |
| 346 | |
| 347 /* 4.12.15 */ | |
| 348 static void apcm_quantization_xmaxc_to_exp_mant(int16_t xmaxc, | |
| 349 int16_t *exp_out, | |
| 350 int16_t *mant_out) | |
| 351 { | |
| 352 int16_t exp; | |
| 353 int16_t mant; | |
| 354 | |
| 355 /* Compute exponent and mantissa of the decoded version of xmaxc */ | |
| 356 exp = 0; | |
| 357 if (xmaxc > 15) | |
| 358 exp = (int16_t) ((xmaxc >> 3) - 1); | |
| 359 /*endif*/ | |
| 360 mant = xmaxc - (exp << 3); | |
| 361 | |
| 362 if (mant == 0) | |
| 363 { | |
| 364 exp = -4; | |
| 365 mant = 7; | |
| 366 } | |
| 367 else | |
| 368 { | |
| 369 while (mant <= 7) | |
| 370 { | |
| 371 mant = (int16_t) (mant << 1 | 1); | |
| 372 exp--; | |
| 373 } | |
| 374 /*endwhile*/ | |
| 375 mant -= 8; | |
| 376 } | |
| 377 /*endif*/ | |
| 378 | |
| 379 assert(exp >= -4 && exp <= 6); | |
| 380 assert(mant >= 0 && mant <= 7); | |
| 381 | |
| 382 *exp_out = exp; | |
| 383 *mant_out = mant; | |
| 384 } | |
| 385 /*- End of function --------------------------------------------------------*/ | |
| 386 | |
| 387 static void apcm_quantization(int16_t xM[13], | |
| 388 int16_t xMc[13], | |
| 389 int16_t *mant_out, | |
| 390 int16_t *exp_out, | |
| 391 int16_t *xmaxc_out) | |
| 392 { | |
| 393 /* Table 4.5 Normalized inverse mantissa used to compute xM/xmax */ | |
| 394 static const int16_t gsm_NRFAC[8] = | |
| 395 { | |
| 396 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 | |
| 397 }; | |
| 398 int i; | |
| 399 int itest; | |
| 400 int16_t xmax; | |
| 401 int16_t xmaxc; | |
| 402 int16_t temp; | |
| 403 int16_t temp1; | |
| 404 int16_t temp2; | |
| 405 int16_t exp; | |
| 406 int16_t mant; | |
| 407 | |
| 408 /* Find the maximum absolute value xmax of xM[0..12]. */ | |
| 409 xmax = 0; | |
| 410 for (i = 0; i < 13; i++) | |
| 411 { | |
| 412 temp = xM[i]; | |
| 413 temp = saturated_abs16(temp); | |
| 414 if (temp > xmax) | |
| 415 xmax = temp; | |
| 416 /*endif*/ | |
| 417 } | |
| 418 /*endfor*/ | |
| 419 | |
| 420 /* Quantizing and coding of xmax to get xmaxc. */ | |
| 421 exp = 0; | |
| 422 temp = xmax >> 9; | |
| 423 itest = 0; | |
| 424 | |
| 425 for (i = 0; i <= 5; i++) | |
| 426 { | |
| 427 itest |= (temp <= 0); | |
| 428 temp >>= 1; | |
| 429 | |
| 430 assert(exp <= 5); | |
| 431 if (itest == 0) | |
| 432 exp++; | |
| 433 /*endif*/ | |
| 434 } | |
| 435 /*endfor*/ | |
| 436 | |
| 437 assert(exp <= 6 && exp >= 0); | |
| 438 temp = (int16_t) (exp + 5); | |
| 439 | |
| 440 assert(temp <= 11 && temp >= 0); | |
| 441 xmaxc = saturated_add16((xmax >> temp), exp << 3); | |
| 442 | |
| 443 /* Quantizing and coding of the xM[0..12] RPE sequence | |
| 444 to get the xMc[0..12] */ | |
| 445 apcm_quantization_xmaxc_to_exp_mant(xmaxc, &exp, &mant); | |
| 446 | |
| 447 /* This computation uses the fact that the decoded version of xmaxc | |
| 448 can be calculated by using the exponent and the mantissa part of | |
| 449 xmaxc (logarithmic table). | |
| 450 So, this method avoids any division and uses only a scaling | |
| 451 of the RPE samples by a function of the exponent. A direct | |
| 452 multiplication by the inverse of the mantissa (NRFAC[0..7] | |
| 453 found in table 4.5) gives the 3 bit coded version xMc[0..12] | |
| 454 of the RPE samples. | |
| 455 */ | |
| 456 /* Direct computation of xMc[0..12] using table 4.5 */ | |
| 457 assert(exp <= 4096 && exp >= -4096); | |
| 458 assert(mant >= 0 && mant <= 7); | |
| 459 | |
| 460 temp1 = (int16_t) (6 - exp); /* Normalization by the exponent */ | |
| 461 temp2 = gsm_NRFAC[mant]; /* Inverse mantissa */ | |
| 462 | |
| 463 for (i = 0; i < 13; i++) | |
| 464 { | |
| 465 assert(temp1 >= 0 && temp1 < 16); | |
| 466 | |
| 467 temp = xM[i] << temp1; | |
| 468 temp = saturated_mul16(temp, temp2); | |
| 469 temp >>= 12; | |
| 470 xMc[i] = (int16_t) (temp + 4); /* See note below */ | |
| 471 } | |
| 472 /*endfor*/ | |
| 473 | |
| 474 /* NOTE: This equation is used to make all the xMc[i] positive. */ | |
| 475 *mant_out = mant; | |
| 476 *exp_out = exp; | |
| 477 *xmaxc_out = xmaxc; | |
| 478 } | |
| 479 /*- End of function --------------------------------------------------------*/ | |
| 480 | |
| 481 /* 4.2.16 */ | |
| 482 static void apcm_inverse_quantization(int16_t xMc[13], | |
| 483 int16_t mant, | |
| 484 int16_t exp, | |
| 485 int16_t xMp[13]) | |
| 486 { | |
| 487 /* Table 4.6 Normalized direct mantissa used to compute xM/xmax */ | |
| 488 static const int16_t gsm_FAC[8] = | |
| 489 { | |
| 490 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 | |
| 491 }; | |
| 492 int i; | |
| 493 int16_t temp; | |
| 494 int16_t temp1; | |
| 495 int16_t temp2; | |
| 496 int16_t temp3; | |
| 497 | |
| 498 /* This part is for decoding the RPE sequence of coded xMc[0..12] | |
| 499 samples to obtain the xMp[0..12] array. Table 4.6 is used to get | |
| 500 the mantissa of xmaxc (FAC[0..7]). | |
| 501 */ | |
| 502 #if 0 | |
| 503 assert(mant >= 0 && mant <= 7); | |
| 504 #endif | |
| 505 | |
| 506 temp1 = gsm_FAC[mant]; /* See 4.2-15 for mant */ | |
| 507 temp2 = saturated_sub16(6, exp); /* See 4.2-15 for exp */ | |
| 508 temp3 = gsm_asl(1, saturated_sub16(temp2, 1)); | |
| 509 | |
| 510 for (i = 0; i < 13; i++) | |
| 511 { | |
| 512 assert(xMc[i] >= 0 && xMc[i] <= 7); /* 3 bit unsigned */ | |
| 513 | |
| 514 temp = (int16_t) ((xMc[i] << 1) - 7); /* Restore sign */ | |
| 515 assert(temp <= 7 && temp >= -7); /* 4 bit signed */ | |
| 516 | |
| 517 temp <<= 12; /* 16 bit signed */ | |
| 518 temp = gsm_mult_r(temp1, temp); | |
| 519 temp = saturated_add16(temp, temp3); | |
| 520 xMp[i] = gsm_asr(temp, temp2); | |
| 521 } | |
| 522 /*endfor*/ | |
| 523 } | |
| 524 /*- End of function --------------------------------------------------------*/ | |
| 525 | |
| 526 /* 4.2.17 */ | |
| 527 static void rpe_grid_positioning(int16_t Mc, | |
| 528 int16_t xMp[13], | |
| 529 int16_t ep[40]) | |
| 530 { | |
| 531 int i = 13; | |
| 532 | |
| 533 /* This procedure computes the reconstructed long term residual signal | |
| 534 ep[0..39] for the LTP analysis filter. The inputs are the Mc | |
| 535 which is the grid position selection and the xMp[0..12] decoded | |
| 536 RPE samples which are upsampled by a factor of 3 by inserting zero | |
| 537 values. | |
| 538 */ | |
| 539 assert(0 <= Mc && Mc <= 3); | |
| 540 | |
| 541 switch (Mc) | |
| 542 { | |
| 543 case 3: | |
| 544 *ep++ = 0; | |
| 545 case 2: | |
| 546 do | |
| 547 { | |
| 548 *ep++ = 0; | |
| 549 case 1: | |
| 550 *ep++ = 0; | |
| 551 case 0: | |
| 552 *ep++ = *xMp++; | |
| 553 } | |
| 554 while (--i); | |
| 555 } | |
| 556 /*endswitch*/ | |
| 557 while (++Mc < 4) | |
| 558 *ep++ = 0; | |
| 559 /*endwhile*/ | |
| 560 } | |
| 561 /*- End of function --------------------------------------------------------*/ | |
| 562 | |
| 563 void gsm0610_rpe_encoding(gsm0610_state_t *s, | |
| 564 int16_t *e, // [-5..-1][0..39][40..44] | |
| 565 int16_t *xmaxc, | |
| 566 int16_t *Mc, | |
| 567 int16_t xMc[13]) | |
| 568 { | |
| 569 int16_t x[40]; | |
| 570 int16_t xM[13]; | |
| 571 int16_t xMp[13]; | |
| 572 int16_t mant; | |
| 573 int16_t exp; | |
| 574 | |
| 575 weighting_filter(x, e); | |
| 576 rpe_grid_selection(x, xM, Mc); | |
| 577 | |
| 578 apcm_quantization(xM, xMc, &mant, &exp, xmaxc); | |
| 579 apcm_inverse_quantization(xMc, mant, exp, xMp); | |
| 580 | |
| 581 rpe_grid_positioning(*Mc, xMp, e); | |
| 582 } | |
| 583 /*- End of function --------------------------------------------------------*/ | |
| 584 | |
| 585 void gsm0610_rpe_decoding(gsm0610_state_t *s, | |
| 586 int16_t xmaxc, | |
| 587 int16_t Mcr, | |
| 588 int16_t xMcr[13], | |
| 589 int16_t erp[40]) | |
| 590 { | |
| 591 int16_t exp; | |
| 592 int16_t mant; | |
| 593 int16_t xMp[13]; | |
| 594 | |
| 595 apcm_quantization_xmaxc_to_exp_mant(xmaxc, &exp, &mant); | |
| 596 apcm_inverse_quantization(xMcr, mant, exp, xMp); | |
| 597 rpe_grid_positioning(Mcr, xMp, erp); | |
| 598 } | |
| 599 /*- End of function --------------------------------------------------------*/ | |
| 600 /*- End of file ------------------------------------------------------------*/ |
