www.pudn.com > AVS_M_ver10.rar > open_pitch.c


/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2007 Audio Video Coding Standard, Part ¢ú
*
* This software module was developed by AVS Audio sub-group
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the users without any
* license fee or royalty on an "as is" basis. The AVS disclaims
* any and all warranties, whether express, implied, or statutory,
* including any implied warranties of merchantability or of fitness
* for a particular purpose. In no event shall the contributors or
* the AVS be liable for any incidental, punitive, or consequential
* damages of any kind whatsoever arising from the use of this program.
*
* This disclaimer of warranty extends to the user of this program
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The AVS does not represent or warrant that the program furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy is available from the AVS Web site at
* http://www.avs.org.cn
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
************************************************************************
*/

#include <stdio.h>
#include <math.h>
#include <float.h>
#include "../include/amr_plus.h"
#include "../../c-code/include/pre_open_pitch.h"
#include "../../c-code/include/open_pitch.h"

static int global_pitch = 0;
static int prevGp = 0;
static int prev_pitch = 0;

static int pitch_cand = 0;
static float corr_cand = 0.0;

static char cond_mul = 0; /* the condition to justify if P0 is multiple of Pc */

int pos[PITCH_NUM];

/************************************************************************/
/* function sort the peak and peakPos according to peak descend
method: heap sort
argument list:
float* peak (i): input peak vector
float* peakPos (i): input peakPos vector
int num (i): the length of the peak vector

return value: N/A */
/************************************************************************/

void sort(float* peak, int p_num, int* peakPos)
{
int end; /* the end index to heap sort */
int start; /* the start index in a heap sort */
char odd; /* if the end index is odd */
float chg_buf; /* the buf in the sort change */
int chg_buf_pos; /* the buf in the sort for peakPos */

/* initiate the end index to be p_num-1 */
end = p_num - 1;
/* justify if the end is odd or even number */
odd = (char)(end &amt; 1);
while(end>0)
{
start = (end - 1)/2;
/* the odd end means the start*2+1 index in peak vector dose not exist */
if(odd){
if(peak[start]>peak[start*2+1]){
/* the queue is wrong */
/* change the two peak value */
chg_buf = peak[start];
peak[start] = peak[start*2+1];
peak[start*2+1] = chg_buf;
/* change the two peakPos value */
chg_buf_pos = peakPos[start];
peakPos[start] = peakPos[start*2+1];
peakPos[start*2+1] = chg_buf_pos;
}
/* update the start value */
start--;
}
while(start >= 0){
/* find the max value in the peak[start*2+1] and peak[start*2+2] */
if(peak[start*2+2]<peak[start*2+1]){
if(peak[start*2+2]<peak[start]){
/* the queue is wrong */
/* change the two peak value */
chg_buf = peak[start];
peak[start] = peak[start*2+2];
peak[start*2+2] = chg_buf;
/* change the two peakPos value */
chg_buf_pos = peakPos[start];
peakPos[start] = peakPos[start*2+2];
peakPos[start*2+2] = chg_buf_pos;
}
}
else{
if(peak[start*2+1]<peak[start]){
/* the queue is wrong */
/* change the two peak value */
chg_buf = peak[start];
peak[start] = peak[start*2+1];
peak[start*2+1] = chg_buf;
/* change the two peakPos value */
chg_buf_pos = peakPos[start];
peakPos[start] = peakPos[start*2+1];
peakPos[start*2+1] = chg_buf_pos;
}
}
/* update the start value */
start--;
}
/* update the end index */
/* put the smallest one to the last */
chg_buf = peak[end];
peak[end] = peak[0];
peak[0] = chg_buf;
/* peakPos is modified with the peak */
chg_buf_pos = peakPos[end];
peakPos[end] = peakPos[0];
peakPos[0] = chg_buf_pos;
/* update the downlimit in the comparision */
end--;
/* update the odd state */
odd = (char)(1 - odd);
}
}

/************************************************************************/
/*function: justify if there's a pitch candidate is the multiple of the pitch
argument list:
int* peak_pos (i): pos vector
int num (i): the length of the peak vector
int pitch (i): the pitch candidate to be check
return value: int
the state if there's a pitch candidate is the multiple of the pitch
*/
/************************************************************************/

