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

📄 gsm610.c

📁 GSM6.10 算法优化及详细注释 本代码较原GSM6.10代码更容易理解 仅供学习
💻 C
📖 第 1 页 / 共 3 页
字号:
		temp = xM[i] << temp1;
		temp = (word) (GSM_MULT( temp, temp2 ));
		temp = SASR(temp, 12);
		xMc[i] = temp + 4;				
	}

	*mant_out  = mant;
	*exp_out   = exp;
	*xmaxc_out = xmaxc;
}

/* 
 * 输入: 量化值xMc[0..12],exp指数,mant尾数
 * 输出:还原量化xMc[0..12]的值
 * 根据量化值xMc[0..12]的值,逆量化估计计算xMp[0..12]
 * This part is for decoding the RPE sequence of coded xMc[0..12]
 * samples to obtain the xMp[0..12] array.  Table 4.6 is used to get
 * the mantissa of xmaxc (FAC[0..7]).
 */
static void APCM_inverse_quantization (register word * xMc, word mant, word exp, register word * xMp)
{
	int 		i;
	word		temp, temp1, temp2, temp3;
	longword	ltmp;

	assert( mant >= 0 && mant <= 7 ); 

	temp1 = gsm_FAC[ mant ];		
	temp2 = gsm_sub( 6, exp );	
	temp3 = gsm_asl( 1, (int) (gsm_sub(temp2, 1))); /* 0.5*2^(temp2)目的四舍五入 */
	for ( i = 0; i < 13; i++)
	{
		assert( *xMc <=7 && *xMc >= 0);
		temp = (*xMc++ << 1) - 7;					/* 取经过逆量化后的平均值 */
		assert(temp <= 7 && temp >= -7);

		temp <<= 12;								/* 转换成平均值 */
		temp = (word) (GSM_MULT_R( temp1, temp));
		temp = (word) (GSM_ADD( temp, temp3 ));		/* 四舍五入+0.5 */
		*xMp++ = gsm_asr( temp, temp2 );			/* 右移temp2位,若temp2为负则左移temp2位 */
	}
}

/*
 * 输入:Mc子序列栅格位置,xMp[0..12]经过自适应量化后的估计值
 * 输出:ep[0..39],拷贝差分估计值估计值
 * This procedure computes the reconstructed long term residual signal
 * ep[0..39] for the LTP analysis filter.	The inputs are the Mc
 * which is the grid position selection and the xMp[0..12] decoded
 * RPE samples which are upsampled by a factor of 3 by inserting zero
 * values.
 */
static void RPE_grid_positioning (word Mc, register word * xMp, register word * ep)
{
	int		i;
	assert(0 <= Mc && Mc <= 3);
	for (i = 0; i < 40; i++)
		ep[i] = 0;
	for (i = 0; i <= 36; i+=3)
		ep[Mc + i] = *xMp++;
}


/* 输入: e[-5..45]差分值,其中e[0..40]为有效值
 * 输出: Mc子序列栅格号(序号),xmaxc为子序列量化值最大值,xMc[0..12]子序列各数值与xm/xmaxc的量化值
 */
void Gsm_RPE_Encoding (struct gsm610_state * g_gsm, word * e, word * xmaxc, word * Mc, word * xMc)
{
	word	x[40];
	word	xM[13], xMp[13];
	word	mant, exp;

	Weighting_filter(e, x);
	RPE_grid_selection(x, xM, Mc);//xM子序列值

	APCM_quantization(		xM, xMc, &mant, &exp, xmaxc);
	APCM_inverse_quantization(	xMc,  mant,  exp, xMp);

	RPE_grid_positioning( *Mc, xMp, e );

}

/* 
 * 输入:xmaxcr最大能量值,Mcr子序列栅格位置,xMcr[0..12]子序列量化值
 * 输出:erp[0..39]差分估计值
 */
void Gsm_RPE_Decoding (struct gsm610_state * g_gsm, word xmaxcr, word Mcr, word * xMcr, word * erp)
{
	word	exp, mant;
	word	xMp[ 13 ];

	APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &exp, &mant );
	APCM_inverse_quantization( xMcr, mant, exp, xMp );
	RPE_grid_positioning( Mcr, xMp, erp );

}

