/* GSM voice codec, part of the HawkVoice Direct Interface (HVDI) cross platform network voice library Copyright (C) 2001-2003 Phil Frisbie, Jr. (phil@hawksoft.com) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Or go to http://www.gnu.org/copyleft/lgpl.html */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include "private.h" static unsigned char const bitoff[ 256 ] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static gsmword gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 }; static gsmword gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 }; static gsmword gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 }; static gsmword gsm_DLB[4] = {6554, 16384, 26214, 32767}; static gsmword gsm_norm(longword a) { if(a < 0) { if(a <= -1073741824) return 0; a = ~a; } return (gsmword)(a & 0xffff0000 ? ( a & 0xff000000 ? -1 + bitoff[ 0xFF & (a >> 24) ] : 7 + bitoff[ 0xFF & (a >> 16) ] ) : ( a & 0xff00 ? 15 + bitoff[ 0xFF & (a >> 8) ] : 23 + bitoff[ 0xFF & a ] )); } static void Gsm_Preprocess(struct gsm_state * S, short *s, gsmword *so) { gsmword z1 = S->z1; longword L_z2 = S->L_z2; gsmword mp = (gsmword)S->mp; gsmword s1; longword L_s2; longword L_temp; gsmword msp; gsmword SO; int k = 160; while(k--) { SO = (gsmword)(SASL( SASR( *s, 3 ), 2 )); s++; s1 = (gsmword)(SO - z1); z1 = SO; L_s2 = s1; L_s2 = SASL( L_s2, 15 ); L_z2 += L_s2; L_temp = L_z2 + 16384; msp = (gsmword)GSM_MULT_R( mp, -28672 ); mp = (gsmword)SASR( L_temp, 15 ); *so++ = (gsmword)(mp + msp); } S->z1 = z1; S->L_z2 = L_z2; S->mp = mp; } static void Autocorrelation(gsmword *s, longword *L_ACF) { int k, i; gsmword * sp = s; gsmword sl; gsmword temp, smax, scalauto; gsmword ss[160]; gsmword * ssp = ss; smax = 0; for(k = 160; k--; sp++) { temp = (gsmword)GSM_ABS( *sp ); if(temp > smax) smax = temp; } if(smax == 0) { scalauto = 0; } else { scalauto = (gsmword)(4 - gsm_norm( SASL( (longword)smax, 16 ) ));/* sub(4,..) */ } sp = s; if(scalauto > 0) { for(k = 160; k--; sp++, ssp++) *ssp = (gsmword)SASR( *sp, scalauto ); } else { memcpy(ssp, sp, sizeof(ss)); } # define STEP(k) L_ACF[k] += ((longword)sl * ssp[ -(k) ]); # define NEXTI sl = *++ssp ssp = ss; sl = *ssp; for(k = 9; k--; L_ACF[k] = 0) ; STEP (0); NEXTI; STEP(0); STEP(1); NEXTI; STEP(0); STEP(1); STEP(2); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); for(i = 8; i < 160; i++) { NEXTI; STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7); STEP(8); } for(k = 9; k--; L_ACF[k] *= 2) ; } static void Reflection_coefficients(longword *L_ACF, gsmword *r) { int i, m, n; gsmword temp; gsmword ACF[9]; /* 0..8 */ gsmword P[ 9]; /* 0..8 */ gsmword K[ 9]; /* 2..8 */ if(L_ACF[0] == 0) { for(i = 8; i--; *r++ = 0) ; return; } temp = gsm_norm( L_ACF[0] ); for(i = 0; i <= 8; i++) ACF[i] = (gsmword)SASR( SASL (L_ACF[i], temp ), 16 ); for(i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; for(i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; for(n = 1; n <= 8; n++, r++) { temp = P[1]; temp = (gsmword)GSM_ABS(temp); if(P[0] < temp) { for(i = n; i <= 8; i++) *r++ = 0; return; } *r = gsm_div( temp, P[0] ); if(P[1] > 0) *r = (gsmword)-*r; if(n == 8) return; temp = (gsmword)GSM_MULT_R( P[1], *r ); P[0] += temp; for(m = 1; m <= 8 - n; m++) { P[m] = (gsmword)P[ m+1 ] + (gsmword)GSM_MULT_R( K[m], *r ); K[m] = (gsmword)K[ m ] + (gsmword)GSM_MULT_R( P[ m+1 ], *r ); } } } static void Transformation_to_Log_Area_Ratios(gsmword *r) { gsmword temp; int i; for(i = 1; i <= 8; i++, r++) { temp = *r; temp = (gsmword)GSM_ABS(temp); if(temp < 22118) { temp = (gsmword)SASR( temp, 1 ); } else if(temp < 31130) { temp -= 11059; } else { temp -= 26112; temp = (gsmword)SASL( temp, 2 ); } *r = (gsmword)(*r < 0 ? -temp : temp); } } static void Quantization_and_coding(gsmword *LAR) { gsmword temp; # undef STEP # define STEP( A, B, MAC, MIC ) \ temp = (gsmword)GSM_MULT( A, *LAR ); \ temp += B; \ temp += 256; \ temp = (gsmword)SASR( temp, 9 ); \ *LAR = (gsmword)(temp>MAC ? MAC - MIC : (temp EM) { Mc = 1; EM = L_result; } L_result = 0; STEP( 2, 0 ); STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 ); STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 ); STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12); L_result = SASL( L_result, 1 ); if(L_result > EM) { Mc = 2; EM = L_result; } L_result = L_common_0_3; STEP( 3, 12 ); L_result = SASL( L_result, 1 ); if(L_result > EM) { Mc = 3; EM = L_result; } for(i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i]; *Mc_out = Mc; } static void APCM_quantization_xmaxc_to_exp_mant(gsmword xmaxc, gsmword *exp_out, gsmword *mant_out) { gsmword exp, mant; exp = 0; if(xmaxc > 15) exp = (gsmword)(SASR(xmaxc, 3) - 1); mant = (gsmword)(xmaxc - SASL( exp, 3 )); if(mant == 0) { exp = -4; mant = 7; } else { while(mant <= 7) { mant = (gsmword)(SASL(mant, 1) | 1); exp--; } mant -= 8; } *exp_out = exp; *mant_out = mant; } static void APCM_quantization(gsmword *xM, gsmword *xMc, gsmword *mant_out, gsmword *exp_out, gsmword *xmaxc_out) { int i, itest; gsmword xmax, xmaxc, temp, temp1, temp2; gsmword exp, mant; longword ltmp; xmax = 0; for(i = 0; i <= 12; i++) { temp = xM[i]; temp = (gsmword)GSM_ABS(temp); if (temp > xmax) xmax = temp; } exp = 0; temp = (gsmword)SASR( xmax, 9 ); itest = 0; for(i = 0; i <= 5; i++) { itest |= (temp <= 0); temp = (gsmword)SASR( temp, 1 ); if(itest == 0) exp++; /* exp = add (exp, 1) */ } temp = (gsmword)(exp + 5); xmaxc = (gsmword)GSM_ADD( (gsmword)SASR(xmax, temp), (gsmword)SASL(exp, 3) ); APCM_quantization_xmaxc_to_exp_mant( xmaxc, &exp, &mant ); temp1 = (gsmword)(6 - exp); /* normalization by the exponent */ temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */ for(i = 0; i <= 12; i++) { temp = (gsmword)SASL(xM[i], temp1); temp = (gsmword)GSM_MULT( temp, temp2 ); temp = (gsmword)SASR(temp, 12); xMc[i] = (gsmword)(temp + 4); } *mant_out = mant; *exp_out = exp; *xmaxc_out = xmaxc; } static void APCM_inverse_quantization(gsmword *xMc, gsmword mant, gsmword exp, gsmword *xMp) { int i; gsmword temp, temp1, temp2, temp3; longword ltmp; temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */ temp2 = (gsmword)GSM_SUB( 6, exp ); /* see 4.2-15 for exp */ temp3 = (gsmword)SASL( 1, GSM_SUB( temp2, 1 )); for(i = 13; i--;) { temp = (gsmword)(SASL(*xMc++, 1) - 7); /* restore sign */ temp = (gsmword)SASL(temp, 12); /* 16 bit signed */ temp = (gsmword)GSM_MULT_R( temp1, temp ); temp = (gsmword)GSM_ADD( temp, temp3 ); *xMp++ = (gsmword)SASR( temp, temp2 ); } } static void RPE_grid_positioning(gsmword Mc, gsmword *xMp, gsmword *ep) { int i = 13; switch (Mc) { case 3: *ep++ = 0; case 2: do { *ep++ = 0; case 1: *ep++ = 0; case 0: *ep++ = *xMp++; } while (--i != 0); } while(++Mc < 4) *ep++ = 0; } static void Gsm_RPE_Encoding(gsmword *e, gsmword *xmaxc, gsmword *Mc, gsmword *xMc) { gsmword x[40]; gsmword xM[13], xMp[13]; gsmword mant, exp; Weighting_filter(e, x); RPE_grid_selection(x, xM, Mc); APCM_quantization( xM, xMc, &mant, &exp, xmaxc); APCM_inverse_quantization( xMc, mant, exp, xMp); RPE_grid_positioning( *Mc, xMp, e ); } static void Decoding_of_the_coded_Log_Area_Ratios(gsmword *LARc, gsmword *LARpp) { gsmword temp1; longword ltmp; #undef STEP #define STEP( B, MIC, INVA ) \ temp1 = (gsmword)(SASL( *LARc++ + MIC , 10)); \ temp1 -= SASL( B, 1 ); \ temp1 = (gsmword)GSM_MULT_R( INVA, temp1 ); \ *LARpp++ = (gsmword)GSM_ADD( temp1, temp1 ); STEP( 0, -32, 13107 ); STEP( 0, -32, 13107 ); STEP( 2048, -16, 13107 ); STEP( -2560, -16, 13107 ); STEP( 94, -8, 19223 ); STEP( -1792, -8, 17476 ); STEP( -341, -4, 31454 ); STEP( -1144, -4, 29708 ); } INLINE void Coefficients_0_12(gsmword * LARpp_j_1, gsmword * LARpp_j, gsmword * LARp) { int i; for(i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) { *LARp = (gsmword)(SASR( *LARpp_j_1, 2 ) + SASR( *LARpp_j, 2 )); *LARp += (gsmword)SASR( *LARpp_j_1, 1); } } INLINE void Coefficients_13_26(gsmword * LARpp_j_1, gsmword * LARpp_j, gsmword * LARp) { int i; for(i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) *LARp = SASR( *LARpp_j_1, 1) + SASR( *LARpp_j, 1 ); } INLINE void Coefficients_27_39(gsmword * LARpp_j_1, gsmword * LARpp_j, gsmword * LARp) { int i; for(i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { *LARp = (gsmword)(SASR( *LARpp_j_1, 2 ) + SASR( *LARpp_j, 2 )); *LARp += (gsmword)SASR( *LARpp_j, 1 ); } } INLINE void Coefficients_40_159(gsmword * LARpp_j, gsmword * LARp) { int i; for(i = 1; i <= 8; i++, LARp++, LARpp_j++) *LARp = *LARpp_j; } static void LARp_to_rp(gsmword * LARp) { int i; gsmword temp; for(i = 1; i <= 8; i++, LARp++) { if(*LARp < 0) { temp = (gsmword)GSM_ABS( *LARp ); *LARp = (gsmword)(- ((temp < 11059) ? SASL( temp, 1 ) : ((temp < 20070) ? temp + 11059 : ( SASR( temp, 2 ) + 26112 )))); } else { temp = *LARp; *LARp = (gsmword)((temp < 11059) ? SASL( temp, 1 ) : ((temp < 20070) ? temp + 11059 : ( SASR( temp, 2 ) + 26112 ))); } } } static void Short_term_analysis_filtering(struct gsm_state *S, gsmword *rp, int k_n, gsmword *s) { gsmword *u = S->u; gsmword di, ui, sav; longword ltmp; gsmword u0=u[0], u1=u[1], u2=u[2], u3=u[3], u4=u[4], u5=u[5], u6=u[6], u7=u[7]; gsmword rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7; rp0 = rp[0]; rp1 = rp[1]; rp2 = rp[2]; rp3 = rp[3]; rp4 = rp[4]; rp5 = rp[5]; rp6 = rp[6]; rp7 = rp[7]; while( k_n-- != 0) { di = sav = *s; ui = u0; u0 = sav; sav = ui + (gsmword)GSM_MULT_R(rp0, di); di += (gsmword)GSM_MULT_R(rp0, ui); ui = u1; u1 = sav; sav = ui + (gsmword)GSM_MULT_R(rp1, di); di += (gsmword)GSM_MULT_R(rp1, ui); ui = u2; u2 = sav; sav = ui + (gsmword)GSM_MULT_R(rp2, di); di += (gsmword)GSM_MULT_R(rp2, ui); ui = u3; u3 = sav; sav = ui + (gsmword)GSM_MULT_R(rp3, di); di += (gsmword)GSM_MULT_R(rp3, ui); ui = u4; u4 = sav; sav = ui + (gsmword)GSM_MULT_R(rp4, di); di += (gsmword)GSM_MULT_R(rp4, ui); ui = u5; u5 = sav; sav = ui + (gsmword)GSM_MULT_R(rp5,di); di += (gsmword)GSM_MULT_R(rp5,ui); ui = u6; u6 = sav; sav = ui + (gsmword)GSM_MULT_R(rp6,di); di += (gsmword)GSM_MULT_R(rp6,ui); ui = u7; u7 = sav; *s++ = (gsmword)GSM_ADD( di, (gsmword)GSM_MULT_R(rp7,ui) ); /* This GSM_ADD is needed for over/under flow */ } u[0]=GSM_ADD(u0, 0); u[1]=GSM_ADD(u1, 0); u[2]=GSM_ADD(u2, 0); u[3]=GSM_ADD(u3, 0); u[4]=GSM_ADD(u4, 0); u[5]=GSM_ADD(u5, 0); u[6]=GSM_ADD(u6, 0); u[7]=GSM_ADD(u7, 0); } static void Gsm_Short_Term_Analysis_Filter( struct gsm_state *S, gsmword *LARc, gsmword *s) { gsmword * LARpp_j = S->LARpp[ S->j ]; gsmword * LARpp_j_1 = S->LARpp[ S->j ^= 1 ]; gsmword LARp[8]; Decoding_of_the_coded_Log_Area_Ratios(LARc, LARpp_j); Coefficients_0_12(LARpp_j_1, LARpp_j, LARp); LARp_to_rp(LARp); Short_term_analysis_filtering(S, LARp, 13, s); Coefficients_13_26(LARpp_j_1, LARpp_j, LARp); LARp_to_rp(LARp); Short_term_analysis_filtering(S, LARp, 14, s + 13); Coefficients_27_39(LARpp_j_1, LARpp_j, LARp); LARp_to_rp(LARp); Short_term_analysis_filtering(S, LARp, 13, s + 27); Coefficients_40_159(LARpp_j, LARp); LARp_to_rp(LARp); Short_term_analysis_filtering(S, LARp, 120, s + 40); } static void Calculation_of_the_LTP_parameters(gsmword *d, gsmword *dp, gsmword *bc_out, gsmword *Nc_out) { int k, lambda; gsmword Nc, bc; gsmword wt[40]; gsmword * pwt = wt; longword L_max, L_power; gsmword R, S, dmax, scal; gsmword temp; gsmword * pd = d; dmax = 0; for (k = 0; k < 40; k+=8) { # undef STEP # define STEP temp = (gsmword)GSM_ABS( *pd );\ if (temp > dmax) dmax = temp;\ pd++; STEP;STEP;STEP;STEP; STEP;STEP;STEP;STEP; } temp = 0; if(dmax == 0) scal = 0; else temp = gsm_norm( SASL( (longword)dmax, 16 ) ); if(temp > 6) scal = 0; else scal = (gsmword)(6 - temp); pd = d; for (k = 0; k < 40; k+=8) { # undef STEP # define STEP *pwt = (gsmword)SASR( *pd, scal ); pd++; pwt++; STEP;STEP;STEP;STEP; STEP;STEP;STEP;STEP; } L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda++) { # undef STEP # define STEP(k) (longword)wt[k] * dp[k - lambda]; register longword L_result; L_result = STEP(0) ; L_result += STEP(1) ; L_result += STEP(2) ; L_result += STEP(3) ; L_result += STEP(4) ; L_result += STEP(5) ; L_result += STEP(6) ; L_result += STEP(7) ; L_result += STEP(8) ; L_result += STEP(9) ; L_result += STEP(10) ; L_result += STEP(11) ; L_result += STEP(12) ; L_result += STEP(13) ; L_result += STEP(14) ; L_result += STEP(15) ; L_result += STEP(16) ; L_result += STEP(17) ; L_result += STEP(18) ; L_result += STEP(19) ; L_result += STEP(20) ; L_result += STEP(21) ; L_result += STEP(22) ; L_result += STEP(23) ; L_result += STEP(24) ; L_result += STEP(25) ; L_result += STEP(26) ; L_result += STEP(27) ; L_result += STEP(28) ; L_result += STEP(29) ; L_result += STEP(30) ; L_result += STEP(31) ; L_result += STEP(32) ; L_result += STEP(33) ; L_result += STEP(34) ; L_result += STEP(35) ; L_result += STEP(36) ; L_result += STEP(37) ; L_result += STEP(38) ; L_result += STEP(39) ; if (L_result > L_max) { Nc = (gsmword)lambda; L_max = L_result; } } *Nc_out = Nc; L_max = SASL(L_max, 1 ); L_max = SASR( L_max, (6 - scal) ); /* sub(6, scal) */ L_power = 0; for (k = 0; k < 40; k+=4) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; L_temp = SASR( dp[k + 1 - Nc], 3 ); L_power += L_temp * L_temp; L_temp = SASR( dp[k + 2 - Nc], 3 ); L_power += L_temp * L_temp; L_temp = SASR( dp[k + 3 - Nc], 3 ); L_power += L_temp * L_temp; } L_power = SASL( L_power, 1 ); if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = (gsmword)SASR( SASL( L_max, temp ), 16 ); S = (gsmword)SASR( SASL( L_power, temp ), 16 ); for(bc = 0; bc <= 2; bc++) { if(R <= GSM_MULT(S, gsm_DLB[bc])) break; } *bc_out = bc; } static void Cut_Calculation_of_the_LTP_parameters(gsmword *d, gsmword *dp, gsmword *bc_out, gsmword *Nc_out) { int k, lambda; gsmword Nc, bc; longword L_result; longword L_max, L_power; gsmword R, S, dmax, scal, best_k; gsmword temp, wt_k; dmax = best_k = 0; for (k = 0; k <= 39; k++) { temp = (gsmword)GSM_ABS( d[k] ); if (temp > dmax) { dmax = temp; best_k = (gsmword)k; } } temp = 0; if (dmax == 0) { scal = 0; } else { temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = (gsmword)(6 - temp); L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ wt_k = (gsmword)SASR(d[best_k], scal); for (lambda = 40; lambda <= 120; lambda++) { L_result = (longword)wt_k * dp[best_k - lambda]; if (L_result > L_max) { Nc = (gsmword)lambda; L_max = L_result; } } *Nc_out = Nc; L_max <<= 1; L_max = L_max >> (6 - scal); /* sub(6, scal) */ L_power = 0; for (k = 0; k <= 39; k++) { longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm(L_power); R = (gsmword)SASR( SASL(L_max, temp), 16 ); S = (gsmword)SASR( SASL(L_power, temp), 16 ); for (bc = 0; bc <= 2; bc++) { if (R <= GSM_MULT(S, gsm_DLB[bc])) break; } *bc_out = bc; } static void Long_term_analysis_filtering(gsmword bc, gsmword Nc, gsmword *dp, gsmword *d, gsmword *dpp, gsmword *e) { int k; dp -= Nc; # undef STEP # define STEP(BP) \ for (k = 40; k--; e++, dpp++, d++, *dp++) { \ *dpp = (gsmword)GSM_MULT_R( BP, *dp); \ *e = (gsmword)( *d - *dpp ); \ } switch (bc) { case 0: STEP( 3277 ); break; case 1: STEP( 11469 ); break; case 2: STEP( 21299 ); break; case 3: STEP( 32767 ); break; } } static void Gsm_Long_Term_Predictor(struct gsm_state *S, gsmword *d, gsmword *dp, gsmword *e, gsmword *dpp, gsmword *Nc, gsmword *bc) { if(S->ltp_cut != 0) { Cut_Calculation_of_the_LTP_parameters(d, dp, bc, Nc); } else { Calculation_of_the_LTP_parameters(d, dp, bc, Nc); } Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); } static void Gsm_Coder(struct gsm_state *S, short *s, gsmword *LARc, gsmword *Nc, gsmword *bc, gsmword *Mc, gsmword *xmaxc, gsmword *xMc) { int k; gsmword *dp = S->dp0 + 120; /* [ -120...-1 ] */ gsmword e[50]; gsmword *pe = &e[5]; gsmword so[160]; memset(e, 0, sizeof(e)); Gsm_Preprocess(S, s, so); Gsm_LPC_Analysis(so, LARc); Gsm_Short_Term_Analysis_Filter (S, LARc, so); for (k = 0; k <= 3; k++, xMc += 13) { int i; Gsm_Long_Term_Predictor(S, so+k*40, dp, pe, dp, Nc++, bc++); Gsm_RPE_Encoding(pe, xmaxc++, Mc++, xMc ); for (i = 0; i <= 39; i++, dp++) *dp += (gsmword)pe[i]; } (void)memcpy( (char *)S->dp0, (char *)(S->dp0 + 160), 120 * sizeof(*S->dp0) ); } int gsm_encode(struct gsm_state * s, short * source, unsigned char * c) { gsmword LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); *c++ = (unsigned char)(((GSM_MAGIC & 0xF) << 4) /* 1 */ | ((LARc[0] >> 2) & 0xF)); *c++ = (unsigned char)(((LARc[0] & 0x3) << 6) | (LARc[1] & 0x3F)); *c++ = (unsigned char)(((LARc[2] & 0x1F) << 3) | ((LARc[3] >> 2) & 0x7)); *c++ = (unsigned char)(((LARc[3] & 0x3) << 6) | ((LARc[4] & 0xF) << 2) | ((LARc[5] >> 2) & 0x3)); *c++ = (unsigned char)(((LARc[5] & 0x3) << 6) | ((LARc[6] & 0x7) << 3) | (LARc[7] & 0x7)); *c++ = (unsigned char)(((Nc[0] & 0x7F) << 1) | ((bc[0] >> 1) & 0x1)); *c++ = (unsigned char)(((bc[0] & 0x1) << 7) | ((Mc[0] & 0x3) << 5) | ((xmaxc[0] >> 1) & 0x1F)); *c++ = (unsigned char)(((xmaxc[0] & 0x1) << 7) | ((xmc[0] & 0x7) << 4) | ((xmc[1] & 0x7) << 1) | ((xmc[2] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[2] & 0x3) << 6) | ((xmc[3] & 0x7) << 3) | (xmc[4] & 0x7)); *c++ = (unsigned char)(((xmc[5] & 0x7) << 5) /* 10 */ | ((xmc[6] & 0x7) << 2) | ((xmc[7] >> 1) & 0x3)); *c++ = (unsigned char)(((xmc[7] & 0x1) << 7) | ((xmc[8] & 0x7) << 4) | ((xmc[9] & 0x7) << 1) | ((xmc[10] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[10] & 0x3) << 6) | ((xmc[11] & 0x7) << 3) | (xmc[12] & 0x7)); *c++ = (unsigned char)(((Nc[1] & 0x7F) << 1) | ((bc[1] >> 1) & 0x1)); *c++ = (unsigned char)(((bc[1] & 0x1) << 7) | ((Mc[1] & 0x3) << 5) | ((xmaxc[1] >> 1) & 0x1F)); *c++ = (unsigned char)(((xmaxc[1] & 0x1) << 7) | ((xmc[13] & 0x7) << 4) | ((xmc[14] & 0x7) << 1) | ((xmc[15] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[15] & 0x3) << 6) | ((xmc[16] & 0x7) << 3) | (xmc[17] & 0x7)); *c++ = (unsigned char)(((xmc[18] & 0x7) << 5) | ((xmc[19] & 0x7) << 2) | ((xmc[20] >> 1) & 0x3)); *c++ = (unsigned char)(((xmc[20] & 0x1) << 7) | ((xmc[21] & 0x7) << 4) | ((xmc[22] & 0x7) << 1) | ((xmc[23] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[23] & 0x3) << 6) | ((xmc[24] & 0x7) << 3) | (xmc[25] & 0x7)); *c++ = (unsigned char)(((Nc[2] & 0x7F) << 1) /* 20 */ | ((bc[2] >> 1) & 0x1)); *c++ = (unsigned char)(((bc[2] & 0x1) << 7) | ((Mc[2] & 0x3) << 5) | ((xmaxc[2] >> 1) & 0x1F)); *c++ = (unsigned char)(((xmaxc[2] & 0x1) << 7) | ((xmc[26] & 0x7) << 4) | ((xmc[27] & 0x7) << 1) | ((xmc[28] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[28] & 0x3) << 6) | ((xmc[29] & 0x7) << 3) | (xmc[30] & 0x7)); *c++ = (unsigned char)(((xmc[31] & 0x7) << 5) | ((xmc[32] & 0x7) << 2) | ((xmc[33] >> 1) & 0x3)); *c++ = (unsigned char)(((xmc[33] & 0x1) << 7) | ((xmc[34] & 0x7) << 4) | ((xmc[35] & 0x7) << 1) | ((xmc[36] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[36] & 0x3) << 6) | ((xmc[37] & 0x7) << 3) | (xmc[38] & 0x7)); *c++ = (unsigned char)(((Nc[3] & 0x7F) << 1) | ((bc[3] >> 1) & 0x1)); *c++ = (unsigned char)(((bc[3] & 0x1) << 7) | ((Mc[3] & 0x3) << 5) | ((xmaxc[3] >> 1) & 0x1F)); *c++ = (unsigned char)(((xmaxc[3] & 0x1) << 7) | ((xmc[39] & 0x7) << 4) | ((xmc[40] & 0x7) << 1) | ((xmc[41] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[41] & 0x3) << 6) /* 30 */ | ((xmc[42] & 0x7) << 3) | (xmc[43] & 0x7)); *c++ = (unsigned char)(((xmc[44] & 0x7) << 5) | ((xmc[45] & 0x7) << 2) | ((xmc[46] >> 1) & 0x3)); *c++ = (unsigned char)(((xmc[46] & 0x1) << 7) | ((xmc[47] & 0x7) << 4) | ((xmc[48] & 0x7) << 1) | ((xmc[49] >> 2) & 0x1)); *c++ = (unsigned char)(((xmc[49] & 0x3) << 6) | ((xmc[50] & 0x7) << 3) | (xmc[51] & 0x7)); return GSM_ENCODED_FRAME_SIZE; }