📄 wav2mfcc-pipe.c
字号:
if (c->cmean_init_set) { /* initial data exists */ for(d=0;d<c->veclen;d++) { /* accumulate current MFCC to sum */ c->now.mfcc_sum[d] += mfcc[d]; /* calculate map-mean */ x = c->now.mfcc_sum[d] + c->cweight * c->cmean_init[d]; y = (double)c->now.framenum + c->cweight; x /= y; if (c->var) { /* calculate map-var */ c->now.mfcc_var[d] += (mfcc[d] - x) * (mfcc[d] - x); } if (c->mean && d < c->mfcc_dim) { /* mean normalization */ mfcc[d] -= x; } if (c->var) { /* variance normalization */ x = c->now.mfcc_var[d] + c->cweight * c->cvar_init[d]; y = (double)c->now.framenum + c->cweight; mfcc[d] /= sqrt(x / y); } } } else { /* no initial data */ for(d=0;d<c->veclen;d++) { /* accumulate current MFCC to sum */ c->now.mfcc_sum[d] += mfcc[d]; /* calculate current mean */ x = c->now.mfcc_sum[d] / c->now.framenum; if (c->var) { /* calculate current variance */ c->now.mfcc_var[d] += (mfcc[d] - x) * (mfcc[d] - x); } if (c->mean && d < c->mfcc_dim) { /* mean normalization */ mfcc[d] -= x; }#if 0 /* not perform variance normalization on no initial data */ if (c->var) { /* variance normalization */ mfcc[d] /= sqrt(c->now.mfcc_var[d] / c->now.framenum); }#endif } }}/** * Update initial cepstral mean from previous utterances for next input. * * @param c [i/o] CMN calculation work area */voidCMN_realtime_update(CMNWork *c, HTK_Param *param){ float *tmp, *tmp2; int i, d; int frames; /* if CMN_realtime was never called before this, return immediately */ /* this may occur by pausing just after startup */ if (c->now.framenum == 0) return; /* re-calculate variance based on the final mean at the given param */ if (c->var && param != NULL) { float m, x; if (param->samplenum != c->now.framenum) { jlog("InternalError: CMN_realtime_update: param->samplenum != c->now.framenum\n"); } else if (param->veclen != c->veclen) { jlog("InternalError: CMN_realtime_update: param->veclen != c->veclen\n"); } else { for(d=0;d<c->veclen;d++) { m = c->now.mfcc_sum[d] / (float) c->now.framenum; x = 0; for(i=0;i<param->samplenum;i++) { x += (param->parvec[i][d] - m) * (param->parvec[i][d] - m); } c->now.mfcc_var[d] = x; } } } /* compute cepstral mean from now and previous sums up to CPMAX frames */ for(d=0;d<c->veclen;d++) c->cmean_init[d] = c->now.mfcc_sum[d]; if (c->var) { for(d=0;d<c->veclen;d++) c->cvar_init[d] = c->now.mfcc_var[d]; } frames = c->now.framenum; for(i=0;i<c->clist_num;i++) { for(d=0;d<c->veclen;d++) c->cmean_init[d] += c->clist[i].mfcc_sum[d]; if (c->var) { for(d=0;d<c->veclen;d++) c->cvar_init[d] += c->clist[i].mfcc_var[d]; } frames += c->clist[i].framenum; if (frames >= CPMAX) break; } for(d=0;d<c->veclen;d++) c->cmean_init[d] /= (float) frames; if (c->var) { for(d=0;d<c->veclen;d++) c->cvar_init[d] /= (float) frames; } c->cmean_init_set = TRUE; /* expand clist if neccessary */ if (c->clist_num == c->clist_max && frames < CPMAX) { c->clist_max += CPSTEP; c->clist = (CMEAN *)myrealloc(c->clist, sizeof(CMEAN) * c->clist_max); for(i=c->clist_num;i<c->clist_max;i++) { c->clist[i].mfcc_sum = (float *)mymalloc(sizeof(float)*c->veclen); if (c->var) c->clist[i].mfcc_var = (float *)mymalloc(sizeof(float)*c->veclen); c->clist[i].framenum = 0; } } /* shift clist */ tmp = c->clist[c->clist_max-1].mfcc_sum; if (c->var) tmp2 = c->clist[c->clist_max-1].mfcc_var; memmove(&(c->clist[1]), &(c->clist[0]), sizeof(CMEAN) * (c->clist_max - 1)); c->clist[0].mfcc_sum = tmp; if (c->var) c->clist[0].mfcc_var = tmp2; /* copy now to clist[0] */ memcpy(c->clist[0].mfcc_sum, c->now.mfcc_sum, sizeof(float) * c->veclen); if (c->var) memcpy(c->clist[0].mfcc_var, c->now.mfcc_var, sizeof(float) * c->veclen); c->clist[0].framenum = c->now.framenum; if (c->clist_num < c->clist_max) c->clist_num++;}/** * Read binary with byte swap (assume file is Big Endian) * * @param buf [out] data buffer * @param unitbyte [in] size of unit in bytes * @param unitnum [in] number of units to be read * @param fp [in] file pointer * * @return TRUE if required number of units are fully read, FALSE if failed. */static booleanmyread(void *buf, size_t unitbyte, int unitnum, FILE *fp){ if (myfread(buf, unitbyte, unitnum, fp) < (size_t)unitnum) { return(FALSE); }#ifndef WORDS_BIGENDIAN swap_bytes(buf, unitbyte, unitnum);#endif return(TRUE);}/** * Write binary with byte swap (assume data is Big Endian) * * @param buf [in] data buffer * @param unitbyte [in] size of unit in bytes * @param unitnum [in] number of units to write * @param fd [in] file descriptor * * @return TRUE if required number of units are fully written, FALSE if failed. */static booleanmywrite(void *buf, size_t unitbyte, size_t unitnum, int fd){#ifndef WORDS_BIGENDIAN swap_bytes(buf, unitbyte, unitnum);#endif if (write(fd, buf, unitbyte * unitnum) < unitbyte * unitnum) { return(FALSE); }#ifndef WORDS_BIGENDIAN swap_bytes(buf, unitbyte, unitnum);#endif return(TRUE);}/** * Load CMN parameter from file. If the number of MFCC dimension in the * file does not match the specified one, an error will occur. * * @param c [i/o] CMN calculation work area * @param filename [in] file name * * @return TRUE on success, FALSE on failure. */booleanCMN_load_from_file(CMNWork *c, char *filename){ FILE *fp; int veclen; jlog("Stat: wav2mfcc-pipe: reading initial CMN from file \"%s\"\n", filename); if ((fp = fopen_readfile(filename)) == NULL) { jlog("Error: wav2mfcc-pipe: failed to open\n"); return(FALSE); } /* read header */ if (myread(&veclen, sizeof(int), 1, fp) == FALSE) { jlog("Error: wav2mfcc-pipe: failed to read header\n"); fclose_readfile(fp); return(FALSE); } /* check length */ if (veclen != c->veclen) { jlog("Error: wav2mfcc-pipe: cepstral dimension mismatch\n"); jlog("Error: wav2mfcc-pipe: process = %d, file = %d\n", c->veclen, veclen); fclose_readfile(fp); return(FALSE); } /* read body */ if (myread(c->cmean_init, sizeof(float), c->veclen, fp) == FALSE) { jlog("Error: wav2mfcc-pipe: failed to read mean for CMN\n"); fclose_readfile(fp); return(FALSE); } if (c->var) { if (myread(c->cvar_init, sizeof(float), c->veclen, fp) == FALSE) { jlog("Error: wav2mfcc-pipe: failed to read variance for CVN\n"); fclose_readfile(fp); return(FALSE); } } if (fclose_readfile(fp) == -1) { jlog("Error: wav2mfcc-pipe: failed to close\n"); return(FALSE); } c->cmean_init_set = TRUE; jlog("Stat: wav2mfcc-pipe: read CMN parameter\n"); return(TRUE);}/** * Save the current CMN vector to a file. * * @param c [i/o] CMN calculation work area * @param filename [in] filename to save the data. * * @return TRUE on success, FALSE on failure. */booleanCMN_save_to_file(CMNWork *c, char *filename){ int fd; jlog("Stat: wav2mfcc-pipe: writing current cepstral data to file \"%s\"\n", filename); if ((fd = creat(filename, 0644)) == -1) { jlog("Error: wav2mfcc-pipe: failed to open \"%s\" to write current cepstral data\n", filename); return(FALSE); } /* write header */ if (mywrite(&(c->veclen), sizeof(int), 1, fd) == FALSE) { jlog("Error: wav2mfcc-pipe: cannot write header to \"%s\" as current cepstral data\n", filename); close(fd); return(FALSE); } /* write body */ if (mywrite(c->cmean_init, sizeof(float), c->veclen, fd) == FALSE) { jlog("Error: wav2mfcc-pipe: cannot write mean to \"%s\" as current cepstral data\n", filename); close(fd); return(FALSE); } if (c->var) { if (mywrite(c->cvar_init, sizeof(float), c->veclen, fd) == FALSE) { jlog("Error: wav2mfcc-pipe: cannot write variance to \"%s\" as current cepstrum\n", filename); close(fd); return(FALSE); } } close(fd); jlog("Stat: wav2mfcc-pipe: current cepstral data written to \"%s\"\n", filename); return(TRUE);}/***********************************************************************//* energy normalization and scaling on live input *//***********************************************************************//** * Initialize work area for energy normalization on live input. * This should be called once on startup. * * @param energy [in] energy normalization work area * */voidenergy_max_init(ENERGYWork *energy){ energy->max = 5.0;}/** * Prepare values for energy normalization on live input. * This should be called before each input segment. * * @param energy [in] energy normalization work area * @param para [in] MFCC computation configuration parameter */voidenergy_max_prepare(ENERGYWork *energy, Value *para){ energy->max_last = energy->max; energy->min_last = energy->max - (para->silFloor * LOG_TEN) / 10.0; energy->max = 0.0;}/** * Peform energy normalization using maximum of last input. * * @param energy [in] energy normalization work area * @param f [in] raw energy * @param para [in] MFCC computation configuration parameter * * @return value of the normalized log energy. */LOGPROBenergy_max_normalize(ENERGYWork *energy, LOGPROB f, Value *para){ if (energy->max < f) energy->max = f; if (f < energy->min_last) f = energy->min_last; return(1.0 - (energy->max_last - f) * para->escale);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -