Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

wav2mfcc-pipe.c

Go to the documentation of this file.
00001 
00025 /*
00026  * Copyright (c) 1991-2006 Kawahara Lab., Kyoto University
00027  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00028  * Copyright (c) 2005-2006 Julius project team, Nagoya Institute of Technology, Nagoya Institute of Technology
00029  * All rights reserved
00030  */
00031 
00032 /* wav2mfcc-pipe.c --- split Wav2MFCC to perform per-frame-basis,
00033    and also realtime CMN for 1st-pass pipe-lining */
00034 
00035 /************************************************************************/
00036 /*    wav2mfcc.c   Convert Speech file to MFCC_E_D_(Z) file             */
00037 /*----------------------------------------------------------------------*/
00038 /*    Author    : Yuichiro Nakano                                       */
00039 /*                                                                      */
00040 /*    Copyright(C) Yuichiro Nakano 1996-1998                            */
00041 /*----------------------------------------------------------------------*/
00042 /************************************************************************/
00043 
00044 
00045 #include <sent/stddefs.h>
00046 #include <sent/mfcc.h>
00047 
00048 static double *fbank;                    
00049 static FBankInfo fb;            
00050 
00059 void
00060 WMP_init(Value para, float **bf, float *ssbuf, int ssbuflen)
00061 {
00062   /* Get filterbank information and initialize tables */
00063   fb = InitFBank(para);
00064   
00065   if((fbank = (double *)mymalloc((para.fbank_num+1)*sizeof(double))) == NULL){
00066     j_error("WMP_init failed\n");
00067   }
00068   if((*bf = (float *)mymalloc(fb.fftN * sizeof(float))) == NULL){
00069     j_error("WMP_init failed\n");
00070   }
00071 
00072   if (ssbuf != NULL) {
00073     /* check ssbuf length */
00074     if (fb.fftN != ssbuflen) {
00075       j_error("Error: Wav2MFCC: noise spectrum length not match\n");
00076     }
00077   }
00078 
00079   /* Normalise Log Energy is not implemented in pipeline mode */
00080   if(para.enormal) {
00081     j_error("Error: \"normalize log energy\" is not supported in live input mode\n");
00082   }
00083 }
00084 
00094 void
00095 WMP_calc(float *mfcc, float *bf, Value para, float *ssbuf)
00096 {
00097   float energy = 0.0;
00098   float c0 = 0.0;
00099   int p;
00100 
00101   if (para.zmeanframe) {
00102     ZMeanFrame(bf, para.framesize);
00103   }
00104 
00105   if (para.energy && para.raw_e) {
00106     /* calculate log raw energy */
00107     energy = CalcLogRawE(bf, para.framesize);
00108   }
00109   /* pre-emphasize */
00110   PreEmphasise(bf, para);
00111   /* hamming window */
00112   Hamming(bf, para.framesize);
00113   if (para.energy && ! para.raw_e) {
00114     /* calculate log energy */
00115     energy = CalcLogRawE(bf, para.framesize);
00116   }
00117   /* filterbank */
00118   MakeFBank(bf, fbank, fb, para, ssbuf);
00119   /* 0'th cepstral parameter */
00120   if (para.c0) c0 = CalcC0(fbank, para);
00121   /* MFCC */
00122   MakeMFCC(fbank, mfcc, para);
00123   /* weight cepstrum */
00124   WeightCepstrum(mfcc, para);
00125   /* set energy to mfcc */
00126   p = para.mfcc_dim;
00127   if (para.c0) mfcc[p++] = c0;
00128   if (para.energy) mfcc[p++] = energy;
00129 }
00130 
00131 /***********************************************************************/
00140 DeltaBuf *
00141 WMP_deltabuf_new(int veclen, int windowlen)
00142 {
00143   int i;
00144   DeltaBuf *db;
00145 
00146   db = (DeltaBuf *)mymalloc(sizeof(DeltaBuf));
00147   db->veclen = veclen;
00148   db->win = windowlen;
00149   db->len = windowlen * 2 + 1;
00150   db->mfcc = (float **)mymalloc(sizeof(float *) * db->len);
00151   db->is_on = (boolean *) mymalloc(sizeof(boolean) * db->len);
00152   for (i=0;i<db->len;i++) {
00153     db->mfcc[i] = (float *)mymalloc(sizeof(float) * veclen * 2);
00154   }
00155   db->B = 0;
00156   for(i = 1; i <= windowlen; i++) db->B += i * i;
00157   db->B *= 2;
00158 
00159   return (db);
00160 }
00161 
00167 void
00168 WMP_deltabuf_free(DeltaBuf *db)
00169 {
00170   int i;
00171 
00172   for (i=0;i<db->len;i++) {
00173     free(db->mfcc[i]);
00174   }
00175   free(db->is_on);
00176   free(db->mfcc);
00177   free(db);
00178 }
00179 
00185 void
00186 WMP_deltabuf_prepare(DeltaBuf *db)
00187 {
00188   int i;
00189   db->store = 0;
00190   for (i=0;i<db->len;i++) {
00191     db->is_on[i] = FALSE;
00192   }
00193 }
00194 
00201 static void
00202 WMP_deltabuf_calc(DeltaBuf *db, int cur)
00203 {
00204   int n, theta, p;
00205   float A1, A2, sum;
00206   int last_valid_left, last_valid_right;
00207   
00208   for (n = 0; n < db->veclen; n++) {
00209     sum = 0.0;
00210     last_valid_left = last_valid_right = cur;
00211     for (theta = 1; theta <= db->win; theta++) {
00212       p = cur - theta;
00213       if (p < 0) p += db->len;
00214       if (db->is_on[p]) {
00215         A1 = db->mfcc[p][n];
00216         last_valid_left = p;
00217       } else {
00218         A1 = db->mfcc[last_valid_left][n];
00219       }
00220       p = cur + theta;
00221       if (p >= db->len) p -= db->len;
00222       if (db->is_on[p]) {
00223         A2 = db->mfcc[p][n];
00224         last_valid_right = p;
00225       } else {
00226         A2 = db->mfcc[last_valid_right][n];
00227       }
00228       sum += theta * (A2 - A1);
00229     }
00230     db->mfcc[cur][db->veclen + n] = sum / db->B;
00231   }
00232 }
00233 
00244 boolean
00245 WMP_deltabuf_proceed(DeltaBuf *db, float *new_mfcc) 
00246 {
00247   int cur;
00248   boolean ret;
00249 
00250   /* copy data to store point */
00251   memcpy(db->mfcc[db->store], new_mfcc, sizeof(float) * db->veclen);
00252   db->is_on[db->store] = TRUE;
00253 
00254   /* get current calculation point */
00255   cur = db->store - db->win;
00256   if (cur < 0) cur += db->len;
00257 
00258   /* if the current point is fulfilled, compute delta  */
00259   if (db->is_on[cur]) {
00260     WMP_deltabuf_calc(db, cur);
00261     db->vec = db->mfcc[cur];
00262     ret = TRUE;
00263   } else {
00264     ret = FALSE;
00265   }
00266 
00267   /* move store pointer to next */
00268   db->store++;
00269   if (db->store >= db->len) db->store -= db->len;
00270 
00271   /* return TRUE if delta computed for current, or -1 if not calculated yet */
00272   return (ret);
00273 }
00274 
00286 boolean
00287 WMP_deltabuf_flush(DeltaBuf *db) 
00288 {
00289   int cur;
00290   boolean ret;
00291 
00292   /* clear store point */
00293   db->is_on[db->store] = FALSE;
00294 
00295   /* get current calculation point */
00296   cur = db->store - db->win;
00297   if (cur < 0) cur += db->len;
00298 
00299   /* if the current point if fulfilled, compute delta  */
00300   if (db->is_on[cur]) {
00301     WMP_deltabuf_calc(db, cur);
00302     db->vec = db->mfcc[cur];
00303     ret = TRUE;
00304   } else {
00305     ret = FALSE;
00306   }
00307 
00308   /* move store pointer to next */
00309   db->store++;
00310   if (db->store >= db->len) db->store -= db->len;
00311 
00312   /* return TRUE if delta computed for current, or -1 if not calculated yet */
00313   return (ret);
00314 }
00315 
00316 /***********************************************************************/
00317 /* MAP-CMN */
00318 /***********************************************************************/
00319 
00320 #define CPMAX 500               
00321 
00326 typedef struct {
00327   float *mfcc_sum;              
00328   int framenum;                 
00329 } CMEAN;
00330 #define CPSTEP 5                
00331 static CMEAN *clist;            
00332 static int clist_max;           
00333 static int clist_num;           
00334 static int dim;                 
00335 static float cweight;           
00336 static float *cmean_init;       
00337 static boolean cmean_init_set;  
00338 static CMEAN now;               
00339 
00347 void
00348 CMN_realtime_init(int dimension, float weight)
00349 {
00350   int i;
00351 
00352   dim = dimension;
00353   cweight = weight;
00354 
00355   clist_max = CPSTEP;
00356   clist_num = 0;
00357   clist = (CMEAN *)mymalloc(sizeof(CMEAN) * clist_max);
00358   for(i=0;i<clist_max;i++) {
00359     clist[i].mfcc_sum = (float *)mymalloc(sizeof(float)*dim);
00360     clist[i].framenum = 0;
00361   }
00362 
00363   now.mfcc_sum = (float *)mymalloc(sizeof(float) * dim);
00364 
00365   cmean_init = (float *)mymalloc(sizeof(float) * dim);
00366   cmean_init_set = FALSE;
00367 
00368 }
00369 
00374 void
00375 CMN_realtime_prepare()
00376 {
00377   int d;
00378   for(d=0;d<dim;d++) now.mfcc_sum[d] = 0.0;
00379   now.framenum = 0;
00380 }
00381 
00389 void
00390 CMN_realtime(float *mfcc, int dim)
00391 {
00392   int d;
00393   double x, y;
00394 
00395   now.framenum++;
00396   if (cmean_init_set) {
00397     for(d=0;d<dim;d++) {
00398       /* accumulate value of given MFCC to sum */
00399       now.mfcc_sum[d] += mfcc[d];
00400       /* calculate map-cmn and perform subtraction to the given vector */
00401       x = now.mfcc_sum[d] + cweight * cmean_init[d];
00402       y = (double)now.framenum + cweight;
00403       mfcc[d] -= x / y;
00404     }
00405   } else {
00406     for(d=0;d<dim;d++) {
00407       now.mfcc_sum[d] += mfcc[d];
00408       mfcc[d] -= now.mfcc_sum[d] / now.framenum;
00409     }
00410   }
00411 }
00412 
00417 void
00418 CMN_realtime_update()
00419 {
00420   float *tmp;
00421   int i, d;
00422   int frames;
00423 
00424   /* if CMN_realtime was never called before this, return immediately */
00425   /* this may occur by pausing just after startup */
00426   if (now.framenum == 0) return;
00427 
00428   /* compute cepstral mean from now and previous sums up to CPMAX frames */
00429   for(d=0;d<dim;d++) cmean_init[d] = now.mfcc_sum[d];
00430   frames = now.framenum;
00431   for(i=0;i<clist_num;i++) {
00432     for(d=0;d<dim;d++) cmean_init[d] += clist[i].mfcc_sum[d];
00433     frames += clist[i].framenum;
00434     if (frames >= CPMAX) break;
00435   }
00436   for(d=0;d<dim;d++) cmean_init[d] /= (float) frames;
00437   cmean_init_set = TRUE;
00438 
00439   /* expand clist if neccessary */
00440   if (clist_num == clist_max && frames < CPMAX) {
00441     clist_max += CPSTEP;
00442     clist = (CMEAN *)myrealloc(clist, sizeof(CMEAN) * clist_max);
00443     for(i=clist_num;i<clist_max;i++) {
00444       clist[i].mfcc_sum = (float *)mymalloc(sizeof(float)*dim);
00445       clist[i].framenum = 0;
00446     }
00447   }
00448   
00449   /* shift clist */
00450   tmp = clist[clist_max-1].mfcc_sum;
00451   memcpy(&(clist[1]), &(clist[0]), sizeof(CMEAN) * (clist_max - 1));
00452   clist[0].mfcc_sum = tmp;
00453   /* copy now to clist[0] */
00454   memcpy(clist[0].mfcc_sum, now.mfcc_sum, sizeof(float) * dim);
00455   clist[0].framenum = now.framenum;
00456 
00457   if (clist_num < clist_max) clist_num++;
00458 
00459 }
00460 
00471 static boolean
00472 myread(void *buf, size_t unitbyte, int unitnum, FILE *fp)
00473 {
00474   if (myfread(buf, unitbyte, unitnum, fp) < (size_t)unitnum) {
00475     return(FALSE);
00476   }
00477 #ifndef WORDS_BIGENDIAN
00478   swap_bytes(buf, unitbyte, unitnum);
00479 #endif
00480   return(TRUE);
00481 }
00482 
00493 static boolean
00494 mywrite(void *buf, size_t unitbyte, int unitnum, int fd)
00495 {
00496 #ifndef WORDS_BIGENDIAN
00497   swap_bytes(buf, unitbyte, unitnum);
00498 #endif
00499   if (write(fd, buf, unitbyte * unitnum) < unitbyte * unitnum) {
00500     return(FALSE);
00501   }
00502 #ifndef WORDS_BIGENDIAN
00503   swap_bytes(buf, unitbyte, unitnum);
00504 #endif
00505   return(TRUE);
00506 }
00507 
00517 boolean
00518 CMN_load_from_file(char *filename, int dim)
00519 {
00520   FILE *fp;
00521   int veclen;
00522   if ((fp = fopen_readfile(filename)) == NULL) {
00523     j_printerr("Error: CMN_load_from_file: failed to open\n");
00524     return(FALSE);
00525   }
00526   /* read header */
00527   if (myread(&veclen, sizeof(int), 1, fp) == FALSE) {
00528     j_printerr("Error: CMN_load_from_file: failed to read header\n");
00529     fclose_readfile(fp);
00530     return(FALSE);
00531   }
00532   /* check length */
00533   if (veclen != dim) {
00534     j_printerr("Error: CMN_load_from_file: vector dimension mismatch\n");
00535     fclose_readfile(fp);
00536     return(FALSE);
00537   }
00538   /* read body */
00539   if (myread(cmean_init, sizeof(float), dim, fp) == FALSE) {
00540     j_printerr("Error: CMN_load_from_file: failed to read\n");
00541     fclose_readfile(fp);
00542     return(FALSE);
00543   }
00544   if (fclose_readfile(fp) == -1) {
00545     j_printerr("Error: CMN_load_from_file: failed to close\n");
00546     return(FALSE);
00547   }
00548 
00549   cmean_init_set = TRUE;
00550 
00551   return(TRUE);
00552 }
00553 
00561 boolean
00562 CMN_save_to_file(char *filename)
00563 {
00564   int fd;
00565 
00566   if ((fd = creat(filename, 0644)) == -1) {
00567     j_printerr("Error: CMN_save_to_file: failed to open\n");
00568     return(FALSE);
00569   }
00570   /* write header */
00571   if (mywrite(&dim, sizeof(int), 1, fd) == FALSE) {
00572     j_printerr("Error: CMN_save_to_file: failed to write header\n");
00573     close(fd);
00574     return(FALSE);
00575   }
00576   /* write body */
00577   if (mywrite(cmean_init, sizeof(float), dim, fd) == FALSE) {
00578     j_printerr("Error: CMN_save_to_file: failed to write header\n");
00579     close(fd);
00580     return(FALSE);
00581   }
00582   close(fd);
00583   
00584   return(TRUE);
00585 }

Generated on Tue Mar 28 16:01:39 2006 for Julius by  doxygen 1.4.2