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 + -
显示快捷键?