annotate src/libsndfile-1.0.25/src/GSM610/rpe.c @ 159:f4b37539fcc7

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