/***************************RPE Code(结束)*******************************************************/
/************************************************************************************************/
/***************************主要函数模块*********************************************************/

/*
 * 输入:s 原始一帧160个采样数据
 * 输出:LARc[0..7]LPC分析自相关系数,分别点6,6,5,5,4,4,3,3个bit;Nc[0..3]4个子帧的LTP滞后系数各占7bit;
 *       bc[0..3]4个子帧LTP增益系数各占2bit;Mc[0..3]4个子帧所选子序列栅格位置(序号)各占2bit;
 *		 xmaxc[0..3]4个子帧所选子序列最大能量量化值占6bit;xMc[13*4]4个子帧13个抽样标量量化值各占3bit;
 *		 一帧160个采样点压缩后共260bit需33byte,
 */
void gsm610_coder (
	gsm610	g_gsm,	/* 储存各运算过程所需联系的数据									IN/OUT  */
	word	* s_in,	/* [0..159]		samples原始数据									IN		*/
	word	* LARc, /* [0..7] LAR coefficients	LPC自相关系数						OUT 	*/
	word	* Nc,	/* [0..3] LTP lag	LTP滞后系数									OUT 	*/
	word	* bc,	/* [0..3] coded LTP gain	LTP增益系数							OUT 	*/
	word	* Mc,	/* [0..3] RPE grid selection	所选子序列栅格位置				OUT 	*/
	word	* xmaxc,/* [0..3] Coded maximum amplitude	所选子序列最大能量量化值	OUT 	*/
	word	* xMc	/* [13*4] normalized RPE samples	13个抽样标量量化			OUT 	*/
	)
{
	int 	k,i;
	word	* dp  = g_gsm->dp0 + 120;	/* [ -120...-1 ] 存放前3个子帧估计值*/
	word	* dpp = dp; 			/* [ 0...39 ]存放该子帧估计值	 */
	static word 	e [50] = {0};	/*存放一个子帧估计数据的差分值[5..44] dp-dpp*/
	word	so[160];				/*so存放原始数据s[0..159]经过运算后的值*/
	longword ltmp;
	Gsm_Preprocess		(g_gsm, s_in, so);
	Gsm_LPC_Analysis	(g_gsm, so, LARc);
	Gsm_Short_Term_Analysis_Filter	(g_gsm, LARc, so);
	for (k = 0; k < 4; k++) 
	{
		Gsm_Long_Term_Predictor ( g_gsm,
								so+k*40, /* d		[0..39] IN	*/
								dp,	  /* dp  [-120..-1] IN	*/
								e + 5,	  /* e		[0..39] OUT */
								dpp,	  /* dpp	[0..39] OUT */
								Nc++,
								bc++);
		
		Gsm_RPE_Encoding		( g_gsm,e + 5,xmaxc++, Mc++, xMc );
		
		for (i = 0; i < 40; i++)
			dp[ i ] = (word) (GSM_ADD( e[5 + i], dpp[i] ));
		xMc += 13;
		dp	+= 40;
		dpp += 40;

	}
	(void)memcpy( (char *)g_gsm->dp0, (char *)(g_gsm->dp0 + 160),
			120 * sizeof(*g_gsm->dp0) );
}

/*
 * 输入:LARcr=[0..7]8个LPC自相关系数,Ncr[0..3]4个LTP滞后值,bcr[0..3]4个LTP增益值
 *		 xmaxcr[0..3]最大能量量化值,xMcr[0..13*4]4个子序列13个量化值
 * 输出:s_out经过解码后的一帧语音160个采样数据
 * Gsm610_Coder()的逆过程
 */
void Gsm610_Decoder (
	gsm610	  g_gsm,
	word	* LARcr,		/* [0..7]				IN		*/
	word	* Ncr,			/* [0..3]				IN		*/
	word	* bcr,			/* [0..3]				IN		*/
	word	* Mcr,			/* [0..3]				IN		*/
	word	* xmaxcr,		/* [0..3]				IN		*/
	word	* xMcr, 		/* [0..13*4]			IN		*/
	word	* s_out
	)		/* [0..159] 			OUT 	*/
{
	int		i, k;
	word	erp[40];
	word	wt[160];
	word	* drp = g_gsm->dp0 + 120;

	for ( k = 0; k < 4; k++)
	{
		Gsm_RPE_Decoding( g_gsm, *xmaxcr, *Mcr, xMcr, erp);
		Gsm_Long_Term_Synthesis_Filtering( g_gsm, *Ncr, *bcr, erp, drp );
		for ( i = 0; i < 40; i++)
			wt[ k * 40 + i] = drp [i];
		xmaxcr ++;
		Mcr ++;
		bcr ++;
		Ncr ++;
		xMcr +=13;
	}
	Gsm_Short_Term_Synthesis_Filter( g_gsm, LARcr, wt, s_out );
	Postprocessing(g_gsm, s_out);
}

/* 
 * 分配初始化gsm610缓存 
 */
gsm610 gsm610_create ()
{
	gsm610		r;

	r = (gsm610)malloc(sizeof(struct gsm610_state));
	if (!r) return r;

	memset((char *)r, 0, sizeof(*r));
	r->nrp = 40;

	return r;
}

/*
 * 释放缓存
 */
void gsm610_destroy (gsm610 g_gsm)
{
	if (g_gsm) 
		free((char *)g_gsm);
}

/*
 * 输入:source 未经过压缩的标准语音数据,共160个采样数据,点320byte。
 * 输出:c 经过编码后语音压缩数据,共占33个字节
 * 压缩原理:首先对一帧160个抽样数据s[0..159](20ms)进行缩减数据取13位有效值,
 * 再进行加权分析,再通过LPC自相关分析得到各个LPC自相关系数量化值LARc[0..8];
 * 接下来对一帧20ms160个抽样数据分成4个子帧处理,每个子帧40个抽样。对每个子帧
 * 查找对应的LTP增益bc与延迟Nc。最后通过RPE差分处理过程编码处理,即将子帧40个抽样
 * 的差分信号分成4个子序列(第一个:0,3..36;第二个:1,4..37;第三个:2,5..38;
 * 第四个:3,6..39),选择最接近原始40个抽样的子序列,子序列栅格位置Mc,并记录子序列
 * 的最大能量量化值xmaxc;压缩前160*2*8bit,压缩后260bit
 */
