📄 melp_ana.c
字号:
/* 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 + -