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/lpc.c,v 1.5 1994/12/30 23:14:54 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 #undef P 18*8ec969ceSTreehugger Robot 19*8ec969ceSTreehugger Robot /* 20*8ec969ceSTreehugger Robot * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION 21*8ec969ceSTreehugger Robot */ 22*8ec969ceSTreehugger Robot 23*8ec969ceSTreehugger Robot /* 4.2.4 */ 24*8ec969ceSTreehugger Robot 25*8ec969ceSTreehugger Robot 26*8ec969ceSTreehugger Robot static void Autocorrelation P2((s, L_ACF), 27*8ec969ceSTreehugger Robot word * s, /* [0..159] IN/OUT */ 28*8ec969ceSTreehugger Robot longword * L_ACF) /* [0..8] OUT */ 29*8ec969ceSTreehugger Robot /* 30*8ec969ceSTreehugger Robot * The goal is to compute the array L_ACF[k]. The signal s[i] must 31*8ec969ceSTreehugger Robot * be scaled in order to avoid an overflow situation. 32*8ec969ceSTreehugger Robot */ 33*8ec969ceSTreehugger Robot { 34*8ec969ceSTreehugger Robot register int k, i; 35*8ec969ceSTreehugger Robot 36*8ec969ceSTreehugger Robot word temp, smax, scalauto; 37*8ec969ceSTreehugger Robot 38*8ec969ceSTreehugger Robot #ifdef USE_FLOAT_MUL 39*8ec969ceSTreehugger Robot float float_s[160]; 40*8ec969ceSTreehugger Robot #endif 41*8ec969ceSTreehugger Robot 42*8ec969ceSTreehugger Robot /* Dynamic scaling of the array s[0..159] 43*8ec969ceSTreehugger Robot */ 44*8ec969ceSTreehugger Robot 45*8ec969ceSTreehugger Robot /* Search for the maximum. 46*8ec969ceSTreehugger Robot */ 47*8ec969ceSTreehugger Robot smax = 0; 48*8ec969ceSTreehugger Robot for (k = 0; k <= 159; k++) { 49*8ec969ceSTreehugger Robot temp = GSM_ABS( s[k] ); 50*8ec969ceSTreehugger Robot if (temp > smax) smax = temp; 51*8ec969ceSTreehugger Robot } 52*8ec969ceSTreehugger Robot 53*8ec969ceSTreehugger Robot /* Computation of the scaling factor. 54*8ec969ceSTreehugger Robot */ 55*8ec969ceSTreehugger Robot if (smax == 0) scalauto = 0; 56*8ec969ceSTreehugger Robot else { 57*8ec969ceSTreehugger Robot assert(smax > 0); 58*8ec969ceSTreehugger Robot scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ 59*8ec969ceSTreehugger Robot } 60*8ec969ceSTreehugger Robot 61*8ec969ceSTreehugger Robot /* Scaling of the array s[0...159] 62*8ec969ceSTreehugger Robot */ 63*8ec969ceSTreehugger Robot 64*8ec969ceSTreehugger Robot if (scalauto > 0) { 65*8ec969ceSTreehugger Robot 66*8ec969ceSTreehugger Robot # ifdef USE_FLOAT_MUL 67*8ec969ceSTreehugger Robot # define SCALE(n) \ 68*8ec969ceSTreehugger Robot case n: for (k = 0; k <= 159; k++) \ 69*8ec969ceSTreehugger Robot float_s[k] = (float) \ 70*8ec969ceSTreehugger Robot (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ 71*8ec969ceSTreehugger Robot break; 72*8ec969ceSTreehugger Robot # else 73*8ec969ceSTreehugger Robot # define SCALE(n) \ 74*8ec969ceSTreehugger Robot case n: for (k = 0; k <= 159; k++) \ 75*8ec969ceSTreehugger Robot s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ 76*8ec969ceSTreehugger Robot break; 77*8ec969ceSTreehugger Robot # endif /* USE_FLOAT_MUL */ 78*8ec969ceSTreehugger Robot 79*8ec969ceSTreehugger Robot switch (scalauto) { 80*8ec969ceSTreehugger Robot SCALE(1) 81*8ec969ceSTreehugger Robot SCALE(2) 82*8ec969ceSTreehugger Robot SCALE(3) 83*8ec969ceSTreehugger Robot SCALE(4) 84*8ec969ceSTreehugger Robot } 85*8ec969ceSTreehugger Robot # undef SCALE 86*8ec969ceSTreehugger Robot } 87*8ec969ceSTreehugger Robot # ifdef USE_FLOAT_MUL 88*8ec969ceSTreehugger Robot else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; 89*8ec969ceSTreehugger Robot # endif 90*8ec969ceSTreehugger Robot 91*8ec969ceSTreehugger Robot /* Compute the L_ACF[..]. 92*8ec969ceSTreehugger Robot */ 93*8ec969ceSTreehugger Robot { 94*8ec969ceSTreehugger Robot # ifdef USE_FLOAT_MUL 95*8ec969ceSTreehugger Robot register float * sp = float_s; 96*8ec969ceSTreehugger Robot register float sl = *sp; 97*8ec969ceSTreehugger Robot 98*8ec969ceSTreehugger Robot # define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); 99*8ec969ceSTreehugger Robot # else 100*8ec969ceSTreehugger Robot word * sp = s; 101*8ec969ceSTreehugger Robot word sl = *sp; 102*8ec969ceSTreehugger Robot 103*8ec969ceSTreehugger Robot # define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); 104*8ec969ceSTreehugger Robot # endif 105*8ec969ceSTreehugger Robot 106*8ec969ceSTreehugger Robot # define NEXTI sl = *++sp 107*8ec969ceSTreehugger Robot 108*8ec969ceSTreehugger Robot 109*8ec969ceSTreehugger Robot for (k = 9; k--; L_ACF[k] = 0) ; 110*8ec969ceSTreehugger Robot 111*8ec969ceSTreehugger Robot STEP (0); 112*8ec969ceSTreehugger Robot NEXTI; 113*8ec969ceSTreehugger Robot STEP(0); STEP(1); 114*8ec969ceSTreehugger Robot NEXTI; 115*8ec969ceSTreehugger Robot STEP(0); STEP(1); STEP(2); 116*8ec969ceSTreehugger Robot NEXTI; 117*8ec969ceSTreehugger Robot STEP(0); STEP(1); STEP(2); STEP(3); 118*8ec969ceSTreehugger Robot NEXTI; 119*8ec969ceSTreehugger Robot STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); 120*8ec969ceSTreehugger Robot NEXTI; 121*8ec969ceSTreehugger Robot STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); 122*8ec969ceSTreehugger Robot NEXTI; 123*8ec969ceSTreehugger Robot STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); 124*8ec969ceSTreehugger Robot NEXTI; 125*8ec969ceSTreehugger Robot STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); 126*8ec969ceSTreehugger Robot 127*8ec969ceSTreehugger Robot for (i = 8; i <= 159; i++) { 128*8ec969ceSTreehugger Robot 129*8ec969ceSTreehugger Robot NEXTI; 130*8ec969ceSTreehugger Robot 131*8ec969ceSTreehugger Robot STEP(0); 132*8ec969ceSTreehugger Robot STEP(1); STEP(2); STEP(3); STEP(4); 133*8ec969ceSTreehugger Robot STEP(5); STEP(6); STEP(7); STEP(8); 134*8ec969ceSTreehugger Robot } 135*8ec969ceSTreehugger Robot 136*8ec969ceSTreehugger Robot for (k = 9; k--; L_ACF[k] <<= 1) ; 137*8ec969ceSTreehugger Robot 138*8ec969ceSTreehugger Robot } 139*8ec969ceSTreehugger Robot /* Rescaling of the array s[0..159] 140*8ec969ceSTreehugger Robot */ 141*8ec969ceSTreehugger Robot if (scalauto > 0) { 142*8ec969ceSTreehugger Robot assert(scalauto <= 4); 143*8ec969ceSTreehugger Robot for (k = 160; k--; *s++ <<= scalauto) ; 144*8ec969ceSTreehugger Robot } 145*8ec969ceSTreehugger Robot } 146*8ec969ceSTreehugger Robot 147*8ec969ceSTreehugger Robot #if defined(USE_FLOAT_MUL) && defined(FAST) 148*8ec969ceSTreehugger Robot 149*8ec969ceSTreehugger Robot static void Fast_Autocorrelation P2((s, L_ACF), 150*8ec969ceSTreehugger Robot word * s, /* [0..159] IN/OUT */ 151*8ec969ceSTreehugger Robot longword * L_ACF) /* [0..8] OUT */ 152*8ec969ceSTreehugger Robot { 153*8ec969ceSTreehugger Robot register int k, i; 154*8ec969ceSTreehugger Robot float f_L_ACF[9]; 155*8ec969ceSTreehugger Robot float scale; 156*8ec969ceSTreehugger Robot 157*8ec969ceSTreehugger Robot float s_f[160]; 158*8ec969ceSTreehugger Robot register float *sf = s_f; 159*8ec969ceSTreehugger Robot 160*8ec969ceSTreehugger Robot for (i = 0; i < 160; ++i) sf[i] = s[i]; 161*8ec969ceSTreehugger Robot for (k = 0; k <= 8; k++) { 162*8ec969ceSTreehugger Robot register float L_temp2 = 0; 163*8ec969ceSTreehugger Robot register float *sfl = sf - k; 164*8ec969ceSTreehugger Robot for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; 165*8ec969ceSTreehugger Robot f_L_ACF[k] = L_temp2; 166*8ec969ceSTreehugger Robot } 167*8ec969ceSTreehugger Robot scale = MAX_LONGWORD / f_L_ACF[0]; 168*8ec969ceSTreehugger Robot 169*8ec969ceSTreehugger Robot for (k = 0; k <= 8; k++) { 170*8ec969ceSTreehugger Robot L_ACF[k] = f_L_ACF[k] * scale; 171*8ec969ceSTreehugger Robot } 172*8ec969ceSTreehugger Robot } 173*8ec969ceSTreehugger Robot #endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ 174*8ec969ceSTreehugger Robot 175*8ec969ceSTreehugger Robot /* 4.2.5 */ 176*8ec969ceSTreehugger Robot 177*8ec969ceSTreehugger Robot static void Reflection_coefficients P2( (L_ACF, r), 178*8ec969ceSTreehugger Robot longword * L_ACF, /* 0...8 IN */ 179*8ec969ceSTreehugger Robot register word * r /* 0...7 OUT */ 180*8ec969ceSTreehugger Robot ) 181*8ec969ceSTreehugger Robot { 182*8ec969ceSTreehugger Robot register int i, m, n; 183*8ec969ceSTreehugger Robot register word temp; 184*8ec969ceSTreehugger Robot register longword ltmp; 185*8ec969ceSTreehugger Robot word ACF[9]; /* 0..8 */ 186*8ec969ceSTreehugger Robot word P[ 9]; /* 0..8 */ 187*8ec969ceSTreehugger Robot word K[ 9]; /* 2..8 */ 188*8ec969ceSTreehugger Robot 189*8ec969ceSTreehugger Robot /* Schur recursion with 16 bits arithmetic. 190*8ec969ceSTreehugger Robot */ 191*8ec969ceSTreehugger Robot 192*8ec969ceSTreehugger Robot if (L_ACF[0] == 0) { 193*8ec969ceSTreehugger Robot for (i = 8; i--; *r++ = 0) ; 194*8ec969ceSTreehugger Robot return; 195*8ec969ceSTreehugger Robot } 196*8ec969ceSTreehugger Robot 197*8ec969ceSTreehugger Robot assert( L_ACF[0] != 0 ); 198*8ec969ceSTreehugger Robot temp = gsm_norm( L_ACF[0] ); 199*8ec969ceSTreehugger Robot 200*8ec969ceSTreehugger Robot assert(temp >= 0 && temp < 32); 201*8ec969ceSTreehugger Robot 202*8ec969ceSTreehugger Robot /* ? overflow ? */ 203*8ec969ceSTreehugger Robot for (i = 0; i <= 8; i++) ACF[i] = SASR( L_ACF[i] << temp, 16 ); 204*8ec969ceSTreehugger Robot 205*8ec969ceSTreehugger Robot /* Initialize array P[..] and K[..] for the recursion. 206*8ec969ceSTreehugger Robot */ 207*8ec969ceSTreehugger Robot 208*8ec969ceSTreehugger Robot for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; 209*8ec969ceSTreehugger Robot for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; 210*8ec969ceSTreehugger Robot 211*8ec969ceSTreehugger Robot /* Compute reflection coefficients 212*8ec969ceSTreehugger Robot */ 213*8ec969ceSTreehugger Robot for (n = 1; n <= 8; n++, r++) { 214*8ec969ceSTreehugger Robot 215*8ec969ceSTreehugger Robot temp = P[1]; 216*8ec969ceSTreehugger Robot temp = GSM_ABS(temp); 217*8ec969ceSTreehugger Robot if (P[0] < temp) { 218*8ec969ceSTreehugger Robot for (i = n; i <= 8; i++) *r++ = 0; 219*8ec969ceSTreehugger Robot return; 220*8ec969ceSTreehugger Robot } 221*8ec969ceSTreehugger Robot 222*8ec969ceSTreehugger Robot *r = gsm_div( temp, P[0] ); 223*8ec969ceSTreehugger Robot 224*8ec969ceSTreehugger Robot assert(*r >= 0); 225*8ec969ceSTreehugger Robot if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ 226*8ec969ceSTreehugger Robot assert (*r != MIN_WORD); 227*8ec969ceSTreehugger Robot if (n == 8) return; 228*8ec969ceSTreehugger Robot 229*8ec969ceSTreehugger Robot /* Schur recursion 230*8ec969ceSTreehugger Robot */ 231*8ec969ceSTreehugger Robot temp = GSM_MULT_R( P[1], *r ); 232*8ec969ceSTreehugger Robot P[0] = GSM_ADD( P[0], temp ); 233*8ec969ceSTreehugger Robot 234*8ec969ceSTreehugger Robot for (m = 1; m <= 8 - n; m++) { 235*8ec969ceSTreehugger Robot temp = GSM_MULT_R( K[ m ], *r ); 236*8ec969ceSTreehugger Robot P[m] = GSM_ADD( P[ m+1 ], temp ); 237*8ec969ceSTreehugger Robot 238*8ec969ceSTreehugger Robot temp = GSM_MULT_R( P[ m+1 ], *r ); 239*8ec969ceSTreehugger Robot K[m] = GSM_ADD( K[ m ], temp ); 240*8ec969ceSTreehugger Robot } 241*8ec969ceSTreehugger Robot } 242*8ec969ceSTreehugger Robot } 243*8ec969ceSTreehugger Robot 244*8ec969ceSTreehugger Robot /* 4.2.6 */ 245*8ec969ceSTreehugger Robot 246*8ec969ceSTreehugger Robot static void Transformation_to_Log_Area_Ratios P1((r), 247*8ec969ceSTreehugger Robot register word * r /* 0..7 IN/OUT */ 248*8ec969ceSTreehugger Robot ) 249*8ec969ceSTreehugger Robot /* 250*8ec969ceSTreehugger Robot * The following scaling for r[..] and LAR[..] has been used: 251*8ec969ceSTreehugger Robot * 252*8ec969ceSTreehugger Robot * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. 253*8ec969ceSTreehugger Robot * LAR[..] = integer( real_LAR[..] * 16384 ); 254*8ec969ceSTreehugger Robot * with -1.625 <= real_LAR <= 1.625 255*8ec969ceSTreehugger Robot */ 256*8ec969ceSTreehugger Robot { 257*8ec969ceSTreehugger Robot register word temp; 258*8ec969ceSTreehugger Robot register int i; 259*8ec969ceSTreehugger Robot 260*8ec969ceSTreehugger Robot 261*8ec969ceSTreehugger Robot /* Computation of the LAR[0..7] from the r[0..7] 262*8ec969ceSTreehugger Robot */ 263*8ec969ceSTreehugger Robot for (i = 1; i <= 8; i++, r++) { 264*8ec969ceSTreehugger Robot 265*8ec969ceSTreehugger Robot temp = *r; 266*8ec969ceSTreehugger Robot temp = GSM_ABS(temp); 267*8ec969ceSTreehugger Robot assert(temp >= 0); 268*8ec969ceSTreehugger Robot 269*8ec969ceSTreehugger Robot if (temp < 22118) { 270*8ec969ceSTreehugger Robot temp >>= 1; 271*8ec969ceSTreehugger Robot } else if (temp < 31130) { 272*8ec969ceSTreehugger Robot assert( temp >= 11059 ); 273*8ec969ceSTreehugger Robot temp -= 11059; 274*8ec969ceSTreehugger Robot } else { 275*8ec969ceSTreehugger Robot assert( temp >= 26112 ); 276*8ec969ceSTreehugger Robot temp -= 26112; 277*8ec969ceSTreehugger Robot temp <<= 2; 278*8ec969ceSTreehugger Robot } 279*8ec969ceSTreehugger Robot 280*8ec969ceSTreehugger Robot *r = *r < 0 ? -temp : temp; 281*8ec969ceSTreehugger Robot assert( *r != MIN_WORD ); 282*8ec969ceSTreehugger Robot } 283*8ec969ceSTreehugger Robot } 284*8ec969ceSTreehugger Robot 285*8ec969ceSTreehugger Robot /* 4.2.7 */ 286*8ec969ceSTreehugger Robot 287*8ec969ceSTreehugger Robot static void Quantization_and_coding P1((LAR), 288*8ec969ceSTreehugger Robot register word * LAR /* [0..7] IN/OUT */ 289*8ec969ceSTreehugger Robot ) 290*8ec969ceSTreehugger Robot { 291*8ec969ceSTreehugger Robot register word temp; 292*8ec969ceSTreehugger Robot longword ltmp; 293*8ec969ceSTreehugger Robot 294*8ec969ceSTreehugger Robot 295*8ec969ceSTreehugger Robot /* This procedure needs four tables; the following equations 296*8ec969ceSTreehugger Robot * give the optimum scaling for the constants: 297*8ec969ceSTreehugger Robot * 298*8ec969ceSTreehugger Robot * A[0..7] = integer( real_A[0..7] * 1024 ) 299*8ec969ceSTreehugger Robot * B[0..7] = integer( real_B[0..7] * 512 ) 300*8ec969ceSTreehugger Robot * MAC[0..7] = maximum of the LARc[0..7] 301*8ec969ceSTreehugger Robot * MIC[0..7] = minimum of the LARc[0..7] 302*8ec969ceSTreehugger Robot */ 303*8ec969ceSTreehugger Robot 304*8ec969ceSTreehugger Robot # undef STEP 305*8ec969ceSTreehugger Robot # define STEP( A, B, MAC, MIC ) \ 306*8ec969ceSTreehugger Robot temp = GSM_MULT( A, *LAR ); \ 307*8ec969ceSTreehugger Robot temp = GSM_ADD( temp, B ); \ 308*8ec969ceSTreehugger Robot temp = GSM_ADD( temp, 256 ); \ 309*8ec969ceSTreehugger Robot temp = SASR( temp, 9 ); \ 310*8ec969ceSTreehugger Robot *LAR = temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \ 311*8ec969ceSTreehugger Robot LAR++; 312*8ec969ceSTreehugger Robot 313*8ec969ceSTreehugger Robot STEP( 20480, 0, 31, -32 ); 314*8ec969ceSTreehugger Robot STEP( 20480, 0, 31, -32 ); 315*8ec969ceSTreehugger Robot STEP( 20480, 2048, 15, -16 ); 316*8ec969ceSTreehugger Robot STEP( 20480, -2560, 15, -16 ); 317*8ec969ceSTreehugger Robot 318*8ec969ceSTreehugger Robot STEP( 13964, 94, 7, -8 ); 319*8ec969ceSTreehugger Robot STEP( 15360, -1792, 7, -8 ); 320*8ec969ceSTreehugger Robot STEP( 8534, -341, 3, -4 ); 321*8ec969ceSTreehugger Robot STEP( 9036, -1144, 3, -4 ); 322*8ec969ceSTreehugger Robot 323*8ec969ceSTreehugger Robot # undef STEP 324*8ec969ceSTreehugger Robot } 325*8ec969ceSTreehugger Robot 326*8ec969ceSTreehugger Robot void Gsm_LPC_Analysis P3((S, s,LARc), 327*8ec969ceSTreehugger Robot struct gsm_state *S, 328*8ec969ceSTreehugger Robot word * s, /* 0..159 signals IN/OUT */ 329*8ec969ceSTreehugger Robot word * LARc) /* 0..7 LARc's OUT */ 330*8ec969ceSTreehugger Robot { 331*8ec969ceSTreehugger Robot longword L_ACF[9]; 332*8ec969ceSTreehugger Robot 333*8ec969ceSTreehugger Robot #if defined(USE_FLOAT_MUL) && defined(FAST) 334*8ec969ceSTreehugger Robot if (S->fast) Fast_Autocorrelation (s, L_ACF ); 335*8ec969ceSTreehugger Robot else 336*8ec969ceSTreehugger Robot #endif 337*8ec969ceSTreehugger Robot Autocorrelation (s, L_ACF ); 338*8ec969ceSTreehugger Robot Reflection_coefficients (L_ACF, LARc ); 339*8ec969ceSTreehugger Robot Transformation_to_Log_Area_Ratios (LARc); 340*8ec969ceSTreehugger Robot Quantization_and_coding (LARc); 341*8ec969ceSTreehugger Robot } 342