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

📄 melp_ana.c

📁 MELPe 1200 bps, fixed point
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*               3.25976428 z^{-3} + 1.51727884 z^{-4} -                  */
	/*               0.39111723 z^{-5} + 0.04335699 z^{-6}.                   */
	/*                                                                        */
	/* It can be shown that the following fixed point filter used by RATE     */
	/* 2400 is the same as the one mentione above (except for some numerical  */
	/* truncation errors) under Q13.  Therefore the floating point version of */
	/* the filter is completely replaced with the RATE2400 filter.            */

	v_equ(&sigbuf[LPF_ORD], &speech[PITCH_BEG], PITCH_FR);
	for (section = 0; section < LPF_ORD/2; section++){
		for (i = (Shortword) (section*2); i < (Shortword) (section*2 + 2);
			 i++){
			temp_delin[i] = sigbuf[LPF_ORD + FRAME - 1 - i + section*2];
		}
		iir_2nd_s(&sigbuf[LPF_ORD], &lpf_den[section*3], &lpf_num[section*3],
				  &sigbuf[LPF_ORD], &lpfsp_delin[section*2],
				  &lpfsp_delout[section*2], FRAME);
		v_equ(&(temp_delout[2*section]), &(lpfsp_delout[2*section]), 2);
		iir_2nd_s(&sigbuf[LPF_ORD + FRAME], &lpf_den[section*3],
				  &lpf_num[section*3], &sigbuf[LPF_ORD + FRAME],
				  &lpfsp_delin[section*2], &lpfsp_delout[section*2],
				  PITCH_FR - FRAME);
		/* restore delay buffers for the next overlapping frame */
		v_equ(&(lpfsp_delin[2*section]), &(temp_delin[2*section]), 2);
		v_equ(&(lpfsp_delout[2*section]), &(temp_delout[2*section]), 2);
	}

	f_pitch_scale(&sigbuf[LPF_ORD], &sigbuf[LPF_ORD], PITCH_FR);

	/* Perform global pitch search at frame end on lowpass speech signal */
    /* Note: avoid short pitches due to formant tracking */
	fpitch[1] = find_pitch(&sigbuf[LPF_ORD + (PITCH_FR/2)], &dontcare,
						   (2*PITCHMIN), PITCHMAX, PITCHMAX);
	fpitch[1] = shl(fpitch[1], 7);                            /* fpitch in Q7 */

	/* Perform bandpass voicing analysis for end of frame */
	bpvc_ana(&speech[FRAME_END], fpitch, par->bpvc, &sub_pitch);

	/* Force jitter if lowest band voicing strength is weak */
	if (par->bpvc[0] < VJIT_Q14)                          /* par->bpvc in Q14 */
		par->jitter = MAX_JITTER_Q15;                   /* par->jitter in Q15 */
	else
		par->jitter = 0;

	/* Calculate LPC for end of frame.  Note that we compute (LPC_ORD + 1)    */
	/* entries of auto_corr[] for RATE2400 but EN_FILTER_ORDER entries for    */
	/* RATE1200 because bandEn() for classify() of "classify.c" needs so many */
	/* entries for computation.  lpc_schur() needs (LPC_ORD + 1) entries.     */

	if (rate == RATE2400)
		lpc_autocorr(&speech[(FRAME_END - (LPC_FRAME/2))], win_cof, auto_corr,
					 HF_CORR_Q15, LPC_ORD, LPC_FRAME);
	else
		lpc_autocorr(&speech[(FRAME_END - (LPC_FRAME/2))], win_cof, auto_corr,
					 HF_CORR_Q15, EN_FILTER_ORDER - 1, LPC_FRAME);

	lpc[0] = ONE_Q12;
	lpc_schur(auto_corr, &(lpc[1]), LPC_ORD);                   /* lpc in Q12 */

	if (rate == RATE2400){             /* Calculate Line Spectral Frequencies */
		lpc_pred2lsp(&(lpc[1]), par->lsf, LPC_ORD);
		v_equ(top_lpc, &(lpc[1]), LPC_ORD);
	} else {
		lpc_bw_expand(&(lpc[1]), &(lpc[1]), BWFACT_Q15, LPC_ORD);

		/* Calculate Line Spectral Frequencies */
		lpc_pred2lsp(&(lpc[1]), par->lsf, LPC_ORD);

		/* Force minimum LSF bandwidth (separation) */
		lpc_clamp(par->lsf, BWMIN_Q15, LPC_ORD);
	}


	/* Calculate LPC residual */
	zerflt(&speech[PITCH_BEG], lpc, &sigbuf[LPF_ORD], LPC_ORD, PITCH_FR);

	/* Check peakiness of residual signal */
	begin = LPF_ORD + (PITCHMAX/2);
	temp = peakiness(&sigbuf[begin], PITCHMAX);                /* temp in Q12 */

	
	/* Peakiness: force lowest band to be voiced  */
	if (temp > PEAK_THRESH_Q12)
		par->bpvc[0] = ONE_Q14;

	/* Extreme peakiness: force second and third bands to be voiced */
	if (temp > PEAK_THR2_Q12){
		par->bpvc[1] = ONE_Q14;
		par->bpvc[2] = ONE_Q14;
	}

	if (rate == RATE1200){
		/* ======== Compute pre-classification and pitch parameters ========  */
		cur_track = (Shortword) (CUR_TRACK + subnum * PIT_SUBNUM);
		for (i = 0; i < PIT_SUBNUM; i++){
			pitchAuto(&speech[FRAME_END + i*PIT_SUBFRAME + PIT_COR_LEN/2],
					  &pitTrack[cur_track + i + 1],
					  &classStat[cur_track + i + 1]);

			classify(&speech[FRAME_END + i * PIT_SUBFRAME + PIT_SUBFRAME/2],
					 &classStat[cur_track + i + 1], auto_corr);
		}
	}

	/* Calculate overall frame pitch using lowpass filtered residual */
	par->pitch = pitch_ana(&speech[FRAME_END], &sigbuf[LPF_ORD + PITCHMAX],
						   sub_pitch, pitch_avg, &pcorr);

	/* Calculate gain of input speech for each gain subframe */
	for (i = 0; i < NUM_GAINFR; i++){
		if (par->bpvc[0] > BPTHRESH_Q14){
			/* voiced mode: pitch synchronous window length */
			temp = sub_pitch;
			par->gain[i] = gain_ana(&speech[FRAME_BEG + (i + 1)*GAINFR],
									temp, MIN_GAINFR, PITCHMAX_X2);
		} else {
			if (rate == RATE2400)
				temp = (Shortword) GAIN_PITCH_Q7;
			else
				temp = (Shortword) 15258;
                                                  /* (1.33*GAINFR - 0.5) << 7 */
			par->gain[i] = gain_ana(&speech[FRAME_BEG + (i + 1)*GAINFR],
									temp, 0, PITCHMAX_X2);
		}
	}

	/* Update average pitch value */
	if (par->gain[NUM_GAINFR - 1] > SILENCE_DB_Q8)         /* par->gain in Q8 */
		temp = pcorr;
	else
		temp = 0;
	/* pcorr in Q14 */
	pitch_avg = p_avg_update(par->pitch, temp, VMIN_Q14);

	if (rate == RATE1200){
		if (par->bpvc[0] > BPTHRESH_Q14)
			par->uv_flag = FALSE;
		else
			par->uv_flag = TRUE;
	}

	/* Update delay buffers for next frame */
	fpitch[0] = fpitch[1];
}



