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

📄 dsp_sub.c

📁 MELPe 1200 bps, fixed point
💻 C
📖 第 1 页 / 共 2 页
字号:

	/*----------------------------------------------------------------------*/
	/* COMPUTE THE PRODUCT (A * next) USING CROSS MULTIPLICATION OF         */
	/* 16-BIT HALVES OF THE INPUT VALUES.	THE RESULT IS REPRESENTED AS 2  */
	/* 31-BIT VALUES.	SINCE 'A' FITS IN 15 BITS, ITS UPPER HALF CAN BE    */
	/* DISREGARDED.  USING THE NOTATION val[m::n] TO MEAN "BITS n THROUGH   */
	/* m OF val", THE PRODUCT IS COMPUTED AS:                               */
	/*   q = (A * x)[0::30]  = ((A * x1)[0::14] << 16) + (A * x0)[0::30]    */
	/*   p = (A * x)[31::60] =  (A * x1)[15::30]		+ (A * x0)[31]	+ C */
	/* WHERE C = q[31] (CARRY BIT FROM q).  NOTE THAT BECAUSE A < 2^15,     */
	/* (A * x0)[31] IS ALWAYS 0.                                            */
	/*----------------------------------------------------------------------*/
	/* save and reset saturation count                                      */

	old_saturation = saturation;
	saturation = 0;

	/* q = ((A * x1) << 17 >> 1) + (A * x0); */
	/* p = ((A * x1) >> 15) + (q >> 31); */
	/* q = q << 1 >> 1; */                                     /* CLEAR CARRY */
	L_temp1 = L_mpyu(A, x1);
	/* store bit 15 to bit 31 in p */
	p = L_shr(L_temp1, 15);
	/* mask bit 15 to bit 31 */
	L_temp1 = L_shl((L_temp1 & (Longword) 0x00007fff), 16);
	L_temp2 = L_mpyu(A, x0);
	L_temp3 = L_sub(LW_MAX, L_temp1);
	if (L_temp2 > L_temp3){
		/* subtract 0x80000000 from sum */
		L_temp1 = L_sub(L_temp1, (Longword) 0x7fffffff);
		L_temp1 = L_sub(L_temp1, 1);
		q = L_add(L_temp1, L_temp2);
		p = L_add(p, 1);
	} else
		q = L_add(L_temp1, L_temp2);

	/*---------------------------------------------------------------------*/
	/* IF (p + q) < 2^31, RESULT IS (p + q).  OTHERWISE, RESULT IS         */
	/* (p + q) - 2^31 + 1.  (SEE REFERENCES).                              */
	/*---------------------------------------------------------------------*/
	/* p += q; next = ((p + (p >> 31)) << 1) >> 1; */
	/* ADD CARRY, THEN CLEAR IT */

	L_temp3 = L_sub(LW_MAX, p);
	if (q > L_temp3){
		/* subtract 0x7fffffff from sum */
		L_temp1 = L_sub(p, (Longword) 0x7fffffff);
		L_temp1 = L_add(L_temp1, q);
	} else
		L_temp1 = L_add(p, q);
	next = L_temp1;

	/* restore saturation count */
	saturation = old_saturation;

	x1 = extract_h(next);
	return (x1);
}


/***************************************************************************
 *
 *	 FUNCTION NAME: L_mpyu
 *
 *	 PURPOSE:
 *
 *	   Perform an unsigned fractional multipy of the two unsigned 16 bit
 *	   input numbers with saturation.  Output a 32 bit unsigned number.
 *
 *	 INPUTS:
 *
 *	   var1
 *					   16 bit short unsigned integer (Shortword) whose value
 *					   falls in the range 0xffff 0000 <= var1 <= 0x0000 ffff.
 *	   var2
 *					   16 bit short unsigned integer (Shortword) whose value
 *					   falls in the range 0xffff 0000 <= var2 <= 0x0000 ffff.
 *
 *	 OUTPUTS:
 *
 *	   none
 *
 *	 RETURN VALUE:
 *
 *	   L_Out
 *					   32 bit long unsigned integer (Longword) whose value
 *					   falls in the range
 *					   0x0000 0000 <= L_var1 <= 0xffff ffff.
 *
 *	 IMPLEMENTATION:
 *
 *	   Multiply the two unsigned 16 bit input numbers.
 *
 *	 KEYWORDS: multiply, mult, mpy
 *
 *************************************************************************/

static ULongword	L_mpyu(UShortword var1, UShortword var2)
{
	ULongword	L_product;


	L_product = (ULongword) var1 *var2;                   /* integer multiply */
	return (L_product);
}


