00001
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
00074 if (fb.fftN != ssbuflen) {
00075 j_error("Error: Wav2MFCC: noise spectrum length not match\n");
00076 }
00077 }
00078
00079
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
00107 energy = CalcLogRawE(bf, para.framesize);
00108 }
00109
00110 PreEmphasise(bf, para);
00111
00112 Hamming(bf, para.framesize);
00113 if (para.energy && ! para.raw_e) {
00114
00115 energy = CalcLogRawE(bf, para.framesize);
00116 }
00117
00118 MakeFBank(bf, fbank, fb, para, ssbuf);
00119
00120 if (para.c0) c0 = CalcC0(fbank, para);
00121
00122 MakeMFCC(fbank, mfcc, para);
00123
00124 WeightCepstrum(mfcc, para);
00125
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
00251 memcpy(db->mfcc[db->store], new_mfcc, sizeof(float) * db->veclen);
00252 db->is_on[db->store] = TRUE;
00253
00254
00255 cur = db->store - db->win;
00256 if (cur < 0) cur += db->len;
00257
00258
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
00268 db->store++;
00269 if (db->store >= db->len) db->store -= db->len;
00270
00271
00272 return (ret);
00273 }
00274
00286 boolean
00287 WMP_deltabuf_flush(DeltaBuf *db)
00288 {
00289 int cur;
00290 boolean ret;
00291
00292
00293 db->is_on[db->store] = FALSE;
00294
00295
00296 cur = db->store - db->win;
00297 if (cur < 0) cur += db->len;
00298
00299
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
00309 db->store++;
00310 if (db->store >= db->len) db->store -= db->len;
00311
00312
00313 return (ret);
00314 }
00315
00316
00317
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
00399 now.mfcc_sum[d] += mfcc[d];
00400
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
00425
00426 if (now.framenum == 0) return;
00427
00428
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
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
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
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
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
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
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
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
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 }