/* ======================================= */
/* melp_ana_init(): perform initialization */
/* ======================================= */

void melp_ana_init()
{
	register Shortword	i;


	v_zap(hpspeech, IN_BEG + BLOCK);   /* speech[] is declared IN_BEG + BLOCK */

	/* Initialize fixed MSE weighting and inverse of weighting */

	if (!w_fs_init){
		vq_fsw(w_fs, NUM_HARM, X60_Q9);
		for (i = 0; i < NUM_HARM; i++)
			w_fs_inv[i] = divide_s(ONE_Q13, w_fs[i]);      /* w_fs_inv in Q14 */
		w_fs_init = TRUE;
	}

	/* Initialize wr_array and wi_array */
	fs_init();

	/* Initialization of the pitch, classification and voicing paramters.  It */
	/* is believed that the following for loop is not necessary.              */

	for (i = 0; i < TRACK_NUM; i++){
		fill(pitTrack[i].pit, FIFTY_Q0, NODE); /* !!! (12/10/99) */
		fill(pitTrack[i].weight, ONE_Q15, NODE);

		classStat[i].classy = UNVOICED;
		classStat[i].subEnergy = X28_Q11;
		classStat[i].zeroCrosRate = X05_Q15;
		classStat[i].peakiness = ONE_Q11;
		classStat[i].corx = X02_Q15;
	}
}


/****************************************************************************
**
** Function:		sc_ana
**
** Description: 	The analysis routine for block (1200bps only)
**
** Arguments:
**
**	melp_param	*par	---- output encoded melp parameters
**
** Return value:	None
**
*****************************************************************************/

void		sc_ana(struct melp_param *par)
{
	register Shortword	i;
	static Shortword	prev_sbp3;
	static BOOLEAN		prev_uv = UNVOICED;
	static Shortword	prev_pitch = FIFTY_Q7;  /* Note that prev_pitch is Q7 */
                                  /* but it is always an integer in Q7 as the */
                                  /* former floating point version specifies. */
	Shortword	pitCand, npitch;                                        /* Q7 */
	Shortword	bpvc_copy[NUM_BANDS];
	Shortword	sbp[NF + 1];
	BOOLEAN		uv[NF + 1];
	Shortword	curTrack;
	Shortword	index, index1, index2;
	Shortword	temp1, temp2;
	Shortword	w1_w2;                                                 /* Q15 */


	/* ======== Update silence energy ======== */
	for (i = 0; i < NF; i++){

		curTrack = (Shortword) (i * PIT_SUBNUM + CUR_TRACK);

		/* ---- update silence energy ---- */
		if ((classStat[curTrack].classy == SILENCE) &&
			(classStat[curTrack - 1].classy == SILENCE)){
			/*	silenceEn = log10(EN_UP_RATE * pow(10.0, silenceEn) +
								  (1.0 - EN_UP_RATE) * 
								  pow(10.0, classStat[curTrack].subEnergy)); */
			silenceEn = updateEn(silenceEn, EN_UP_RATE_Q15,
								 classStat[curTrack].subEnergy);
		}
	}

	uv[0] = prev_uv;
	uv[1] = par[0].uv_flag;
	uv[2] = par[1].uv_flag;
	uv[3] = par[2].uv_flag;

	curTrack = CUR_TRACK;
	if (!uv[1])
		voicedCnt++;
	else
		voicedCnt = 0;

	if (!uv[1] && !uv[2] && !uv[3] && !subenergyRelation1(classStat, curTrack)){
		/* ---- process only voiced frames ---- */
		/* check if it is offset first */
		if ((voicedCnt < 2) || subenergyRelation2(classStat, curTrack)){

			/* Got onset position, should look forward for pitch */
			pitCand = pitLookahead(&pitTrack[curTrack], 3);
			if (ratio(par[0].pitch, pitCand) > X015_Q15){
				if (ratio(pitCand, par[1].pitch) < X015_Q15)
					par[0].pitch = pitCand;
				else if ((ratio(par[1].pitch, par[2].pitch) < X015_Q15) &&
						 (ratio(par[0].pitch, par[1].pitch) > X015_Q15))
					par[0].pitch = par[1].pitch;
				else if (ratio(par[0].pitch, par[1].pitch) > X015_Q15)
					par[0].pitch = pitCand;
			}
		} else if (!uv[0]){
			/* not onset not offset, just check pitch smooth */
			temp1 = sub(par[0].pitch, prev_pitch);
			index1 = shr(temp1, 7);                                     /* Q0 */
			temp2 = sub(par[1].pitch, par[0].pitch);
			index2 = shr(temp2, 7);                                     /* Q0 */
			if ((abs_s(index1) > 5) && (abs_s(index2) > 5) &&
				(index1 * index2 < 0)){
				/* here is a pitch jump */
				pitCand = pitLookahead(&pitTrack[curTrack], 3);
				if ((ratio(prev_pitch, pitCand) < X015_Q15) ||
					(ratio(pitCand, par[1].pitch) < X02_Q15))
					par[0].pitch = pitCand;
				else {
					/*	par[0].pitch = (prev_pitch + par[1].pitch)/2; */
					temp1 = shr(prev_pitch, 1);
					temp2 = shr(par[1].pitch, 1);
					par[0].pitch = add(temp1, temp2);                   /* Q7 */
				}
			} else if ((ratio(par[0].pitch, prev_pitch) > X015_Q15) &&
					   ((ratio(par[1].pitch, prev_pitch) < X015_Q15) ||
						(ratio(par[2].pitch, prev_pitch) < X015_Q15))){
				index1 = trackPitch(prev_pitch, &pitTrack[curTrack]);
				pitCand = shl(pitTrack[curTrack].pit[index1], 7); /* !!! (12/10/99) */
				index2 = trackPitch(par[0].pitch, &pitTrack[curTrack]);
				w1_w2 = sub(pitTrack[curTrack].weight[index1],
							pitTrack[curTrack].weight[index2]);

				if (multiCheck(par[0].pitch, pitCand) < X008_Q15){
					if (((par[0].pitch > pitCand) && (w1_w2 > MX02_Q15)) ||
						(w1_w2 > X02_Q15))
						par[0].pitch = pitCand;
				} else if (w1_w2 > MX01_Q15){
					par[0].pitch = pitCand;
				}
			} else if ((L_ratio(par[0].pitch, (Longword) (prev_pitch*2)) <
						X008_Q15) ||
					   (L_ratio(par[0].pitch, (Longword) (prev_pitch*3)) <
						X008_Q15)){
				/* possible it is a double pitch */
				pitCand = pitLookahead(&pitTrack[curTrack], 4);
				if (ratio(pitCand, prev_pitch) < X01_Q15)
					par[0].pitch = pitCand;
			}
		}
	}

	/* ======== The second frame ======== */
	prev_pitch = shl(shr(par[0].pitch, 7), 7);     /* Rounding to Q7 integer. */
	curTrack = CUR_TRACK + 2;
	if (!uv[2])
		voicedCnt++;
	else
		voicedCnt = 0;

⌨️ 快捷键说明

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