void gsm610_encode(gsm610 g_gsm, gsm_signal * source, gsm_byte * c)
{
	word	LARc[8];		//存储一帧数据(160)8个LPC自相关分析系数
	word	Nc[4];			//各子序列LTP分析滞后值 
	word	Mc[4];			//存储和子序列栅格位置
	word	bc[4];			//各子序列LTP分析增益值
	word	xmaxc[4];		//经量化后各子序列13个抽样误差最大值
	word	xmc[13*4];		//13个抽样数据量化值为0-7

	gsm610_coder(g_gsm, source, LARc, Nc, bc, Mc, xmaxc, xmc);
	
	*c++ =	 ((GSM_MAGIC & 0xF) << 4)				/* 1 */
		   | ((LARc[0] >> 2) & 0xF);
	*c++ =	 ((LARc[0] & 0x3) << 6)
		   | (LARc[1] & 0x3F);
	*c++ =	 ((LARc[2] & 0x1F) << 3)
		   | ((LARc[3] >> 2) & 0x7);
	*c++ =	 ((LARc[3] & 0x3) << 6)
		   | ((LARc[4] & 0xF) << 2)
		   | ((LARc[5] >> 2) & 0x3);
	*c++ =	 ((LARc[5] & 0x3) << 6)
		   | ((LARc[6] & 0x7) << 3)
		   | (LARc[7] & 0x7);
	*c++ =	 ((Nc[0] & 0x7F) << 1)
		   | ((bc[0] >> 1) & 0x1);
	*c++ =	 ((bc[0] & 0x1) << 7)
		   | ((Mc[0] & 0x3) << 5)
		   | ((xmaxc[0] >> 1) & 0x1F);
	*c++ =	 ((xmaxc[0] & 0x1) << 7)
		   | ((xmc[0] & 0x7) << 4)
		   | ((xmc[1] & 0x7) << 1)
		   | ((xmc[2] >> 2) & 0x1);
	*c++ =	 ((xmc[2] & 0x3) << 6)
		   | ((xmc[3] & 0x7) << 3)
		   | (xmc[4] & 0x7);
	*c++ =	 ((xmc[5] & 0x7) << 5)					/* 10 */
		   | ((xmc[6] & 0x7) << 2)
		   | ((xmc[7] >> 1) & 0x3);
	*c++ =	 ((xmc[7] & 0x1) << 7)
		   | ((xmc[8] & 0x7) << 4)
		   | ((xmc[9] & 0x7) << 1)
		   | ((xmc[10] >> 2) & 0x1);
	*c++ =	 ((xmc[10] & 0x3) << 6)
		   | ((xmc[11] & 0x7) << 3)
		   | (xmc[12] & 0x7);
	*c++ =	 ((Nc[1] & 0x7F) << 1)
		   | ((bc[1] >> 1) & 0x1);
	*c++ =	 ((bc[1] & 0x1) << 7)
		   | ((Mc[1] & 0x3) << 5)
		   | ((xmaxc[1] >> 1) & 0x1F);
	*c++ =	 ((xmaxc[1] & 0x1) << 7)
		   | ((xmc[13] & 0x7) << 4)
		   | ((xmc[14] & 0x7) << 1)
		   | ((xmc[15] >> 2) & 0x1);
	*c++ =	 ((xmc[15] & 0x3) << 6)
		   | ((xmc[16] & 0x7) << 3)
		   | (xmc[17] & 0x7);
	*c++ =	 ((xmc[18] & 0x7) << 5)
		   | ((xmc[19] & 0x7) << 2)
		   | ((xmc[20] >> 1) & 0x3);
	*c++ =	 ((xmc[20] & 0x1) << 7)
		   | ((xmc[21] & 0x7) << 4)
		   | ((xmc[22] & 0x7) << 1)
		   | ((xmc[23] >> 2) & 0x1);
	*c++ =	 ((xmc[23] & 0x3) << 6)
		   | ((xmc[24] & 0x7) << 3)
		   | (xmc[25] & 0x7);
	*c++ =	 ((Nc[2] & 0x7F) << 1)					/* 20 */
		   | ((bc[2] >> 1) & 0x1);
	*c++ =	 ((bc[2] & 0x1) << 7)
		   | ((Mc[2] & 0x3) << 5)
		   | ((xmaxc[2] >> 1) & 0x1F);
	*c++ =	 ((xmaxc[2] & 0x1) << 7)
		   | ((xmc[26] & 0x7) << 4)
		   | ((xmc[27] & 0x7) << 1)
		   | ((xmc[28] >> 2) & 0x1);
	*c++ =	 ((xmc[28] & 0x3) << 6)
		   | ((xmc[29] & 0x7) << 3)
		   | (xmc[30] & 0x7);
	*c++ =	 ((xmc[31] & 0x7) << 5)
		   | ((xmc[32] & 0x7) << 2)
		   | ((xmc[33] >> 1) & 0x3);
	*c++ =	 ((xmc[33] & 0x1) << 7)
		   | ((xmc[34] & 0x7) << 4)
		   | ((xmc[35] & 0x7) << 1)
		   | ((xmc[36] >> 2) & 0x1);
	*c++ =	 ((xmc[36] & 0x3) << 6)
		   | ((xmc[37] & 0x7) << 3)
		   | (xmc[38] & 0x7);
	*c++ =	 ((Nc[3] & 0x7F) << 1)
		   | ((bc[3] >> 1) & 0x1);
	*c++ =	 ((bc[3] & 0x1) << 7)
		   | ((Mc[3] & 0x3) << 5)
		   | ((xmaxc[3] >> 1) & 0x1F);
	*c++ =	 ((xmaxc[3] & 0x1) << 7)
		   | ((xmc[39] & 0x7) << 4)
		   | ((xmc[40] & 0x7) << 1)
		   | ((xmc[41] >> 2) & 0x1);
	*c++ =	 ((xmc[41] & 0x3) << 6) 				/* 30 */
		   | ((xmc[42] & 0x7) << 3)
		   | (xmc[43] & 0x7);
	*c++ =	 ((xmc[44] & 0x7) << 5)
		   | ((xmc[45] & 0x7) << 2)
		   | ((xmc[46] >> 1) & 0x3);
	*c++ =	 ((xmc[46] & 0x1) << 7)
		   | ((xmc[47] & 0x7) << 4)
		   | ((xmc[48] & 0x7) << 1)
		   | ((xmc[49] >> 2) & 0x1);
	*c++ =	 ((xmc[49] & 0x3) << 6)
		   | ((xmc[50] & 0x7) << 3)
		   | (xmc[51] & 0x7);
}