int Ambiguous_2(int* peak_pos, int num, int pitch)
{
int i; /* the index to look over the vector */
int state = 0; /* the result state */
i = 0;
while(i<num){
/* do not consider the pitch itself */
if(peak_pos[i] == pitch){
i++;
continue;
}
/*justify if the candidate is the multiple of the pitch */
if( abs( peak_pos[i] - 2 * pitch ) < 5
|| abs( peak_pos[i] - 3 * pitch ) < 8
|| abs( peak_pos[i] - 4 * pitch ) < 8
|| abs( peak_pos[i] - 5 * pitch ) < 8
|| abs( peak_pos[i] - 6 * pitch ) < 8
|| abs( peak_pos[i] - 7 * pitch ) < 8 ){
state = 1;
break;
}
i++;
}
return state;
}

/************************************************************************/
/* function: justify if the P0 is the multiple of the Pc
argument list:
float* peak (i): the peak correlation vector
int* peak_pos (i): the pos vector corresponding to the peak vector
int num (i): the length of the peak vector
return value: int
return the state if the P0 is the multiple of Pc */
/************************************************************************/

int Ambiguous_1(float* peak, int* peak_pos, int num)
{
int i; /* the index to look over the peak correlation vector */
int pitch; /* the pitch candidate */
float ratio; /* the ratio in look for the pitch candidate */
if(num>= 2){
/* case of multiple significant pitches */
pitch = peak_pos[0];
for(i=1; i<num; i++){
/* divide the peak corr into two section */
if(peak_pos[i]< 25)
/* the first section ratio is 1.11 */
ratio = (float)1.11;
else
/* the second section ratio is 1.2 */
ratio = (float)1.2;
if(peak[0]/(peak[i]+FLT_MIN)<ratio&amt;&amt;peak_pos[i]<pitch){
/* get the peak candidate */
pitch = peak_pos[i];
}
}
/* justify if the P0 is multiple of Pc */
return(abs(peak_pos[0]-2*pitch)<5||abs(peak_pos[0]-3*pitch)<8
||abs(peak_pos[0]-4*pitch)<8||abs(peak_pos[0]-5*pitch)<8
||abs(peak_pos[0]-6*pitch)<8||abs(peak_pos[0]-7*pitch)<8);
}
return 0;
}

/************************************************************************/
/* function: to get the pitch candidate value
argument list:
float* sig_in (i): the input signal
float* maxcr (o): the output correlation vector
int* peakPos (o): the output pitch vector
int lower (i): the serch down limit
int upper (i): the serch up limit
int length (i): the length of the signal
int* pch_num (o): the length of the peak vector
return value: N/A */
/************************************************************************/

void calc_pitch_cand(float* sig_in, float* maxcr, int* peakPos,
int lower, int upper, int length, int* pch_num)
{
int i, j, m, n;
double corr; /* the temp correlation */
double c0_0, cT_T; /* the nominator to calculate the correlation value */
/* the var to save the correlation value */
double mid_corr; /* the correlation of the middle section */
double side_corr; /* the correlation of the side section */

float corr_pre; /* correlation of last search delay */
char peak_able; /* ability to be peak value of last search correlation */

corr_pre = 0.0;
peak_able = 0;
*pch_num = 0;

/* Calculate the energy of the vector */
mid_corr = v_magsq(sig_in,length-lower);
side_corr = v_magsq(sig_in+length-lower,lower);
c0_0 = mid_corr + side_corr;
/* Calculate the energy of the last pitch vector */
side_corr = v_magsq( &amt;(sig_in[-lower]),lower);
cT_T = mid_corr + side_corr;
for( i=lower; i<=upper; i++ )
{
/* calculate auto-correlation */
corr = v_inner( sig_in, &amt;(sig_in[-i]), length );
/* to avoid the correlation to be to small */
if( corr > 0.005||corr < -0.005){
mid_corr = c0_0 * cT_T ;
/* to avoid the denominator to be zero */
if(mid_corr < 0.0005)
mid_corr = 0.0005 ;
if(corr>0)
corr = (corr*corr) / mid_corr;
else
corr = -(corr*corr) / mid_corr;
}
/* update for next iteration */
if(i<(upper)){
/* in the last iteration there's no need to update */
cT_T += sig_in[-i-1]*sig_in[-i-1]-sig_in[-i+length-1]*sig_in[-i+length-1];
}
/* justify if the correlation is peak value */
if(peak_able){
/* condition1: compare the two previous delay, the correlation corresponding to the smaller delay is smaller */
if(corr_pre>(float)corr){
/* set peak_able tag */
peak_able = 0;
/* the previous correlation is peak value */
/* insert the previous delay and correlation to peak vector */
if(*pch_num < PITCH_NUM){ /* maximum of peak value number is PITCH_NUM */
(*pch_num)++;
n = ((*pch_num) - 2); /* end of search */
}
else{
n = 5; /* end of search */
}
m = 0; /* begin of search */
j = ((m+n)>>1);
while(m<=n){
/* modify begin and end index */
if(corr_pre>maxcr[j]){
n = (j - 1);
}
else{
m = (j + 1);
}
j = ((m+n)>>1);
}
/* set the end of the peak vector */
j = (*pch_num - 1);
while(j>m){
/* move the peak vector */
maxcr[j] = maxcr[j-1];
peakPos[j] = peakPos[j-1];
j--;
}
/* insert current correlation and delay */
if(m<PITCH_NUM){
maxcr[m] = corr_pre;
peakPos[m] = i - 1;
}
}
else{
if(corr_pre<(float)corr){
/* set peak_able tag */
peak_able = 1;
}
else
/* set peak_able tag */
peak_able = 0;
}
}
else{
if(corr_pre<corr)
peak_able = 1;
else
peak_able = 0;
}
corr_pre = (float)corr;
/* save autocorrelation */
// corr_list[i-lower] = (float)corr;/
}
if(!(*pch_num)){
maxcr[0] = corr_pre;
peakPos[0] = lower;
*pch_num = 1;
}
return;
}

/************************************************************************/
/* function: find the global pitch reference
argument list:
int* peakPos (i): the pitch candidate vector
float* maxcr (i): the correlation candidate vector
int num (i): the length of the peak vector
return value: N/A
set global variable:
int global_pitch (0): the global pitch
int prevGp (o): the last nonzero global pitch
set static variable
int gpcd (i/o): the last pitch candidate
int fbState (i/o): the weak pitch hold state
int gpHoldState (i/o): the global pitch hold state
int hold_Gp (i/o): the preGp hold state
*/
/************************************************************************/

void CheckGlobalPitch(int* peakPos,float* maxcr,int num)
{
static int gpcd = 0;
static int fbState = 0;
static int gpHoldState = 0;
static int hold_Gp = 0;

int pitch; /* the pitch candidate value */
float corr; /* the correlation candidate value */
char i; /* the index to look over the vector */
char condition1; /* the first condition to confirm the global-pitch */
char condition2; /* the second condition to confirm the global-pitch */
char condition3; /* the third condition to confirm the global-pitch */
char condition4; /* the fourth condition to confirm the global-pitch */

/* weight the peak correlation value according the global_pitch */
if(global_pitch){
for(i=0; i<num; i++){
if(abs(peakPos[i]-global_pitch)<3)
maxcr[i] *= (float)1.2;
}
/* sort the peak_corr value again */
sort(maxcr,num,peakPos);
}
/* initiate the pitch candidate and corr candidate value */
pitch = peakPos[0];
corr = maxcr[0];
if(maxcr[0]>0.2){
/* justify is the P0 is multiple of Pc */
if(cond_mul = (char)(Ambiguous_1(maxcr, peakPos, num))){
for(i=1; i<num; i++){
if(maxcr[0]/(maxcr[i]+FLT_MIN)<1.2&amt;&amt;peakPos[i]<pitch){
/* update the pitch and corr candidate value */
pitch = peakPos[i];
corr = maxcr[i];
}
}
}
}
/* save the pitch candidate and correlation value candidate */
pitch_cand = pitch;
corr_cand = corr;
/* if the pitch is multiple or fractional of global_pitch */
/* set the candidate to be global_pitch */
if(
fabs((float)global_pitch-(float)pitch/2.0)/((float)global_pitch+FLT_MIN)<0.11
||fabs((float)global_pitch-(float)pitch/3.0)/((float)global_pitch+FLT_MIN)<0.11){
pitch = global_pitch;
}
/* 0.6*1.32*0.6*1.32 = 0.627264 */
/* if the corr is large enough */
if(corr>0.627264){
/* the first condition to confirm the global pitch */
condition1 = (char)(!cond_mul &amt;&amt; fabs(pitch-global_pitch)<8.0);
/* the second condition to confirm the global pitch */
condition2 = (char)(maxcr[0]>0.6274 &amt;&amt; maxcr[0]/maxcr[1]>1.7);
/* the third condition to confirm the global pitch */
condition3 = (char)(cond_mul||Ambiguous_2(peakPos,num,pitch));
/* the fourth condition to confirm the global pitch */
condition4 = (char)(maxcr[0]>0.36 &amt;&amt; fabs(global_pitch-2*pitch)<5.0);
/* if the condition is satisfied, set the credible global pitch */
if(condition1 || condition2 || condition3 || condition4){
/* set the global_pitch */
global_pitch = pitch;
/* set the hold state to be zero */
gpHoldState = 0;
if(global_pitch != 0){
/* the prevGp set to be the last nonzero global_pitch */
prevGp = global_pitch;
hold_Gp = 0;
}
}
}
else{
/* if the correlation is too small */
/* the pitch is very weak */
if(maxcr[0]<0.15){
if(global_pitch != 0){
/* the prevGp set to be the last nonzero global_pitch */
prevGp = global_pitch;
hold_Gp = 0;
}
/* set the global pitch to be zero */
global_pitch = 0;
/* set the hold state to be zero */
gpHoldState = 0;
}
/* the hold state limit is 2 */
if(gpHoldState == 2){
if(global_pitch != 0){
/* the prevGp set to be the last nonzero global_pitch */
prevGp = global_pitch;
hold_Gp = 0;
}
/* if the hold state get to the limit, set the global pitch zero */
global_pitch = 0;
gpHoldState = 0;
}
else{
/* if the hold state does not exceed the limit */
gpHoldState++;
}
/* consider the weak pitch hold state */
if(maxcr[0]<0.15){
if(fbState == 1){
if(global_pitch != 0){
/* the prevGp set to be the last nonzero global_pitch */
prevGp = global_pitch;
hold_Gp = 0;
}
global_pitch = 0;
}
else{
/* if the weak pitch hold state does not exceed the limit */
fbState++;
}
}
else{
fbState=0;
}
}
/* set the last frame pitch candidate */
gpcd = pitch;
/* increase the Gp hold state */
hold_Gp ++;
/* the Gp hold state's limit is 4 */
if(hold_Gp >= 4){
prevGp = 0;
}
return;
}

/************************************************************************/
/* function : the main function in the pitch determination
argument list:
float* sig_in (i): the input signal
int lower (i): the search down limit
int upper (i): the search up limit
int length (i): the length of the signal
return value: N/A
*/
/************************************************************************/

int find_pitch(float* sig_in, int lower, int upper, int length)
{
int i; /* the index to look over the vector */
int peakPos[PITCH_NUM]; /* the peakPos list vector */
float maxcr[PITCH_NUM]; /* the correlation list vector */

float corr_c; /* the correlation candidate */
int p_num; /* the length of peak vector */
int pitch_c; /* the pitch candidate */
int trkp; /* the reference to set the pitch */

int max_i; /* the index of the pos which is nearest to trkp */
/* initiate the trkp to zero */
trkp = 0;
/* compute pitch candidates */
calc_pitch_cand(sig_in, maxcr, peakPos, lower, upper, length, &amt;p_num);
/* compute the global pitch */
CheckGlobalPitch(peakPos, maxcr, p_num);
/* if the correlation is too small, pitch which corresponding to the max correlation value */
if(maxcr[0]<0.15){
prev_pitch = 0 ;
return peakPos[0];
}
/* load the pitch candidate and correlation value candidate */
pitch_c = pitch_cand;
corr_c = corr_cand;
/* consider the global pitch */
if(global_pitch>12 &amt;&amt; abs(global_pitch-pitch_c)<5){
/* if the candidate is near to the global pitch */
/* set the candidate to be the pitch */
prev_pitch = pitch_c ;
return pitch_c;
}
/* if the pitch has not confirmed, use the trkp to weight*/
if(global_pitch){
/* the most preferential trkp is global_pitch */
trkp = global_pitch;
}
else{
if(prev_pitch){
/* the second preferential trkp is pre_pitch */
trkp = prev_pitch;
}
else{
if(prevGp){
/* the third preferential trkp is prevGp */
trkp =prevGp;
}
}
}
i=0;
max_i = 0 ;
if(corr_c<0.6 &amt;&amt; trkp){
while((i<p_num) &amt;&amt; (maxcr[i]>0.10)){
if(abs(peakPos[i]-trkp)<abs(peakPos[max_i]-trkp)){
/* find the pitch candidate which is nearest to trkp */
max_i = i;
}
i++;
}
/* weight the corr */
maxcr[max_i] *= 2;
if(corr_c < maxcr[max_i]){
corr_c = maxcr[max_i] ;
pitch_c = peakPos[max_i];
}
}
return(pitch_c);
}