00001
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <sent/stddefs.h>
00036 #include <sent/htk_param.h>
00037 #include <sent/htk_hmm.h>
00038 #include <sent/mfcc.h>
00039
00040
00049 static void
00050 wrt(FILE *fp, void *buf, size_t unitbyte, int unitnum)
00051 {
00052 #ifndef WORDS_BIGENDIAN
00053 if (unitbyte != 1) {
00054 swap_bytes((char *)buf, unitbyte, unitnum);
00055 }
00056 #endif
00057 if (myfwrite(buf, unitbyte, unitnum, fp) < unitnum) {
00058 perror("write_binhmm: wrt");
00059 j_error("write failed\n");
00060 }
00061 #ifndef WORDS_BIGENDIAN
00062 if (unitbyte != 1) {
00063 swap_bytes((char *)buf, unitbyte, unitnum);
00064 }
00065 #endif
00066 }
00067
00074 static void
00075 wrt_str(FILE *fp, char *str)
00076 {
00077 static char noname = '\0';
00078
00079 if (str) {
00080 wrt(fp, str, sizeof(char), strlen(str)+1);
00081 } else {
00082 wrt(fp, &noname, sizeof(char), 1);
00083 }
00084 }
00085
00086
00087 static char *binhmm_header_v2 = BINHMM_HEADER_V2;
00088
00094 static void
00095 wt_header(FILE *fp, boolean emp, boolean inv)
00096 {
00097 char buf[50];
00098 char *p;
00099
00100 wrt_str(fp, binhmm_header_v2);
00101 p = &(buf[0]);
00102 if (emp) {
00103 *p++ = '_';
00104 *p++ = BINHMM_HEADER_V2_EMBEDPARA;
00105 }
00106 if (inv) {
00107 *p++ = '_';
00108 *p++ = BINHMM_HEADER_V2_VARINV;
00109 }
00110 *p = '\0';
00111 wrt_str(fp, buf);
00112 }
00113
00114
00121 static void
00122 wt_para(FILE *fp, Value *para)
00123 {
00124 short version;
00125
00126 version = VALUE_VERSION;
00127 wrt(fp, &version, sizeof(short), 1);
00128
00129 wrt(fp, &(para->smp_period), sizeof(long), 1);
00130 wrt(fp, &(para->smp_freq), sizeof(long), 1);
00131 wrt(fp, &(para->framesize), sizeof(int), 1);
00132 wrt(fp, &(para->frameshift), sizeof(int), 1);
00133 wrt(fp, &(para->preEmph), sizeof(float), 1);
00134 wrt(fp, &(para->lifter), sizeof(int), 1);
00135 wrt(fp, &(para->fbank_num), sizeof(int), 1);
00136 wrt(fp, &(para->delWin), sizeof(int), 1);
00137 wrt(fp, &(para->accWin), sizeof(int), 1);
00138 wrt(fp, &(para->silFloor), sizeof(float), 1);
00139 wrt(fp, &(para->escale), sizeof(float), 1);
00140 wrt(fp, &(para->hipass), sizeof(int), 1);
00141 wrt(fp, &(para->lopass), sizeof(int), 1);
00142 wrt(fp, &(para->enormal), sizeof(int), 1);
00143 wrt(fp, &(para->raw_e), sizeof(int), 1);
00144 wrt(fp, &(para->ss_alpha), sizeof(float), 1);
00145 wrt(fp, &(para->ss_floor), sizeof(float), 1);
00146 wrt(fp, &(para->zmeanframe), sizeof(int), 1);
00147 }
00148
00149
00156 static void
00157 wt_opt(FILE *fp, HTK_HMM_Options *opt)
00158 {
00159 wrt(fp, &(opt->stream_info.num), sizeof(short), 1);
00160 wrt(fp, opt->stream_info.vsize, sizeof(short), 50);
00161 wrt(fp, &(opt->vec_size), sizeof(short), 1);
00162 wrt(fp, &(opt->cov_type), sizeof(short), 1);
00163 wrt(fp, &(opt->dur_type), sizeof(short), 1);
00164 wrt(fp, &(opt->param_type), sizeof(short), 1);
00165 }
00166
00173 static void
00174 wt_type(FILE *fp, HTK_HMM_INFO *hmm)
00175 {
00176 wrt(fp, &(hmm->is_tied_mixture), sizeof(boolean), 1);
00177 wrt(fp, &(hmm->maxmixturenum), sizeof(int), 1);
00178 }
00179
00180
00181
00182 static HTK_HMM_Trans **tr_index;
00183 static unsigned int tr_num;
00184
00194 static int
00195 qsort_tr_index(HTK_HMM_Trans **t1, HTK_HMM_Trans **t2)
00196 {
00197 if (*t1 > *t2) return 1;
00198 else if (*t1 < *t2) return -1;
00199 else return 0;
00200 }
00201
00213 static void
00214 wt_trans(FILE *fp, HTK_HMM_INFO *hmm)
00215 {
00216 HTK_HMM_Trans *t;
00217 unsigned int idx;
00218 int i;
00219
00220 tr_num = 0;
00221 for(t = hmm->trstart; t; t = t->next) tr_num++;
00222 tr_index = (HTK_HMM_Trans **)mymalloc(sizeof(HTK_HMM_Trans *) * tr_num);
00223 idx = 0;
00224 for(t = hmm->trstart; t; t = t->next) tr_index[idx++] = t;
00225 qsort(tr_index, tr_num, sizeof(HTK_HMM_Trans *), (int (*)(const void *, const void *))qsort_tr_index);
00226
00227 wrt(fp, &tr_num, sizeof(unsigned int), 1);
00228 for (idx = 0; idx < tr_num; idx++) {
00229 t = tr_index[idx];
00230 wrt_str(fp, t->name);
00231 wrt(fp, &(t->statenum), sizeof(short), 1);
00232 for(i=0;i<t->statenum;i++) {
00233 wrt(fp, t->a[i], sizeof(PROB), t->statenum);
00234 }
00235 }
00236
00237 j_printf("%d transition maxtix written\n", tr_num);
00238 }
00239
00247 static unsigned int
00248 search_trid(HTK_HMM_Trans *t)
00249 {
00250 unsigned int left = 0;
00251 unsigned int right = tr_num - 1;
00252 unsigned int mid;
00253
00254 while (left < right) {
00255 mid = (left + right) / 2;
00256 if (tr_index[mid] < t) {
00257 left = mid + 1;
00258 } else {
00259 right = mid;
00260 }
00261 }
00262 return(left);
00263 }
00264
00265
00266
00267 static HTK_HMM_Var **vr_index;
00268 static unsigned int vr_num;
00269
00279 static int
00280 qsort_vr_index(HTK_HMM_Var **v1, HTK_HMM_Var **v2)
00281 {
00282 if (*v1 > *v2) return 1;
00283 else if (*v1 < *v2) return -1;
00284 else return 0;
00285 }
00286
00298 static void
00299 wt_var(FILE *fp, HTK_HMM_INFO *hmm)
00300 {
00301 HTK_HMM_Var *v;
00302 unsigned int idx;
00303
00304 vr_num = 0;
00305 for(v = hmm->vrstart; v; v = v->next) vr_num++;
00306 vr_index = (HTK_HMM_Var **)mymalloc(sizeof(HTK_HMM_Var *) * vr_num);
00307 idx = 0;
00308 for(v = hmm->vrstart; v; v = v->next) vr_index[idx++] = v;
00309 qsort(vr_index, vr_num, sizeof(HTK_HMM_Var *), (int (*)(const void *, const void *))qsort_vr_index);
00310
00311 wrt(fp, &vr_num, sizeof(unsigned int), 1);
00312 for (idx = 0; idx < vr_num; idx++) {
00313 v = vr_index[idx];
00314 wrt_str(fp, v->name);
00315 wrt(fp, &(v->len), sizeof(short), 1);
00316 wrt(fp, v->vec, sizeof(VECT), v->len);
00317 }
00318 j_printf("%d variance written\n", vr_num);
00319 }
00320
00328 static unsigned int
00329 search_vid(HTK_HMM_Var *v)
00330 {
00331 unsigned int left = 0;
00332 unsigned int right = vr_num - 1;
00333 unsigned int mid;
00334
00335 while (left < right) {
00336 mid = (left + right) / 2;
00337 if (vr_index[mid] < v) {
00338 left = mid + 1;
00339 } else {
00340 right = mid;
00341 }
00342 }
00343 return(left);
00344 }
00345
00346
00347
00348 static HTK_HMM_Dens **dens_index;
00349 static unsigned int dens_num;
00350
00360 static int
00361 qsort_dens_index(HTK_HMM_Dens **d1, HTK_HMM_Dens **d2)
00362 {
00363 if (*d1 > *d2) return 1;
00364 else if (*d1 < *d2) return -1;
00365 else return 0;
00366 }
00367
00381 static void
00382 wt_dens(FILE *fp, HTK_HMM_INFO *hmm)
00383 {
00384 HTK_HMM_Dens *d;
00385 unsigned int idx;
00386 unsigned int vid;
00387
00388 dens_num = hmm->totalmixnum;
00389 dens_index = (HTK_HMM_Dens **)mymalloc(sizeof(HTK_HMM_Dens *) * dens_num);
00390 idx = 0;
00391 for(d = hmm->dnstart; d; d = d->next) dens_index[idx++] = d;
00392 qsort(dens_index, dens_num, sizeof(HTK_HMM_Dens *), (int (*)(const void *, const void *))qsort_dens_index);
00393
00394 wrt(fp, &dens_num, sizeof(unsigned int), 1);
00395 for (idx = 0; idx < dens_num; idx++) {
00396 d = dens_index[idx];
00397 wrt_str(fp, d->name);
00398 wrt(fp, &(d->meanlen), sizeof(short), 1);
00399 wrt(fp, d->mean, sizeof(VECT), d->meanlen);
00400 vid = search_vid(d->var);
00401
00402 if (d->var != vr_index[vid]) j_error("index not match!!! dens\n");
00403 wrt(fp, &vid, sizeof(unsigned int), 1);
00404 wrt(fp, &(d->gconst), sizeof(LOGPROB), 1);
00405 }
00406 j_printf("%d gaussian densities written\n", dens_num);
00407 }
00408
00416 static unsigned int
00417 search_did(HTK_HMM_Dens *d)
00418 {
00419 unsigned int left = 0;
00420 unsigned int right = dens_num - 1;
00421 unsigned int mid;
00422
00423 while (left < right) {
00424 mid = (left + right) / 2;
00425 if (dens_index[mid] < d) {
00426 left = mid + 1;
00427 } else {
00428 right = mid;
00429 }
00430 }
00431 return(left);
00432 }
00433
00434
00435
00436 static GCODEBOOK **tm_index;
00437 static unsigned int tm_num;
00438 static unsigned int tm_idx;
00439
00445 static void
00446 tmix_list_callback(void *p)
00447 {
00448 GCODEBOOK *tm;
00449 tm = p;
00450 tm_index[tm_idx++] = tm;
00451 }
00452
00462 static int
00463 qsort_tm_index(GCODEBOOK **tm1, GCODEBOOK **tm2)
00464 {
00465 if (*tm1 > *tm2) return 1;
00466 else if (*tm1 < *tm2) return -1;
00467 else return 0;
00468 }
00469
00483 static void
00484 wt_tmix(FILE *fp, HTK_HMM_INFO *hmm)
00485 {
00486 GCODEBOOK *tm;
00487 unsigned int idx;
00488 unsigned int did;
00489 int i;
00490
00491 tm_num = hmm->codebooknum;
00492 tm_index = (GCODEBOOK **)mymalloc(sizeof(GCODEBOOK *) * tm_num);
00493 tm_idx = 0;
00494 aptree_traverse_and_do(hmm->codebook_root, tmix_list_callback);
00495 qsort(tm_index, tm_num, sizeof(GCODEBOOK *), (int (*)(const void *, const void *))qsort_tm_index);
00496
00497 wrt(fp, &tm_num, sizeof(unsigned int), 1);
00498 for (idx = 0; idx < tm_num; idx++) {
00499 tm = tm_index[idx];
00500 wrt_str(fp, tm->name);
00501 wrt(fp, &(tm->num), sizeof(int), 1);
00502 for(i=0;i<tm->num;i++) {
00503 if (tm->d[i] == NULL) {
00504 did = dens_num;
00505 } else {
00506 did = search_did(tm->d[i]);
00507
00508 if (tm->d[i] != dens_index[did]) j_error("index not match!!! dens\n");
00509 }
00510 wrt(fp, &did, sizeof(unsigned int), 1);
00511 }
00512 }
00513 j_printf("%d tied-mixture codebooks written\n", tm_num);
00514 }
00515
00523 static unsigned int
00524 search_tmid(GCODEBOOK *tm)
00525 {
00526 unsigned int left = 0;
00527 unsigned int right = tm_num - 1;
00528 unsigned int mid;
00529
00530 while (left < right) {
00531 mid = (left + right) / 2;
00532 if (tm_index[mid] < tm) {
00533 left = mid + 1;
00534 } else {
00535 right = mid;
00536 }
00537 }
00538 return(left);
00539 }
00540
00541
00542
00543 static HTK_HMM_State **st_index;
00544 static unsigned int st_num;
00545
00555 static int
00556 qsort_st_index(HTK_HMM_State **s1, HTK_HMM_State **s2)
00557 {
00558 if (*s1 > *s2) return 1;
00559 else if (*s1 < *s2) return -1;
00560 else return 0;
00561 }
00562
00576 static void
00577 wt_state(FILE *fp, HTK_HMM_INFO *hmm)
00578 {
00579 HTK_HMM_State *s;
00580 unsigned int idx;
00581 unsigned int did;
00582 int i;
00583 short dummy;
00584
00585 st_num = hmm->totalstatenum;
00586 st_index = (HTK_HMM_State **)mymalloc(sizeof(HTK_HMM_State *) * st_num);
00587 idx = 0;
00588 for(s = hmm->ststart; s; s = s->next) st_index[idx++] = s;
00589 qsort(st_index, st_num, sizeof(HTK_HMM_State *), (int (*)(const void *, const void *))qsort_st_index);
00590
00591 wrt(fp, &st_num, sizeof(unsigned int), 1);
00592 for (idx = 0; idx < st_num; idx++) {
00593 s = st_index[idx];
00594 wrt_str(fp, s->name);
00595 if (hmm->is_tied_mixture) {
00596
00597 did = search_tmid((GCODEBOOK *)(s->b));
00598 if ((GCODEBOOK *)s->b == tm_index[did]) {
00599
00600 dummy = -1;
00601 wrt(fp, &dummy, sizeof(short), 1);
00602 wrt(fp, &did, sizeof(unsigned int), 1);
00603 } else {
00604
00605 wrt(fp, &(s->mix_num), sizeof(short), 1);
00606 for (i=0;i<s->mix_num;i++) {
00607 if (s->b[i] == NULL) {
00608 did = dens_num;
00609 } else {
00610 did = search_did(s->b[i]);
00611 if (s->b[i] != dens_index[did]) {
00612 j_error("index not match!!!");
00613 }
00614 }
00615 wrt(fp, &did, sizeof(unsigned int), 1);
00616 }
00617 }
00618 } else {
00619 wrt(fp, &(s->mix_num), sizeof(short), 1);
00620 for (i=0;i<s->mix_num;i++) {
00621 if (s->b[i] == NULL) {
00622 did = dens_num;
00623 } else {
00624 did = search_did(s->b[i]);
00625 if (s->b[i] != dens_index[did]) {
00626 j_error("index not match!!!");
00627 }
00628 }
00629 wrt(fp, &did, sizeof(unsigned int), 1);
00630 }
00631 }
00632 wrt(fp, s->bweight, sizeof(PROB), s->mix_num);
00633 }
00634 j_printf("%d states written\n", st_num);
00635 }
00636
00644 static unsigned int
00645 search_stid(HTK_HMM_State *s)
00646 {
00647 unsigned int left = 0;
00648 unsigned int right = st_num - 1;
00649 unsigned int mid;
00650
00651 while (left < right) {
00652 mid = (left + right) / 2;
00653 if (st_index[mid] < s) {
00654 left = mid + 1;
00655 } else {
00656 right = mid;
00657 }
00658 }
00659 return(left);
00660 }
00661
00662
00674 static void
00675 wt_data(FILE *fp, HTK_HMM_INFO *hmm)
00676 {
00677 HTK_HMM_Data *d;
00678 unsigned int md_num;
00679 unsigned int sid, tid;
00680 int i;
00681
00682 md_num = hmm->totalhmmnum;
00683
00684 wrt(fp, &(md_num), sizeof(unsigned int), 1);
00685 for(d = hmm->start; d; d = d->next) {
00686 wrt_str(fp, d->name);
00687 wrt(fp, &(d->state_num), sizeof(short), 1);
00688 for (i=0;i<d->state_num;i++) {
00689 if (d->s[i] != NULL) {
00690 sid = search_stid(d->s[i]);
00691
00692 if (d->s[i] != st_index[sid]) j_error("index not match!!! data state\n");
00693 } else {
00694 sid = hmm->totalstatenum + 1;
00695 }
00696 wrt(fp, &sid, sizeof(unsigned int), 1);
00697 }
00698 tid = search_trid(d->tr);
00699
00700 if (d->tr != tr_index[tid]) j_error("index not match!!! data trans\n");
00701 wrt(fp, &tid, sizeof(unsigned int), 1);
00702 }
00703 j_printf("%d HMM model definition written\n", md_num);
00704 }
00705
00706
00716 boolean
00717 write_binhmm(FILE *fp, HTK_HMM_INFO *hmm, Value *para)
00718 {
00719
00720
00721 wt_header(fp, (para ? TRUE : FALSE), hmm->variance_inversed);
00722
00723 if (para) {
00724
00725 wt_para(fp, para);
00726 }
00727
00728
00729 wt_opt(fp, &(hmm->opt));
00730
00731
00732 wt_type(fp, hmm);
00733
00734
00735 wt_trans(fp, hmm);
00736
00737
00738 wt_var(fp, hmm);
00739
00740
00741 wt_dens(fp, hmm);
00742
00743
00744 if (hmm->is_tied_mixture) {
00745 wt_tmix(fp, hmm);
00746 }
00747
00748
00749 wt_state(fp, hmm);
00750
00751
00752 wt_data(fp, hmm);
00753
00754
00755 free(tr_index);
00756 free(vr_index);
00757 free(dens_index);
00758 if (hmm->is_tied_mixture) free(tm_index);
00759 free(st_index);
00760
00761 return (TRUE);
00762 }