dp_f0.c

来自「speech signal process tools」· C语言 代码 · 共 919 行 · 第 1/2 页

C
919
字号
      /* Now have found the best path from this cand. to prev. frame */      if (first_time && i==0) {		/* this is the first frame */	headF->dp->dpvals[k] = headF->dp->mpvals[k];	headF->dp->prept[k] = 0;      } else {	headF->dp->dpvals[k] = errmin + headF->dp->mpvals[k];	headF->dp->prept[k] = minloc;      }    } /*    END OF THIS DP FRAME */    if (i < nframes - 1)      headF = headF->next;        if (debug_level >= 2) {      Fprintf(stderr,"%d engref:%10.0f max:%7.5f loc:%4d\n",	      i,engref,maxval,maxloc);    }      } /* end for (i ...) */  /***************************************************************/  /* DONE WITH FILLING DP STRUCTURES FOR THE SET OF SAMPLED DATA */  /*    NOW FIND A CONVERGED DP PATH                             */  /***************************************************************/  *vecsize = 0;			/* # of output frames returned */  num_active_frames += nframes;  if( num_active_frames >= size_frame_hist  || last_time ){    Frame *frm;    int  num_paths, best_cand, frmcnt, checkpath_done = 1;    float patherrmin;          if(debug_level)      Fprintf(stderr, "%s: available frames for backtracking: %d\n", 	      ProgName, num_active_frames);          patherrmin = FLT_MAX;    best_cand = 0;    num_paths = headF->dp->ncands;    /* Get the best candidate for the final frame and initialize the       paths' backpointers. */    frm = headF;    for(k=0; k < num_paths; k++) {      if (patherrmin > headF->dp->dpvals[k]){	patherrmin = headF->dp->dpvals[k];	best_cand = k;	/* index indicating the best candidate at a path */      }      pcands[k] = frm->dp->prept[k];    }    if(last_time){     /* Input data was exhausted. force final outputs. */      cmpthF = headF;		/* Use the current frame as starting point. */    } else {      /* Starting from the most recent frame, trace back each candidate's	 best path until reaching a common candidate at some past frame. */      frmcnt = 0;      while (1) {	frm = frm->prev;	frmcnt++;	checkpath_done = 1;	for(k=1; k < num_paths; k++){ /* Check for convergence. */	  if(pcands[0] != pcands[k])	    checkpath_done = 0;	}	if( ! checkpath_done) { /* Prepare for checking at prev. frame. */	  for(k=0; k < num_paths; k++){	    pcands[k] = frm->dp->prept[pcands[k]];	  }	} else {	/* All paths have converged. */	  cmpthF = frm;	  best_cand = pcands[0];	  if(debug_level)	    Fprintf(stderr,		    "%s: paths went back %d frames before converging\n",		    ProgName, frmcnt);	  break;	}	if(frm == tailF){	/* Used all available data? */	  if( num_active_frames < size_frame_out) { /* Delay some more? */	    checkpath_done = 0; /* Yes, don't backtrack at this time. */	    cmpthF = NULL;	  } else {		/* No more delay! Force best-guess output. */	    checkpath_done = 1;	    cmpthF = headF;	    Fprintf(stderr,		    "%s: WARNING: no converging path found after going back %d frames, will use the lowest cost path\n",		    ProgName, num_active_frames);	  }	  break;	} /* end if (frm ...) */      }	/* end while (1) */    } /* end if (last_time) ... else */    /*************************************************************/    /* BACKTRACKING FROM cmpthF (best_cand) ALL THE WAY TO tailF    */    /*************************************************************/    i = 0;    frm = cmpthF;	/* Start where convergence was found (or faked). */    while( frm != tailF->prev && checkpath_done){      if( i == output_buf_size ){ /* Need more room for outputs? */	output_buf_size *= 2;	if(debug_level)	  Fprintf(stderr,		  "%s: reallocating space for output frames: %d\n",		  ProgName, output_buf_size);	rms_speech = (float *) realloc((char *) rms_speech,				       sizeof(float) * output_buf_size);	spsassert(rms_speech, "rms_speech realloc failed in dp_f0()");	f0p = (float *) realloc((char *) f0p,				sizeof(float) * output_buf_size);	spsassert(f0p, "f0p realloc failed in dp_f0()");	vuvp = (float *) realloc(vuvp, sizeof(float) * output_buf_size);	spsassert(vuvp, "vuvp realloc failed in dp_f0()");	acpkp = (float *) realloc(acpkp, sizeof(float) * output_buf_size);	spsassert(acpkp, "acpkp realloc failed in dp_f0()");      }      rms_speech[i] = frm->rms;      acpkp[i] =  frm->dp->pvals[best_cand];      loc1 = frm->dp->locs[best_cand];      vuvp[i] = 1.0;      best_cand = frm->dp->prept[best_cand];      ftemp = loc1;      if(loc1 > 0) {		/* Was f0 actually estimated for this frame? */	if (loc1 > start && loc1 < stop) { /* loc1 must be a local maximum. */	  float cormax, cprev, cnext, den;		  	  j = loc1 - start;	  cormax = frm->cp->correl[j];	  cprev = frm->cp->correl[j+1];	  cnext = frm->cp->correl[j-1];	  den = (2.0 * ( cprev + cnext - (2.0 * cormax) ));	  /*	   * Only parabolic interpolate if cormax is indeed a local 	   * turning point. Find peak of curve that goes though the 3 points	   */		  	  if (fabs(den) > 0.000001)	    ftemp += 2.0 - ((((5.0*cprev)+(3.0*cnext)-(8.0*cormax))/den));	}	f0p[i] = freq/ftemp;      } else {		/* No valid estimate; just fake some arbitrary F0. */	f0p[i] = 0;	vuvp[i] = 0.0;      }      frm = frm->prev;	        if (debug_level >= 2)	Fprintf(stderr," i:%4d%8.1f%8.1f\n",i,f0p[i],vuvp[i]);      /* f0p[i] starts from the most recent one */       /* Need to reverse the order in the calling function */      i++;    } /* end while() */    if (checkpath_done){      *vecsize = i;      tailF = cmpthF->next;      num_active_frames -= *vecsize;    }  } /* end if() */  if (debug_level)    Fprintf(stderr, "%s: writing out %d frames.\n", ProgName, *vecsize);    *f0p_pt = f0p;  *vuvp_pt = vuvp;  *acpkp_pt = acpkp;  *rms_speech_pt = rms_speech;  *acpkp_pt = acpkp;    if(first_time) first_time = 0;  return(0);}/*--------------------------------------------------------------------*/Frame *alloc_frame(nlags, ncands)    int     nlags, ncands;{  Frame *frm;  int j;  frm = (Frame*)malloc(sizeof(Frame));  frm->dp = (Dprec *) malloc(sizeof(Dprec));  spsassert(frm->dp,"frm->dp malloc failed in alloc_frame");  frm->dp->ncands = 0;  frm->cp = (Cross *) malloc(sizeof(Cross));  spsassert(frm->cp,"frm->cp malloc failed in alloc_frame");  frm->cp->correl = (float *) malloc(sizeof(float) * nlags);  spsassert(frm->cp->correl, "frm->cp->correl malloc failed");  /* Allocate space for candidates and working arrays. */  frm->dp->locs = (short*)malloc(sizeof(short) * ncands);  spsassert(frm->dp->locs,"frm->dp->locs malloc failed in alloc_frame()");  frm->dp->pvals = (float*)malloc(sizeof(float) * ncands);  spsassert(frm->dp->pvals,"frm->dp->pvals malloc failed in alloc_frame()");  frm->dp->mpvals = (float*)malloc(sizeof(float) * ncands);  spsassert(frm->dp->mpvals,"frm->dp->mpvals malloc failed in alloc_frame()");  frm->dp->prept = (short*)malloc(sizeof(short) * ncands);  spsassert(frm->dp->prept,"frm->dp->prept malloc failed in alloc_frame()");  frm->dp->dpvals = (float*)malloc(sizeof(float) * ncands);  spsassert(frm->dp->dpvals,"frm->dp->dpvals malloc failed in alloc_frame()");      /*  Initialize the cumulative DP costs to zero */  for(j = ncands-1; j >= 0; j--)    frm->dp->dpvals[j] = 0.0;  return(frm);}/*--------------------------------------------------------------------*//* push window stat to stack, and pop the oldest one */static intsave_windstat(rho, order, err, rms)    float   *rho;    int     order;    float   err;    float   rms;{    int i,j;    if(wReuse > 1){               /* push down the stack */	for(j=1; j<wReuse; j++){	    for(i=0;i<=order; i++) windstat[j-1].rho[i] = windstat[j].rho[i];	    windstat[j-1].err = windstat[j].err;	    windstat[j-1].rms = windstat[j].rms;	}	for(i=0;i<=order; i++) windstat[wReuse-1].rho[i] = rho[i]; /*save*/	windstat[wReuse-1].err = err;	windstat[wReuse-1].rms = rms;	return 1;    } else if (wReuse == 1) {	for(i=0;i<=order; i++) windstat[0].rho[i] = rho[i];  /* save */	windstat[0].err = err;	windstat[0].rms = rms;	return 1;    } else 	return 0;}/*--------------------------------------------------------------------*/static intretrieve_windstat(rho, order, err, rms)    float   *rho;    int     order;    float   *err;    float   *rms;{    Windstat wstat;    int i;	    if(wReuse){	wstat = windstat[0];	for(i=0; i<=order; i++) rho[i] = wstat.rho[i];	*err = wstat.err;	*rms = wstat.rms;	return 1;    }    else return 0;}/*--------------------------------------------------------------------*/static floatget_similarity(order, size, pdata, cdata,	       rmsa, rms_ratio, pre, stab, w_type, init)    int     order, size;    float   *pdata, *cdata;    float   *rmsa, *rms_ratio, pre, stab;    int     w_type, init;{  float rho3[BIGSORD+1], err3, rms3, rmsd3, b0, t, a2[BIGSORD+1],       rho1[BIGSORD+1], a1[BIGSORD+1], b[BIGSORD+1], err1, rms1, rmsd1;  float itakura(), wind_energy();/* (In the lpc() calls below, size-1 is used, since the windowing and   preemphasis function assumes an extra point is available in the   input data array.  This condition is apparently no longer met after   Derek's modifications.) */  /* get current window stat */  lpc(order, stab, size-1, cdata,      a2, rho3, (float *) NULL, &err3, &rmsd3, pre, w_type);  rms3 = wind_energy(cdata, size, w_type);    if(!init) {      /* get previous window stat */      if( !retrieve_windstat(rho1, order, &err1, &rms1)){	  lpc(order, stab, size-1, pdata,	      a1, rho1, (float *) NULL, &err1, &rmsd1, pre, w_type);	  rms1 = wind_energy(pdata, size, w_type);      }      a_to_aca(a2+1,b,&b0,order);      t = itakura(order,b,&b0,rho1+1,&err1) - .8;      if(rms1 > 0.0)	  *rms_ratio = (0.001 + rms3)/rms1;      else	  if(rms3 > 0.0)	      *rms_ratio = 2.0;	/* indicate some energy increase */	  else	      *rms_ratio = 1.0;	/* no change */  } else {      *rms_ratio = 1.0;      t = 10.0;  }  *rmsa = rms3;  save_windstat( rho3, order, err3, rms3);  return((float)(0.2/t));}/* -------------------------------------------------------------------- *//* This is an ad hoc signal stationarity function based on Itakura * distance and relative amplitudes. *//*   This illustrates the window locations when the very first frame is read.  It shows an example where each frame step |  .  | is 10 msec.  The  frame step size is variable.  The window size is always 30 msec.  The window centers '*' is always 20 msec apart.  The windows cross each other right at the center of the DP frame, or  where the '.' is.                          ---------*---------   current window              ---------*---------  previous window  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |              ^           ^  ^              ^           ^  ^              ^           ^  fdata              ^           ^              ^           q	      p                          ---                          ind  fdata, q, p, ind, are variables used below.   */static Stat*get_stationarity(fdata, freq, buff_size, nframes, frame_step, first_time)    float   *fdata;    double  freq;    int     buff_size, nframes, frame_step, first_time;{  static Stat *stat;  static int nframes_old = 0, memsize;  static float *mem;  float preemp = 0.4, stab = 30.0;  float *p, *q, *r, *datend;  int ind, i, j, m, size, order, agap, w_type = 3;  agap = (int) (STAT_AINT *freq);  size = (int) (STAT_WSIZE * freq);  ind = (agap - size) / 2;  if( nframes_old < nframes || !stat || first_time){    /* move this to init_dp_f0() later */    nframes_old = nframes;    if(stat){       free((char *) stat->stat);      free((char *) stat->rms);      free((char *) stat->rms_ratio);      free((char *) stat);    }    stat = (Stat *) malloc(nframes *sizeof(Stat));    spsassert(stat,"stat malloc failed in get_stationarity");    stat->stat = (float*)malloc(sizeof(float)*nframes);    spsassert(stat->stat,"stat->stat malloc failed in get_stationarity");    stat->rms = (float*)malloc(sizeof(float)*nframes);    spsassert(stat->rms,"stat->rms malloc failed in get_stationarity");    stat->rms_ratio = (float*)malloc(sizeof(float)*nframes);    spsassert(stat->rms_ratio,"stat->ratio malloc failed in get_stationarity");    memsize = (int) (STAT_WSIZE * freq) + (int) (STAT_AINT * freq);    mem = (float *) malloc( sizeof(float) * memsize);    spsassert(mem, "mem malloc failed in get_stationarity()");    for(j=0; j<memsize; j++) mem[j] = 0;  }    if(nframes == 0) return(stat);  q = fdata + ind;  datend = fdata + buff_size;  if((order = 2.0 + (freq/1000.0)) > BIGSORD) {    Fprintf(stderr,	    "%s: Optimim order (%d) exceeds that allowable (%d); reduce Fs\n",	    ProgName, order, BIGSORD);    order = BIGSORD;  }  /* prepare for the first frame */  for(j=memsize/2, i=0; j<memsize; j++, i++) mem[j] = fdata[i];  /* never run over end of frame, should already taken care of when read */  for(j=0, p = q - agap; j < nframes; j++, p += frame_step, q += frame_step){      if( (p >= fdata) && (q >= fdata) && ( q + size <= datend) )	  stat->stat[j] = get_similarity(order,size, p, q, 					     &(stat->rms[j]),					     &(stat->rms_ratio[j]),preemp,					     stab,w_type, 0);      else {	  if(first_time) {	      if( (p < fdata) && (q >= fdata) && (q+size <=datend) )		  stat->stat[j] = get_similarity(order,size, NULL, q,						     &(stat->rms[j]),						     &(stat->rms_ratio[j]),						     preemp,stab,w_type, 1);	      else{		  stat->rms[j] = 0.0;		  stat->stat[j] = 0.01 * 0.2;   /* a big transition */		  stat->rms_ratio[j] = 1.0;   /* no amplitude change */	      }	  } else {	      if( (p<fdata) && (q+size <=datend) ){		  stat->stat[j] = get_similarity(order,size, mem, 						     mem + (memsize/2) + ind,						     &(stat->rms[j]),						     &(stat->rms_ratio[j]),						     preemp, stab,w_type, 0);		  /* prepare for the next frame_step if needed */		  if(p + frame_step < fdata ){		      for( m=0; m<(memsize-frame_step); m++) 			  mem[m] = mem[m+frame_step];		      r = q + size;		      for( m=0; m<frame_step; m++) 			  mem[memsize-frame_step+m] = *r++;		  }	      }	  }      }  }  /* last frame, prepare for next call */  for(j=(memsize/2)-1, p=fdata + (nframes * frame_step)-1; j>=0; j-- )    mem[j] = *p--;  return(stat);}/* -------------------------------------------------------------------- *//*	Round the argument to the nearest integer.			*/intround(flnum)    double  flnum;{  return((flnum >= 0.0) ? (int)(flnum + 0.5) : (int)(flnum - 0.5));}

⌨️ 快捷键说明

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