/*
 * 输入:c 未解码前的一帧20ms语音压缩数据,占33byte。
 * 输出: target 解码后的一帧20ms语音数据,共160个采样数据,共320byte。
 * 解压原理:输入33byte经GSM6.10编码后的压缩语音,首先取前4bit判断是否为GSM_MAGIC(类似验证码),
 * 验证通过,进行按位操作具体步骤:1.首先提取LARc[0..7],为接下来6,6,5,5,4,4,3,3位。2.将剩下224bit
 * 分成4部分,即4个子帧来分析,每个子帧占56bit,并对各帧进行位操作。3.将56bit各分配为:LTP滞后Nc[0..3]
 * 为7bit*4(每个子帧56bit前7bit);LTP增益bc[0..3]为2bit*4(接下来2bit);子序列栅格位置Mc[0..3]为2bit*4(接
 * 下来2bit);再接下来为最大能量量化值xmaxc[0..3]占6bit;最后剩39bit分别为子序列13个抽样差分量化值xmc[0..12*4]。
 * 位操作完毕根据各系数逆编码原理解码。
 */
void gsm610_decode (gsm610 g_gsm, gsm_byte * c, gsm_signal * target)
{
	word	LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];

	/* GSM_MAGIC  = (*c >> 4) & 0xF; */

	if (((*c >> 4) & 0x0F) != GSM_MAGIC) 
		return ;//-1;

	LARc[0]  = (*c++ & 0xF) << 2;			/* 1 */
	LARc[0] |= (*c >> 6) & 0x3;
	LARc[1]  = *c++ & 0x3F;
	LARc[2]  = (*c >> 3) & 0x1F;
	LARc[3]  = (*c++ & 0x7) << 2;
	LARc[3] |= (*c >> 6) & 0x3;
	LARc[4]  = (*c >> 2) & 0xF;
	LARc[5]  = (*c++ & 0x3) << 2;
	LARc[5] |= (*c >> 6) & 0x3;
	LARc[6]  = (*c >> 3) & 0x7;
	LARc[7]  = *c++ & 0x7;
	Nc[0]  = (*c >> 1) & 0x7F;
	bc[0]  = (*c++ & 0x1) << 1;
	bc[0] |= (*c >> 7) & 0x1;
	Mc[0]  = (*c >> 5) & 0x3;
	xmaxc[0]  = (*c++ & 0x1F) << 1;
	xmaxc[0] |= (*c >> 7) & 0x1;
	xmc[0]	= (*c >> 4) & 0x7;
	xmc[1]	= (*c >> 1) & 0x7;
	xmc[2]	= (*c++ & 0x1) << 2;
	xmc[2] |= (*c >> 6) & 0x3;
	xmc[3]	= (*c >> 3) & 0x7;
	xmc[4]	= *c++ & 0x7;
	xmc[5]	= (*c >> 5) & 0x7;
	xmc[6]	= (*c >> 2) & 0x7;
	xmc[7]	= (*c++ & 0x3) << 1;			/* 10 */
	xmc[7] |= (*c >> 7) & 0x1;
	xmc[8]	= (*c >> 4) & 0x7;
	xmc[9]	= (*c >> 1) & 0x7;
	xmc[10]  = (*c++ & 0x1) << 2;
	xmc[10] |= (*c >> 6) & 0x3;
	xmc[11]  = (*c >> 3) & 0x7;
	xmc[12]  = *c++ & 0x7;
	Nc[1]  = (*c >> 1) & 0x7F;
	bc[1]  = (*c++ & 0x1) << 1;
	bc[1] |= (*c >> 7) & 0x1;
	Mc[1]  = (*c >> 5) & 0x3;
	xmaxc[1]  = (*c++ & 0x1F) << 1;
	xmaxc[1] |= (*c >> 7) & 0x1;
	xmc[13]  = (*c >> 4) & 0x7;
	xmc[14]  = (*c >> 1) & 0x7;
	xmc[15]  = (*c++ & 0x1) << 2;
	xmc[15] |= (*c >> 6) & 0x3;
	xmc[16]  = (*c >> 3) & 0x7;
	xmc[17]  = *c++ & 0x7;
	xmc[18]  = (*c >> 5) & 0x7;
	xmc[19]  = (*c >> 2) & 0x7;
	xmc[20]  = (*c++ & 0x3) << 1;
	xmc[20] |= (*c >> 7) & 0x1;
	xmc[21]  = (*c >> 4) & 0x7;
	xmc[22]  = (*c >> 1) & 0x7;
	xmc[23]  = (*c++ & 0x1) << 2;
	xmc[23] |= (*c >> 6) & 0x3;
	xmc[24]  = (*c >> 3) & 0x7;
	xmc[25]  = *c++ & 0x7;
	Nc[2]  = (*c >> 1) & 0x7F;
	bc[2]  = (*c++ & 0x1) << 1; 			/* 20 */
	bc[2] |= (*c >> 7) & 0x1;
	Mc[2]  = (*c >> 5) & 0x3;
	xmaxc[2]  = (*c++ & 0x1F) << 1;
	xmaxc[2] |= (*c >> 7) & 0x1;
	xmc[26]  = (*c >> 4) & 0x7;
	xmc[27]  = (*c >> 1) & 0x7;
	xmc[28]  = (*c++ & 0x1) << 2;
	xmc[28] |= (*c >> 6) & 0x3;
	xmc[29]  = (*c >> 3) & 0x7;
	xmc[30]  = *c++ & 0x7;
	xmc[31]  = (*c >> 5) & 0x7;
	xmc[32]  = (*c >> 2) & 0x7;
	xmc[33]  = (*c++ & 0x3) << 1;
	xmc[33] |= (*c >> 7) & 0x1;
	xmc[34]  = (*c >> 4) & 0x7;
	xmc[35]  = (*c >> 1) & 0x7;
	xmc[36]  = (*c++ & 0x1) << 2;
	xmc[36] |= (*c >> 6) & 0x3;
	xmc[37]  = (*c >> 3) & 0x7;
	xmc[38]  = *c++ & 0x7;
	Nc[3]  = (*c >> 1) & 0x7F;
	bc[3]  = (*c++ & 0x1) << 1;
	bc[3] |= (*c >> 7) & 0x1;
	Mc[3]  = (*c >> 5) & 0x3;
	xmaxc[3]  = (*c++ & 0x1F) << 1;
	xmaxc[3] |= (*c >> 7) & 0x1;
	xmc[39]  = (*c >> 4) & 0x7;
	xmc[40]  = (*c >> 1) & 0x7;
	xmc[41]  = (*c++ & 0x1) << 2;
	xmc[41] |= (*c >> 6) & 0x3;
	xmc[42]  = (*c >> 3) & 0x7;
	xmc[43]  = *c++ & 0x7;					/* 30  */
	xmc[44]  = (*c >> 5) & 0x7;
	xmc[45]  = (*c >> 2) & 0x7;
	xmc[46]  = (*c++ & 0x3) << 1;
	xmc[46] |= (*c >> 7) & 0x1;
	xmc[47]  = (*c >> 4) & 0x7;
	xmc[48]  = (*c >> 1) & 0x7;
	xmc[49]  = (*c++ & 0x1) << 2;
	xmc[49] |= (*c >> 6) & 0x3;
	xmc[50]  = (*c >> 3) & 0x7;
	xmc[51]  = *c & 0x7;					/* 33 */

	Gsm610_Decoder(g_gsm, LARc, Nc, bc, Mc, xmaxc, xmc, target);

	//return; 0;
}

⌨️ 快捷键说明

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