/*
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<MIC ? 0 : temp - MIC)); \
LAR++;
STEP( 20480, 0, 31, -32 );
STEP( 20480, 0, 31, -32 );
STEP( 20480, 2048, 15, -16 );
STEP( 20480, -2560, 15, -16 );
STEP( 13964, 94, 7, -8 );
STEP( 15360, -1792, 7, -8 );
STEP( 8534, -341, 3, -4 );
STEP( 9036, -1144, 3, -4 );
# undef STEP
}
static void Gsm_LPC_Analysis(gsmword *s, gsmword *LARc)
{
longword L_ACF[9];
Autocorrelation (s, L_ACF);
Reflection_coefficients(L_ACF, LARc);
Transformation_to_Log_Area_Ratios(LARc);
Quantization_and_coding(LARc);
}
static void Weighting_filter(gsmword *e, gsmword *x)
{
longword L_result, ltmp;
gsmword * pe = e;
int k;
pe -= 5;
for (k = 40; k--; pe++)
{
#undef STEP
#define STEP( i, H ) (SASL( pe[i], (H) ) )
L_result = 4096 - STEP( 0, 7 ) - (STEP( 1, 8 ))
+ STEP( 3, 11 ) + STEP( 4, 12 ) + STEP( 4, 10 )
+ STEP( 5, 13 ) + STEP( 6, 12 ) + STEP( 6, 10 )
+ STEP( 7, 11 ) - STEP( 9, 8 ) - STEP( 10, 7 );
*x++ = (gsmword)GSM_ADD( SASR( L_result, 13 ), 0 );
}
}
static void RPE_grid_selection(gsmword *x, gsmword *xM, gsmword *Mc_out)
{
int i;
longword L_result, L_temp;
longword EM;
gsmword Mc;
longword L_common_0_3;
EM = 0;
Mc = 0;
#undef STEP
#define STEP( m, i ) L_temp = SASR( x[m + 3 * i], 2 ); \
L_result += L_temp * L_temp;
L_result = 0;
STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 );
STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 );
STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12);
L_common_0_3 = L_result;
STEP( 0, 0 );
L_result = SASL( L_result, 1 );
EM = L_result;
L_result = 0;
STEP( 1, 0 );
STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 );
STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 );
STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12);
L_result = SASL( L_result, 1 );
if(L_result > 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;
}
syntax highlighted by Code2HTML, v. 0.9.1