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