⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsm_encode.c

📁 由HawK提供的语音压缩软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
  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 ));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -