📄 pitch.c
字号:
}
classStat->corx = corx[0];
j = 0;
for (i = MINPITCH; i <= MAXPITCH; i++){
if (index[i] != 0){
pitTrack->pit[j] = i;
pitTrack->weight[j] = corx[index[i] - 1];
j ++;
}
}
for(; j < NODE; j++){
pitTrack->pit[j] = 100;
/* The floating point version set pitTrack->weight[j] to -100.0 */
/* here we use 0 */
pitTrack->weight[j] = 0;
}
/* ---- Modify time domain correlation by muliple checking ---- */
for (i = 0; i < NODE - 1; i++){
for (j = (Shortword) (i + 1); j < NODE; j++){
temp1 = pitTrack->pit[j];
temp2 = pitTrack->pit[i];
temp = temp2;
while (temp < temp1){
temp = add(temp, temp2);
}
temp2 = shr(temp2, 1);
temp2 = sub(temp, temp2);
if (temp2 >= temp1)
temp = sub(temp, pitTrack->pit[i]);
/* Now temp is the multiples of pitTrack->pit[i] which is the */
/* closest to pitTrack->pit[j]. */
/* rk_f = abs(pitTrack->pit[j] -
temp*pitTrack->pit[i])/pitTrack->pit[j]; */
temp = sub(pitTrack->pit[j], temp);
temp = abs_s(temp);
temp2 = divide_s(temp, pitTrack->pit[j]); /* Q15 */
if (temp2 < X008_Q15){
/* pitTrack->weight[j] -= pitTrack->weight[i]/5.0; */
temp1 = pitTrack->weight[i];
temp1 = mult(temp1, X02_Q15);
temp2 = pitTrack->weight[j];
temp2 = sub(temp2, temp1);
if( temp2 < 0 ) temp2 = 0;
pitTrack->weight[j] = temp2;
}
}
}
}
/******************************************************************
**
** Function: multiCheck
**
** Description: multiple or sub-multiple pitch check
**
** Input:
** Shortword f1 ------ the pitch candidate 1 (Q7)
** Shortword f2 ------ the pitch candidate 2 (Q7)
**
** Return: Shortword ----- ratio of f1, f2 with multiple (Q15)
**
********************************************************************/
Shortword multiCheck(Shortword f1, Shortword f2)
{
Shortword temp, f2_multiple; /* Q7 */
if (f1 <= f2){ /* Swap f1 and f2 so that f1 is larger than f2. */
temp = f1;
f1 = f2;
f2 = temp;
}
f2_multiple = f2;
while (f2_multiple <= f1)
f2_multiple = add(f2_multiple, f2);
/* Now f2_multiple is larger than f1. Check whether f2_multiple or */
/* (f2_multiple - f2) is closer to f1 and use the better one. */
temp = shr(f2, 1);
temp = sub(f2_multiple, temp); /* Q7 */
if (temp > f1)
f2_multiple = sub(f2_multiple, f2);
return(ratio(f1, f2_multiple));
}
/******************************************************************
**
** Function: minCostIndex
**
** Description: find first two largest local maxs
**
** Input:
** Shortword *costBuf ------ the cost buffer Q5
** Shortword *index1 ------ the index of the largest peak
** Shortword *index2 ------ the index of the second largest peak
**
** Return: None
**
********************************************************************/
void minCostIndex(Shortword *costBuf, Shortword *index1, Shortword *index2)
{
register Shortword i;
Shortword co = SW_MAX;
*index1 = 0; /* largest weight */
co = costBuf[0];
for (i = 1; i < NODE; i++){
if (costBuf[i] < co){
co = costBuf[i];
*index1 = i;
}
}
if (*index1 == 0)
*index2 = 1; /* second largest weight */
else
*index2 = 0;
co = costBuf[*index2];
for (i = (Shortword) (*index2 + 1); i < NODE; i++){
if (*index1 == i)
continue;
if (costBuf[i] < co){
co = costBuf[i];
*index2 = i;
}
}
}
/******************************************************************
**
** Function: trackPitch
**
** Description: Find coresponding pitch index for pitch tracking
**
** Input:
** Shortword pitch ------ the pitch candidate (Q7)
** pitTrackParam *pitTrack ------ The pitch tracker structure
**
** Return: Shortword ----- index of the time domain candidates
**
********************************************************************/
Shortword trackPitch(Shortword pitch, pitTrackParam *pitTrack)
{
register Shortword i;
Shortword index;
Shortword best, temp; /* Q7 */
Shortword co = MONE_Q15; /* Minus infinity. */
/* The following loop finds the index for pitTrack->pit[] so that it */
/* maximizes pitTrack->weight[] among those indices with */
/* ratio(pitTrack->pit[*], pitch) < 0.2 as a qualification. If index */
/* remains -1, it means none of pitTrack->pit[] qualifies. */
index = -1;
for (i = 0; i < NODE; i++){
temp = shl(pitTrack->pit[i], 7); /* Q7 */
if (ratio(temp, pitch) < X02_Q15){
if (pitTrack->weight[i] > co){
co = pitTrack->weight[i];
index = i;
}
}
}
if (index < 0){ /* All of pitTrack->pit[] makes ratio(*, pitch) > 0.2; */
/* none of pitTrack->pit[] is close enough to "pitch". */
/* Then we find the "index" which is the closest to "pitch". */
index = 0;
temp = shl(pitTrack->pit[index], 7);
temp = sub(temp, pitch);
best = abs_s(temp); /* Q7 */
for (i = 1; i < NODE; i++){
temp = shl(pitTrack->pit[i], 7);
temp = sub(temp, pitch);
temp = abs_s(temp); /* Q7 */
if (temp < best){
index = i;
best = temp;
}
}
}
return(index);
}
/******************************************************************
**
** Function: pitLookahead
**
** Description: Find pitch at onset segment
**
** Input:
** pitTrackParam *pitTrack ------ The pitch tracker structure
** Shortword num ------ The number of available structures
**
** Return: Shortword ----- the smoothed pitch (Q7)
**
********************************************************************/
Shortword pitLookahead(pitTrackParam *pitTrack, Shortword num)
{
register Shortword i, j;
Shortword index;
Longword L_sum, L_cost;
/* compute the cost function of the last strucutre */
for(i = 0; i < NODE; i++){
L_sum = L_sub(LW_MAX, L_deposit_h(pitTrack[num].weight[i]));
L_cost = L_mult(extract_h(L_sum), PIT_WEIGHT_Q5);
pitTrack[num].cost[i] = extract_h(L_cost); /* Q5 */
}
/* -------- forward tracker -------- */
for(i = sub(num, 1); i >= 0; i--){
for(j = 0; j < NODE; j++){
index = trackPitch(shl(pitTrack[i].pit[j], 7), &pitTrack[i + 1]);
/* pitTrack[i].cost[j] = PIT_WEIGHT*(1.0-pitTrack[i].weight[j]); */
L_sum = L_sub(LW_MAX, L_deposit_h(pitTrack[i].weight[j]));
L_cost = L_mult(extract_h(L_sum), PIT_WEIGHT_Q5); /* Q5 */
/* pitTrack[i].cost[j] +=
abs(pitTrack[i].pit[j] - pitTrack[i + 1].pit[index]); */
L_sum = L_sub(L_deposit_h(pitTrack[i].pit[j]),
L_deposit_h(pitTrack[i+1].pit[index]));
L_cost = L_add(L_cost, L_shl(L_abs(L_sum), 5)); /* Q5 */
/* pitTrack[i].cost[j] += pitTrack[i+1].cost[index]; */
L_cost = L_add(L_cost, L_deposit_h(pitTrack[i+1].cost[index]));
pitTrack[i].cost[j] = extract_h(L_cost); /* Q5 */
}
}
/* find the best index to minimize the cost */
L_cost = L_deposit_h(pitTrack[0].cost[0]);
index = 0;
for( i = 1; i < NODE; i++){
if( L_deposit_h(pitTrack[0].cost[i]) < L_cost ){
L_cost = L_deposit_h(pitTrack[0].cost[i]);
index = i;
}
}
return(shl(pitTrack[0].pit[index], 7));
}
/* ========================================================================== */
/* This function replaces the previous macro declaration for RATIO(x, y): */
/* */
/* RATIO(x, y) = (fabs((float)(x)-(float)(y))/(float)((x)>(y)?(x):(y))) */
/* */
/* The Shortword Q7 arguments x and y are implied to be positive. The */
/* returned value is Q15. */
/* ========================================================================== */
Shortword ratio(Shortword x, Shortword y)
{
Shortword diff, larger;
diff = sub(x, y);
diff = abs_s(diff);
larger = (Shortword) ((x > y) ? x : y);
return(divide_s(diff, larger));
}
/* ========================================================================== */
/* This function should be functionally almost the same as ratio() except */
/* that the second argument is Longword. It is used in sc_ana() of */
/* "melp_ana.c" when we call ratio() in */
/* */
/* ratio(par[1].pitch, (prev_pitch*3)) < X008_Q15 */
/* */
/* where a Q7 prev_pitch multiplied by 3 could overflow a Shortword. Both */
/* inputs are still Q7 and the returned value is still Q15. */
/* ========================================================================== */
Shortword L_ratio(Shortword x, Longword y)
{
Longword L_x, diff, larger;
L_x = L_deposit_l(x);
diff = L_sub(y, L_x);
if (diff < 0)
diff = L_negate(diff);
larger = (L_x > y) ? L_x : y;
return(L_divider2(diff, larger, 0, 0));
}
/* ========================================================================== */
/* This function updates silenceEn and voicedEn used in sc_ana() of */
/* "melp_ana.c". prev_en, curr_en and the returned result are of the same */
/* Q value (Q11), while ifact is Q15. */
/* */
/* Note that because of the dynamic range problem, approximations are used in */
/* the fixed point implementation. The implementation assumes "ifact" is */
/* always equal to 0.9. */
/* ========================================================================== */
Shortword updateEn(Shortword prev_en, Shortword ifact, Shortword curr_en)
{
Shortword temp1, temp2;
Shortword result; /* Q11 */
/* Now we want to compute */
/* log10(ifact*pow(10.0, prev_en) + (1.0 - ifact)*pow(10.0, curr_en)). */
/* We rearrange the expression as */
/* prev_en + log10(ifact + (1 - ifact) * */
/* pow(10.0, curr_en - prev_en)) */
/* Depending on the range of (curr_en - prev_en), we might choose to */
/* ignore the pow() term, or ignore the "ifact" term inside log10() (so */
/* the expression becomes curr_en + log10(1 - ifact)). This manipulation */
/* is necessary because pow(10.0, prev_en) and pow(10.0, curr_en) can */
/* easily overflow the dynamic range for Shortword. */
temp1 = shr(curr_en, 1); /* Q10 */
temp2 = shr(prev_en, 1);
temp1 = sub(temp1, temp2); /* Q10 */
if (temp1 < negate(ONE_Q10)){ /* Case (a) */
/* Compute log10(ifact) + prev_en. */
temp1 = log10_fxp(ifact, 15); /* Q12 */
temp1 = shr(temp1, 1); /* Q11 */
result = add(temp1, prev_en);
} else if (temp1 > THREE_Q10){ /* Case (b) */
temp1 = sub(ONE_Q15, ifact); /* Q15 */
temp1 = log10_fxp(temp1, 15); /* Q12 */
temp1 = shr(temp1, 1); /* Q11 */
result = add(temp1, curr_en); /* Q11 */
} else { /* Case (c) */
/* temp1 = (curr_en - prev_en) is between -1 and 3. */
temp1 = shl(temp1, 2); /* Q12 */
temp1 = pow10_fxp(temp1, 5); /* Q5 */
temp1 = interp_scalar(temp1, ONE_Q5, ifact); /* Q5 */
temp1 = log10_fxp(temp1, 5); /* Q12 */
temp1 = shr(temp1, 1); /* Q11 */
result = add(prev_en, temp1);
}
return(result);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -