www.pudn.com > lpc.zip > dyptrk_i.c


/**********************************************************************
*
*	DYPTRK Version 52
*
**********************************************************************
*
*   Dynamic Pitch Tracker
*
*  Inputs:
*   AMDF   - Average Magnitude Difference Function array
*   LTAU   - Number of lags in AMDF
*   MINPTR - Location of minimum AMDF value
*   VOICE  - Voicing decision
*  Outputs:
*   PITCH  - Smoothed pitch value, 2 frames delayed
*   MIDX   - Initial estimate of current frame pitch
*  Compile time constant:
*   DEPTH  - Number of frames to trace back
*/

#include "lpcdefs.h"
#include "ourstuff.h"

extern int_type s_i[60];
extern int_type p_i[60][2];

dyptrk_i( amdf, minptr, voice, pitch, midx )
int_type amdf[];
int_type minptr, voice, *pitch, *midx;
{
int_type sbar, minsc, maxsc, alpha, temp;
int_type depth=2;
int_type pbar, i, j, iptr, path[2];
static int_type alphax, ipoint=0;


/*   Calculate the confidence factor ALPHA, used as a threshold slope in
*   SEESAW.  If unvoiced, set high slope so that every point in P array
*   is marked as a potential pitch frequency.  A scaled up version (ALPHAX)
*   is used to maintain arithmetic precision.	*/

if( voice == 1 ) 
	alphax = (((long_type)3072*(long_type)alphax)>>12) + (amdf[minptr]>>1);
else
	alphax = ((long_type)4032*(long_type)alphax)>>12;
alpha = alphax>>4;


if( voice == 0 && alphax < 128 ) alpha = 8;

/*  SEESAW: Construct a pitch pointer array and intermediate winner function
*   Left to right pass:		*/

iptr = ipoint+1;
p_i[0][iptr-1] = 1;
i = 1;
pbar = 1;
temp = s_i[0]>>1;

for(i=1;i<=LTAU;i++)	{
  temp = (alpha>>1) + temp;
  sbar = (temp >= 16383)?(32767):(temp<<1);
  /*  printf("i: %d temp:%d sbar_i:%d alpha:%d s[i-1]:%d\n", i,temp, sbar, alpha, s_i[i-1]);*/
  if (sbar < s_i[i-1]) {
    s_i[i-1] = sbar;
    p_i[i-1][iptr-1] = pbar;
  }
  else	{
    temp = s_i[i-1]>>1;
    p_i[i-1][iptr-1] = i;
    pbar = i;
  }
}

/*   Right to left pass:	*/

i = pbar-1;
temp = s_i[i]>>1;

while (i>=1)	{
  temp = (alpha>>1) + temp;
  sbar = (temp >= 16383)?(32767):(temp<<1);
  /*  printf("i:%d temp:%d sbar_i:%d alpha:%d s_i[i-1]:%d\n",i,temp, sbar, alpha, s_i[i-1]);*/
  if (sbar < s_i[i-1]) {
    s_i[i-1] = sbar;
    p_i[i-1][iptr-1] = pbar;
  }
  else	{
    pbar = p_i[i-1][iptr-1];
    i = pbar;
    temp = s_i[i-1]>>1;
  }
  i--;
}

/*   Update S using AMDF
*   Find maximum, minimum, and location of minimum	*/

temp = (amdf[1]>>2) + (s_i[0]>>1);
s_i[0] = (temp >= 16383)?(32767):(temp<<1);
minsc = s_i[0];
maxsc = minsc;
*midx = 1;

for(i=2;i<=LTAU;i++)	{
  temp = (s_i[i-1]>>1) + (amdf[i]>>2);
  s_i[i-1] = (temp >= 16383)?(32767):(temp<<1);
  /*  printf("i:%d temp:%d s_i[i-1]:%d minsc:%d\n",i,temp,s_i[i-1],minsc);*/
  if(s_i[i-1] > maxsc) maxsc = s_i[i-1];
  if(s_i[i-1] < minsc) *midx = i;
  if(s_i[i-1] < minsc) minsc = s_i[i-1];
}

/*   Subtract MINSC from S to prevent overflow	*/

for(i=1;i<=LTAU;i++) {
	s_i[i-1] -= minsc;
	/*	printf("i:%d s_i:%d minsc:%d\n",i,s_i[i-1], minsc);*/
}

maxsc -= minsc;

/*   Use higher octave pitch if significant null there	*/

j = 0;
for(i=20;i<=40;i+=10)	
	if (*midx > i) 
		if (s_i[*midx-i-1] < (maxsc>>2)) j = i;
*midx -= j;

/*   TRACE: look back two frames to find minimum cost pitch estimate	*/

j = ipoint;
*pitch = *midx;
for(i=1;i<=depth;i++)	{
  j = j - depth* (j/depth) +1;
	*pitch = p_i[*pitch-1][j-1];
	path[i-1] = *pitch;
}
temp = ipoint + depth -1;
ipoint = temp - depth*(temp/depth);
/*printf("midx:%d pitch:%d\n",*midx, *pitch);*/
}