/* ========================================================================== */
/* This function reads a block of input data.  It returns the actual number   */
/*    of samples read.  Zeros are filled into input[] if there are not suffi- */
/*    cient data samples.                                                     */
/* ========================================================================== */
Shortword readbl(Shortword input[], FILE *fp_in, Shortword size)
{
	Shortword	length;


	length = (Shortword) fread(input, sizeof(Shortword), size, fp_in);
	v_zap(&(input[length]), (Shortword) (size - length));

	return(length);
}


/* ========================================================================== */
/* This function unpacks bits of "code" from channel.  It returns 1 if an     */
/*    erasure is encountered, or 0 otherwise.  "numbits" bits of "code" */
/*    is used and they are packed into the array pointed by "ptr_ch_begin".   */
/*    "ptr_ch_bit" points to the position of the next bit being copied onto.  */
/* ========================================================================== */
BOOLEAN	unpack_code(unsigned char **ptr_ch_begin, Shortword *ptr_ch_bit,
					Shortword *code, Shortword numbits, Shortword wsize,
					UShortword erase_mask)
{
	register Shortword	i;
	unsigned char	*ch_word;
	Shortword	ret_code;
	Shortword	ch_bit;


	ch_bit = *ptr_ch_bit;
	ch_word = *ptr_ch_begin;
	*code = 0;
	ret_code = (Shortword) (*ch_word & erase_mask); 

	for (i = 0; i < numbits; i++){
		/* Mask in bit from channel word to code */
		*code |= shl(shr((Shortword) ((Shortword) *ch_word & shl(1, ch_bit)), ch_bit), i);

		/* Check for end of channel word */
		ch_bit = add(ch_bit, 1);
		if (ch_bit >= wsize){
			ch_bit = 0;
			(*ptr_ch_begin) ++;
			ch_word++ ;
		}
	}

	/* Save updated bit counter */
	*ptr_ch_bit = ch_bit;

	/* Catch erasure in new word if read */
	if (ch_bit != 0)
		ret_code |= *ch_word & erase_mask;

	return(ret_code);
}


/* ============================================ */
/* Subroutine window: multiply signal by window */
/*                                              */
/* Q values:                                    */
/*    input - Q0, win_coeff - Q15, output - Q0  */
/* ============================================ */

void window(Shortword input[], const Shortword win_coeff[], Shortword output[],
			Shortword npts)
{
	register Shortword	i;

	for (i = 0; i < npts; i++){
		output[i] = mult(win_coeff[i], input[i]);
	}
}


/* ============================================== */
/* Subroutine window_Q: multiply signal by window */
/*                                                */
/* Q values:                                      */
/*    win_coeff - Qin, output = input             */
/* ============================================== */

void window_Q(Shortword input[], Shortword win_coeff[], Shortword output[],
			  Shortword npts, Shortword Qin)
{
	register Shortword	i;
	Shortword	shift;

	/* After computing "shift", win_coeff[]*2^(-shift) is considered Q15.     */
	shift = sub(15, Qin);
	for (i = 0; i < npts; i++){
		output[i] = extract_h(L_shl(L_mult(win_coeff[i], input[i]), shift));
	}
}


/* ============================================ */
/* This function writes a block of output data. */
/* ============================================ */
void writebl(Shortword output[], FILE *fp_out, Shortword size)
{
	fwrite(output, sizeof(Shortword), size, fp_out);
}


/* Subroutine polflt(): all pole (IIR) filter.                                */
/*   Note: The filter coefficients (Q13) represent the denominator only, and  */
/*         the leading coefficient is assumed to be 1.  The output array can  */
/*         overlay the input.                                                 */
/* Q value:                                                                   */
/*   input[], output[]: Q0, coeff[]: Q12                                      */

void polflt(Shortword input[], Shortword coeff[], Shortword output[],
			Shortword order, Shortword npts)
{
	register Shortword	i, j;
	Longword	accum;                                                 /* Q12 */


	for (i = 0; i < npts; i++ ){
		accum = L_shl(L_deposit_l(input[i]), 12);
		for (j = 1; j <= order; j++)
			accum = L_msu(accum, output[i - j], coeff[j]);
		/* Round off output */
		accum = L_shl(accum, 3);
		output[i] = round(accum);
	}
}


/* Subroutine zerflt(): all zero (FIR) filter.                                */
/*   Note: the output array can overlay the input.                            */
/*                                                                            */
/* Q values:                                                                  */
/*   input[], output[] - Q0, coeff[] - Q12                                    */

