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

📄 conv_cor.c

📁 4.8k/s速率FS1016标准语音压缩源码
💻 C
字号:
          /*LINTLIBRARY*/          /*PROTOLIB1*/#include <math.h>#include "main.h"#include "conv_cor.h"#include "rint.h"static void CalcStochConv(float	ExcVec[],int	ExVecLen,float	LPImpResp[],int	LenTruncH,float	Conv[MAX_CW_VEC_LEN]);static void EndCorrectStoch(float	ExcVal,float	LPImpResp[],int	LenTruncH,float	Conv[]);static void CalcCorEngStoch(float	Residual[RES_LEN],float	Conv[],float	ExcVal1,float	ExcVal2,int	First,float	*Cor,float 	*Energy);static void CompGainErrStoch(float	Energy,float	Cor,float	*Gain,float	*Error);/**************************************************************************** ROUTINE*		ConvCor** FUNCTION*		Find codeword gain and error (TERNARY CODE BOOK ASSUMED!)** SYNOPSIS*               ConvCor(ExcVec, ExVecLen, First, LPImpResp, LenTruncH, NegErr)**   formal **                       data    I/O*       name            type    type    function*       -------------------------------------------------------------------*       ExcVec		float	 i	excitation vector (ternary codeword)*       ExcVecLen	int	 i	size of ex (dimension of codeword)*       First		int	 i	first call flag*	LPImpResp	float	 i	LPC Impulse Response*	LenTruncH	int	 i	Length to truncate impulse response*       NegErr		float	 o	negative partial squared error**       ConvCor		float	fun	optimal gain for ex***==========================================================================*	* DESCRIPTION** (The calculations below may be valid for version 3.2, but may not be *  correct for version 3.3).**	For each code word find its gain and error:*	   a.  Filter code words through impulse response*	       of perceptual weighting filter (LPC filter with*	       bandwidth broadening).*	   b.  Correlate filtered result with actual second error*	       signal (e0).*	   c.  Compute MSPE gain and error for code book vector.**	Notes:  Codewords may contain many zeros (i.e., ex(1)=0).  The*		code book could be accessed by a pointer to nonzero samples.*		Because the code book is static, it`s silly to test its*		samples as in the code below.**		Proper selection of the convolution length (len) depends on*		the perceptual weighting filter's expansion factor (gamma)*		which controls the damping of the impulse response.**		This is one of CELP's most computationally intensive*		routines.  Neglecting overhead, the approximate number of*		DSP instructions (add, multiply, multiply accumulate, or*		compare) per second (IPS) is:**	               Code book size   MIPS*	               --------------   ----*	                   64           1.1*	                  128           2.1*	                  256           4.2*	                  512 (max)     8.3**	        C:  convolution (recursive truncated end-point correction)*	        R:  correlation*	        E:  energy (recursive end-point correction)*	        G:  gain quantization**	celp code book search complexity (doesn't fully exploit ternary values!):*	implicit undefined(a-z)cc	DSP chip instructions/operation:*	integer MUL, ADD, SUB, MAC, MAD, CMP*	parameter (MUL=1)	!multiply*	parameter (ADD=1)	!add*	parameter (SUB=1)	!subtract*	parameter (MAC=1)	!multiply & accumulate*	parameter (MAD=2)	!multiply & add*	parameter (CMP=1)	!comparecc	CELP algorithm parameters:*	integer L, len, K, shift, g_bits*	real p, F*	parameter (L=60)	!subframe length*	parameter (len=30)	!length to truncate calculations (<= L)*	parameter (p=0.77)	!code book sparsity*	parameter (shift=2)	!shift between code words*	parameter (K=4)		!number of subframes/frame*	parameter (F=30.e-3)	!time (seconds)/frame*	parameter (g_bits=5)	!cbgain bit allocationc*	integer j*	parameter (j=10)*	integer N(j), i*	real C, R, E, G, IPS*	data N/1, 2, 4, 8, 16, 32, 64, 128, 256, 512/*	print 1*1	format(10x,'N',10x,'C',13x,'R',12x,'E',15x,'G',13x,'MIPS')*	do i = 1, j*	   C = (335)*MAD + (N(i)-1)*shift*(1.-p)*len*ADD*	   R = N(i)*L*MAC*	   E = L*MAC + (N(i)-1)*((1.-p*p)*L*MAC + (p*p)*2*MAD)*	   G = N(i)*(g_bits*(CMP+MUL+ADD) + 3*MUL+1*SUB)*	   IPS = (C+R+E+G)*K/F*	   print *,N(i),C*K/1.e6/F,R*K/1.e6/F,E*K/1.e6/F,G*K/1.e6/F,IPS/1.e6*	end do*	end**    N        C             R             E               G           MIPS*    1  8.9333333E-02  8.0000004E-03  8.0000004E-03  2.5333334E-03  0.1078667   *    2  9.1173328E-02  1.6000001E-02  1.1573013E-02  5.0666668E-03  0.1238130   *    4  9.4853334E-02  3.2000002E-02  1.8719040E-02  1.0133334E-02  0.1557057   *    8  0.1022133      6.4000003E-02  3.3011094E-02  2.0266667E-02  0.2194911   *   16  0.1169333      0.1280000      6.1595201E-02  4.0533334E-02  0.3470618   *   32  0.1463733      0.2560000      0.1187634      8.1066668E-02  0.6022034   *   64  0.2052534      0.5120000      0.2330998      0.1621333       1.112487   *  128  0.3230133       1.024000      0.4617727      0.3242667       2.133053   *  256  0.5585334       2.048000      0.9191184      0.6485333       4.174185   *  512   1.029573       4.096000       1.833810       1.297067       8.256450  **==========================================================================** CALLED BY**	cbsearch** CALLS**	gainencode2**==========================================================================** REFERENCES**	See REFERENCES in celp.c...and:**	Lin, Daniel, "New Approaches to Stochastic Coding of Speech*	Sources at Very Low Bit Rates," Signal Processing III:  Theories*	and Applications (Proceedings of EUSIPCO-86), 1986, p.445.**	Xydeas, C.S., M.A. Ireton and D.K. Baghbadrani, "Theory and*	Real Time Implementation of a CELP Coder at 4.8 and 6.0 kbits/s*	Using Ternary Code Excitation," Fifth International Conference on*	Digital Processing of Signals in Communications, 1988, p. 167.**	Ess, Mike, "Simple Convolution on the Cray X-MP,"*	Supercomputer, March 1988, p. 35**	Supercomputer, July 1988, p. 24****************************************************************************/float ConvCor(float	ExcVec[],int	ExVecLen,int	First,float	LPImpResp[SF_LEN],int 	LenTruncH,float	Residual[RES_LEN],float	*NegErr){static float 	Conv[MAX_CW_VEC_LEN];static float 	Energy=0.0;float		Cor;float		Gain;	if (First)	{/*  For first codeword, calculate and save convolution of codeword with     truncated impulse response */	  CalcStochConv(ExcVec, ExVecLen, LPImpResp, LenTruncH, Conv);	}	else	{	  /*  End correct the convolution sum on subsequent code words *//*  First Shift */	  EndCorrectStoch(ExcVec[1], LPImpResp, LenTruncH, Conv);/*  Second Shift */	  EndCorrectStoch(ExcVec[0], LPImpResp, LenTruncH, Conv);	}/*  Calculate correlation and energy */	CalcCorEngStoch(Residual, Conv, ExcVec[0], ExcVec[1], First, &Cor, &Energy);/*  Compute Gain and Error */	CompGainErrStoch(Energy, Cor, &Gain, NegErr);	return Gain;}/**************************************************************************** ROUTINE*		CalcStochConv** FUNCTION*		Calculate and save convolution of codeword with *		truncated impulse response** SYNOPSIS*               CalcStochConv(ExcVec, ExcVecLen, LPImpulseResponse, Conv)**   formal **                       data    I/O*       name            type    type    function*       -------------------------------------------------------------------*       ExcVec		float	 i	excitation vector (ternary codeword)*       ExcVecLen	int	 i	excitation vector length*	LPImpResp	float	 i	LPC Impulse Response*	LenTruncH	int	 i	length to truncate impulse response*	Conv		float	 o	Convolution of codeword with impulse*					response*****************************************************************************	   For first code word, calculate and save convolution*	   of code word with truncated (to len) impulse response:**	   NOTES: A standard convolution of two L point sequences*	          produces 2L-1 points, however, this convolution*	          generates only the first L points.**	          A "scalar times vector accumulation" method is used*	          to exploit (skip) zero samples of the code words:**	          min(L-i+1, len)*	   y         =  SUM  ex * h   , where i = 1, ..., L points*	    i+j-1, t    j=1    i   j**	                ex |1 2  .  .  .  L|*	   h |x x len ... 2 1|               = y(1)*	     h |x x len ... 2 1|             = y(2)*	                      :                 :*	                 h |x x len ... 2 1| = y(L)****************************************************************************/void CalcStochConv(float	ExcVec[],int	ExcVecLen,float	LPImpResp[],int	LenTruncH,float	Conv[MAX_CW_VEC_LEN]){int	i, j;/*  Initialize */	for(i=0; i< SF_LEN; i++)	{	  Conv[i] = 0.0;	}	for(i=0; i< ExcVecLen; i++)	{	  if (rint((double)(ExcVec[i])) != 0.0)	{	    for(j=0; j<min(SF_LEN - i, LenTruncH); j++)	{	      Conv[i+j] += ExcVec[i] * LPImpResp[j];	    }	  }	}}/**************************************************************************** ROUTINE*		EndCorrectStoch** FUNCTION*		End correct the convolution sum** SYNOPSIS*               EndCorrectStoch(ExcVal, LPImpResp, LenTruncH, Conv)**   formal **                       data    I/O*       name            type    type    function*       -------------------------------------------------------------------*	ExcVal		float	 i	Excitation value*	LPImpResp	float	 i	LPC impulse response*	LenTruncH	int	 i	Length to truncate impulse response*	Conv		float	 o	Convolution sum******************************************************************************	   End correct the convolution sum on subsequent code words:*	   (Do two end corrections for a shift by 2 code book)**	   y     =  0*	    0, 0*	   y     =  y        + ex * h   where i = 1, ..., L points*	    i, m     i-1, m-1   -m   i  and   m = 1, ..., cbsize-1 code words**	   NOTE:  The data movements in loops "do 59 ..." and "do 69 ..."*	          are performed many times and can be quite time consuming.*	          Therefore, special precautions should be taken when*	          implementing this.  Some implementation suggestions:*	          1.  Circular buffers with pointers to eliminate data moves.*	          2.  Fast "block move" operation as offered on some DSPs.*****************************************************************************/void EndCorrectStoch(float	ExcVal,float	LPImpResp[],int	LenTruncH,float	Conv[]){int 	i;	if(rint((double)(ExcVal)) != 0.0)	{	/*  Ternary stochastic code book (-1, 0, +1) */	  if(rint((double)(ExcVal)) == 1.0)	{	    for(i=LenTruncH-1; i>0; i--)	{	      Conv[i-1] += LPImpResp[i];	    }	  }	  else	{	    for(i=LenTruncH-1; i>0; i--)	{	      Conv[i-1] -= LPImpResp[i];	    }	  }	}	for(i=SF_LEN-1; i>0; i--)	{	  Conv[i] = Conv[i-1];	}	Conv[0] = ExcVal*LPImpResp[0];}/**************************************************************************** ROUTINE*		CalcCorEngStoch** FUNCTION*		Calculate correlation and energy** SYNOPSIS*               CalcCorEngStoch(Residual, Conv, ExcVal1, ExcVal2, First, Cor, Energy)**   formal **                       data    I/O*       name            type    type    function*       -------------------------------------------------------------------*	Residual	float	 i	Spectrum and adaptive residual*	Conv		float	 i	Convolution sum*	ExcVal1		float	 i	First excitation vector value*	ExcVal2		float	 i	Second excitation vector value*	First		int	 i	First subframe flag*	Cor		float	 o	Correlation*	Energy		float	 o	Energy******************************************************************************	Calculate correlation and energy:*	e0 = spectrum & pitch prediction residual*	y  = error weighting filtered code words**	\/\/\/  CELP's computations are focused in this correlation \/\/\/*		- For a 512 code book this correlation takes 4 MIPS!*		- Decimation?, Down-sample & decimate?, FEC codes?****************************************************************************/void CalcCorEngStoch(float	Residual[RES_LEN],float	Conv[],float	ExcVal1,float	ExcVal2,int	First,float	*Cor,float 	*Energy){int i;static float NextLastConv=0.0;static float LastConv=0.0;/*  Initialize */	*Cor = 0.0;/*  Calculate correlation */	for(i=0; i<SF_LEN; i++)	{	  *Cor += Conv[i]*Residual[i];	}/*  End correct energy on subsequent code words */	if ((rint((double)(ExcVal1)) == 0.0) && (rint((double)(ExcVal2)) == 0.0) && (!First))	{	  *Energy -= NextLastConv*NextLastConv + LastConv*LastConv;	}	else	{	  *Energy = 0.0;	  for(i=0; i<SF_LEN; i++)	{	    *Energy += Conv[i] * Conv[i];	  }	}	NextLastConv = Conv[SF_LEN-2];	LastConv = Conv[SF_LEN-1];}/**************************************************************************** ROUTINE*		CompGainErrStoch** FUNCTION*		Compute gain and error** SYNOPSIS*               CompGainErrStoch(Energy, Cor, Gain, Error)**   formal **                       data    I/O*       name            type    type    function*       -------------------------------------------------------------------*	Energy		float	 i	Energy*	Cor		float	 i	Correlation*	Gain		float	 o	Codebook Gain*	Error		float	 o	Codebook Error******************************************************************************	Compute gain and error:*	  NOTE: Actual MSPE = e0.e0 - gain(2*cor-gain*eng)*		since e0.e0 is independent of the code word,*		minimizing MSPE is equivalent to maximizing:*		     match = gain(2*cor-gain*eng)*		If unquantized gain is used, this simplifies:*		     match = cor*gain**	Independent (open-loop) quantization of gain and match (index):****************************************************************************/void CompGainErrStoch(float	Energy,float	Cor,float	*Gain,float	*Error){	if(Energy <= 0.0)	  *Gain = Cor;	else	  *Gain = Cor/Energy;	*Error = Cor * *Gain;}

⌨️ 快捷键说明

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