void zerflt(Shortword input[], const Shortword coeff[], Shortword output[],
			Shortword order, Shortword npts)
{
	register Shortword	i, j;
	Longword	accum;


	for (i = sub(npts, 1); i >= 0; i--){ 
		accum = 0;
		for (j = 0; j <= order; j++)
			accum = L_mac(accum, input[i - j], coeff[j]);
		/* Round off output */
		accum = L_shl(accum, 3);
		output[i] = round(accum);
	}
}


/* Subroutine zerflt_Q: all zero (FIR) filter.                                */
/* Note: the output array can overlay the input.                              */
/*                                                                            */
/* Q values:                                                                  */
/* coeff - specified by Q_coeff, output - same as input                       */

void zerflt_Q(Shortword input[], const Shortword coeff[], Shortword output[],
			  Shortword order, Shortword npts, Shortword Q_coeff)
{
	register Shortword	i, j;
	Shortword	scale;
	Longword	accum;


	scale = sub(15, Q_coeff);
	for (i = sub(npts, 1); i >= 0; i--){
		accum = 0;
		for (j = 0; j <= order; j++)
			accum = L_mac(accum, input[i - j], coeff[j]);
		/* Round off output */
		accum = L_shl(accum, scale);
		output[i] = round(accum);
	}
}


/* ========================================================================== */
/* Subroutine iir_2nd_d: Second order IIR filter (Double precision)           */
/*    Note: the output array can overlay the input.                           */
/*                                                                            */
/* Input scaled down by a factor of 2 to prevent overflow                     */
/* ========================================================================== */
void iir_2nd_d(Shortword input[], const Shortword den[], const Shortword num[],
			   Shortword output[], Shortword delin[], Shortword delout_hi[],
			   Shortword delout_lo[], Shortword npts)
{
	register Shortword	i;
	Shortword	temp;
	Longword	accum;


	for (i = 0; i < npts; i++){
		accum = L_mult(delout_lo[0], den[1]);
		accum = L_mac(accum, delout_lo[1], den[2]);
		accum = L_shr(accum, 14);
		accum = L_mac(accum, delout_hi[0], den[1]);
		accum = L_mac(accum, delout_hi[1], den[2]);

		accum = L_mac(accum, shr(input[i], 1), num[0]);
		accum = L_mac(accum, delin[0], num[1]);
		accum = L_mac(accum, delin[1], num[2]);

		/* shift result to correct Q value */
		accum = L_shl(accum, 2);                /* assume coefficients in Q13 */

		/* update input delay buffer */
		delin[1] = delin[0];
		delin[0] = shr(input[i], 1);

		/* update output delay buffer */
		delout_hi[1] = delout_hi[0];
		delout_lo[1] = delout_lo[0];
		delout_hi[0] = extract_h(accum);
		temp = shr(extract_l(accum), 2);
		delout_lo[0] = (Shortword) (temp & (Shortword)0x3FFF);

		/* round off result */
		accum = L_shl(accum, 1);
		output[i] = round(accum);
	}
}


/* ========================================================================== */
/* Subroutine iir_2nd_s: Second order IIR filter (Single precision)           */
/*    Note: the output array can overlay the input.                           */
/*                                                                            */
/* Input scaled down by a factor of 2 to prevent overflow                     */
/* ========================================================================== */
void iir_2nd_s(Shortword input[], const Shortword den[], const Shortword num[],
			   Shortword output[], Shortword delin[], Shortword delout[],
			   Shortword npts)
{
	register Shortword	i;
	Longword	accum;


	for (i = 0; i < npts; i++){
		accum = L_mult(input[i], num[0]);
		accum = L_mac(accum, delin[0], num[1]);
		accum = L_mac(accum, delin[1], num[2]);

		accum = L_mac(accum, delout[0], den[1]);
		accum = L_mac(accum, delout[1], den[2]);

		/* shift result to correct Q value */
		accum = L_shl(accum, 2);                /* assume coefficients in Q13 */

		/* update input delay buffer */
		delin[1] = delin[0];
		delin[0] = input[i];

		/* round off result */
		output[i] = round(accum);

		/* update output delay buffer */
		delout[1] = delout[0];
		delout[0] = output[i];
	}
}


/* ========================================================================== */
/* This function interpolates two scalars to obtain the output.  It calls     */
/* interp_array() to do the job.  "ifact" is Q15, and "prev", "curr" and the  */
/* returned value are of the same Q value.                                    */
/* ========================================================================== */

Shortword interp_scalar(Shortword prev, Shortword curr, Shortword ifact)
{
	Shortword	out;


	interp_array(&prev, &curr, &out, ifact, 1);
	return(out);
}

⌨️ 快捷键说明

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