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
00039
00048 static void
00049 wrt(FILE *fp, void *buf, size_t unitbyte, int unitnum)
00050 {
00051 #ifndef WORDS_BIGENDIAN
00052 if (unitbyte != 1) {
00053 swap_bytes((char *)buf, unitbyte, unitnum);
00054 }
00055 #endif
00056 if (myfwrite(buf, unitbyte, unitnum, fp) < unitnum) {
00057 perror("write_binhmm: wrt");
00058 j_error("write failed\n");
00059 }
00060 #ifndef WORDS_BIGENDIAN
00061 if (unitbyte != 1) {
00062 swap_bytes((char *)buf, unitbyte, unitnum);
00063 }
00064 #endif
00065 }
00066
00073 static void
00074 wrt_str(FILE *fp, char *str)
00075 {
00076 static char noname = '\0';
00077
00078 if (str) {
00079 wrt(fp, str, sizeof(char), strlen(str)+1);
00080 } else {
00081 wrt(fp, &noname, sizeof(char), 1);
00082 }
00083 }
00084
00085
00086 static char *binhmm_header = BINHMM_HEADER;
00087
00092 static void
00093 wt_header(FILE *fp)
00094 {
00095 wrt_str(fp, binhmm_header);
00096 }
00097
00098
00105 static void
00106 wt_opt(FILE *fp, HTK_HMM_Options *opt)
00107 {
00108 wrt(fp, &(opt->stream_info.num), sizeof(short), 1);
00109 wrt(fp, opt->stream_info.vsize, sizeof(short), 50);
00110 wrt(fp, &(opt->vec_size), sizeof(short), 1);
00111 wrt(fp, &(opt->cov_type), sizeof(short), 1);
00112 wrt(fp, &(opt->dur_type), sizeof(short), 1);
00113 wrt(fp, &(opt->param_type), sizeof(short), 1);
00114 }
00115
00122 static void
00123 wt_type(FILE *fp, HTK_HMM_INFO *hmm)
00124 {
00125 wrt(fp, &(hmm->is_tied_mixture), sizeof(boolean), 1);
00126 wrt(fp, &(hmm->maxmixturenum), sizeof(int), 1);
00127 }
00128
00129
00130
00131 static HTK_HMM_Trans **tr_index;
00132 static unsigned int tr_num;
00133
00143 static int
00144 qsort_tr_index(HTK_HMM_Trans **t1, HTK_HMM_Trans **t2)
00145 {
00146 if (*t1 > *t2) return 1;
00147 else if (*t1 < *t2) return -1;
00148 else return 0;
00149 }
00150
00162 static void
00163 wt_trans(FILE *fp, HTK_HMM_INFO *hmm)
00164 {
00165 HTK_HMM_Trans *t;
00166 unsigned int idx;
00167 int i;
00168
00169 tr_num = 0;
00170 for(t = hmm->trstart; t; t = t->next) tr_num++;
00171 tr_index = (HTK_HMM_Trans **)mymalloc(sizeof(HTK_HMM_Trans *) * tr_num);
00172 idx = 0;
00173 for(t = hmm->trstart; t; t = t->next) tr_index[idx++] = t;
00174 qsort(tr_index, tr_num, sizeof(HTK_HMM_Trans *), (int (*)(const void *, const void *))qsort_tr_index);
00175
00176 wrt(fp, &tr_num, sizeof(unsigned int), 1);
00177 for (idx = 0; idx < tr_num; idx++) {
00178 t = tr_index[idx];
00179 wrt_str(fp, t->name);
00180 wrt(fp, &(t->statenum), sizeof(short), 1);
00181 for(i=0;i<t->statenum;i++) {
00182 wrt(fp, t->a[i], sizeof(PROB), t->statenum);
00183 }
00184 }
00185
00186 j_printf("%d transition maxtix written\n", tr_num);
00187 }
00188
00196 static unsigned int
00197 search_trid(HTK_HMM_Trans *t)
00198 {
00199 unsigned int left = 0;
00200 unsigned int right = tr_num - 1;
00201 unsigned int mid;
00202
00203 while (left < right) {
00204 mid = (left + right) / 2;
00205 if (tr_index[mid] < t) {
00206 left = mid + 1;
00207 } else {
00208 right = mid;
00209 }
00210 }
00211 return(left);
00212 }
00213
00214
00215
00216 static HTK_HMM_Var **vr_index;
00217 static unsigned int vr_num;
00218
00228 static int
00229 qsort_vr_index(HTK_HMM_Var **v1, HTK_HMM_Var **v2)
00230 {
00231 if (*v1 > *v2) return 1;
00232 else if (*v1 < *v2) return -1;
00233 else return 0;
00234 }
00235
00247 static void
00248 wt_var(FILE *fp, HTK_HMM_INFO *hmm)
00249 {
00250 HTK_HMM_Var *v;
00251 unsigned int idx;
00252
00253 vr_num = 0;
00254 for(v = hmm->vrstart; v; v = v->next) vr_num++;
00255 vr_index = (HTK_HMM_Var **)mymalloc(sizeof(HTK_HMM_Var *) * vr_num);
00256 idx = 0;
00257 for(v = hmm->vrstart; v; v = v->next) vr_index[idx++] = v;
00258 qsort(vr_index, vr_num, sizeof(HTK_HMM_Var *), (int (*)(const void *, const void *))qsort_vr_index);
00259
00260 wrt(fp, &vr_num, sizeof(unsigned int), 1);
00261 for (idx = 0; idx < vr_num; idx++) {
00262 v = vr_index[idx];
00263 wrt_str(fp, v->name);
00264 wrt(fp, &(v->len), sizeof(short), 1);
00265 wrt(fp, v->vec, sizeof(VECT), v->len);
00266 }
00267 j_printf("%d variance written\n", vr_num);
00268 }
00269
00277 static unsigned int
00278 search_vid(HTK_HMM_Var *v)
00279 {
00280 unsigned int left = 0;
00281 unsigned int right = vr_num - 1;
00282 unsigned int mid;
00283
00284 while (left < right) {
00285 mid = (left + right) / 2;
00286 if (vr_index[mid] < v) {
00287 left = mid + 1;
00288 } else {
00289 right = mid;
00290 }
00291 }
00292 return(left);
00293 }
00294
00295
00296
00297 static HTK_HMM_Dens **dens_index;
00298 static unsigned int dens_num;
00299
00309 static int
00310 qsort_dens_index(HTK_HMM_Dens **d1, HTK_HMM_Dens **d2)
00311 {
00312 if (*d1 > *d2) return 1;
00313 else if (*d1 < *d2) return -1;
00314 else return 0;
00315 }
00316
00330 static void
00331 wt_dens(FILE *fp, HTK_HMM_INFO *hmm)
00332 {
00333 HTK_HMM_Dens *d;
00334 unsigned int idx;
00335 unsigned int vid;
00336
00337 dens_num = hmm->totalmixnum;
00338 dens_index = (HTK_HMM_Dens **)mymalloc(sizeof(HTK_HMM_Dens *) * dens_num);
00339 idx = 0;
00340 for(d = hmm->dnstart; d; d = d->next) dens_index[idx++] = d;
00341 qsort(dens_index, dens_num, sizeof(HTK_HMM_Dens *), (int (*)(const void *, const void *))qsort_dens_index);
00342
00343 wrt(fp, &dens_num, sizeof(unsigned int), 1);
00344 for (idx = 0; idx < dens_num; idx++) {
00345 d = dens_index[idx];
00346 wrt_str(fp, d->name);
00347 wrt(fp, &(d->meanlen), sizeof(short), 1);
00348 wrt(fp, d->mean, sizeof(VECT), d->meanlen);
00349 vid = search_vid(d->var);
00350
00351 if (d->var != vr_index[vid]) j_error("index not match!!! dens\n");
00352 wrt(fp, &vid, sizeof(unsigned int), 1);
00353 wrt(fp, &(d->gconst), sizeof(LOGPROB), 1);
00354 }
00355 j_printf("%d gaussian densities written\n", dens_num);
00356 }
00357
00365 static unsigned int
00366 search_did(HTK_HMM_Dens *d)
00367 {
00368 unsigned int left = 0;
00369 unsigned int right = dens_num - 1;
00370 unsigned int mid;
00371
00372 while (left < right) {
00373 mid = (left + right) / 2;
00374 if (dens_index[mid] < d) {
00375 left = mid + 1;
00376 } else {
00377 right = mid;
00378 }
00379 }
00380 return(left);
00381 }
00382
00383
00384
00385 static GCODEBOOK **tm_index;
00386 static unsigned int tm_num;
00387 static unsigned int tm_idx;
00388
00394 static void
00395 tmix_list_callback(void *p)
00396 {
00397 GCODEBOOK *tm;
00398 tm = p;
00399 tm_index[tm_idx++] = tm;
00400 }
00401
00411 static int
00412 qsort_tm_index(GCODEBOOK **tm1, GCODEBOOK **tm2)
00413 {
00414 if (*tm1 > *tm2) return 1;
00415 else if (*tm1 < *tm2) return -1;
00416 else return 0;
00417 }
00418
00432 static void
00433 wt_tmix(FILE *fp, HTK_HMM_INFO *hmm)
00434 {
00435 GCODEBOOK *tm;
00436 unsigned int idx;
00437 unsigned int did;
00438 int i;
00439
00440 tm_num = hmm->codebooknum;
00441 tm_index = (GCODEBOOK **)mymalloc(sizeof(GCODEBOOK *) * tm_num);
00442 tm_idx = 0;
00443 aptree_traverse_and_do(hmm->codebook_root, tmix_list_callback);
00444 qsort(tm_index, tm_num, sizeof(GCODEBOOK *), (int (*)(const void *, const void *))qsort_tm_index);
00445
00446 wrt(fp, &tm_num, sizeof(unsigned int), 1);
00447 for (idx = 0; idx < tm_num; idx++) {
00448 tm = tm_index[idx];
00449 wrt_str(fp, tm->name);
00450 wrt(fp, &(tm->num), sizeof(int), 1);
00451 for(i=0;i<tm->num;i++) {
00452 if (tm->d[i] == NULL) {
00453 did = dens_num;
00454 } else {
00455 did = search_did(tm->d[i]);
00456
00457 if (tm->d[i] != dens_index[did]) j_error("index not match!!! dens\n");
00458 }
00459 wrt(fp, &did, sizeof(unsigned int), 1);
00460 }
00461 }
00462 j_printf("%d tied-mixture codebooks written\n", tm_num);
00463 }
00464
00472 static unsigned int
00473 search_tmid(GCODEBOOK *tm)
00474 {
00475 unsigned int left = 0;
00476 unsigned int right = tm_num - 1;
00477 unsigned int mid;
00478
00479 while (left < right) {
00480 mid = (left + right) / 2;
00481 if (tm_index[mid] < tm) {
00482 left = mid + 1;
00483 } else {
00484 right = mid;
00485 }
00486 }
00487 return(left);
00488 }
00489
00490
00491
00492 static HTK_HMM_State **st_index;
00493 static unsigned int st_num;
00494
00504 static int
00505 qsort_st_index(HTK_HMM_State **s1, HTK_HMM_State **s2)
00506 {
00507 if (*s1 > *s2) return 1;
00508 else if (*s1 < *s2) return -1;
00509 else return 0;
00510 }
00511
00525 static void
00526 wt_state(FILE *fp, HTK_HMM_INFO *hmm)
00527 {
00528 HTK_HMM_State *s;
00529 unsigned int idx;
00530 unsigned int did;
00531 int i;
00532 short dummy;
00533
00534 st_num = hmm->totalstatenum;
00535 st_index = (HTK_HMM_State **)mymalloc(sizeof(HTK_HMM_State *) * st_num);
00536 idx = 0;
00537 for(s = hmm->ststart; s; s = s->next) st_index[idx++] = s;
00538 qsort(st_index, st_num, sizeof(HTK_HMM_State *), (int (*)(const void *, const void *))qsort_st_index);
00539
00540 wrt(fp, &st_num, sizeof(unsigned int), 1);
00541 for (idx = 0; idx < st_num; idx++) {
00542 s = st_index[idx];
00543 wrt_str(fp, s->name);
00544 if (hmm->is_tied_mixture) {
00545
00546 did = search_tmid((GCODEBOOK *)(s->b));
00547 if ((GCODEBOOK *)s->b == tm_index[did]) {
00548
00549 dummy = -1;
00550 wrt(fp, &dummy, sizeof(short), 1);
00551 wrt(fp, &did, sizeof(unsigned int), 1);
00552 } else {
00553
00554 wrt(fp, &(s->mix_num), sizeof(short), 1);
00555 for (i=0;i<s->mix_num;i++) {
00556 if (s->b[i] == NULL) {
00557 did = dens_num;
00558 } else {
00559 did = search_did(s->b[i]);
00560 if (s->b[i] != dens_index[did]) {
00561 j_error("index not match!!!");
00562 }
00563 }
00564 wrt(fp, &did, sizeof(unsigned int), 1);
00565 }
00566 }
00567 } else {
00568 wrt(fp, &(s->mix_num), sizeof(short), 1);
00569 for (i=0;i<s->mix_num;i++) {
00570 if (s->b[i] == NULL) {
00571 did = dens_num;
00572 } else {
00573 did = search_did(s->b[i]);
00574 if (s->b[i] != dens_index[did]) {
00575 j_error("index not match!!!");
00576 }
00577 }
00578 wrt(fp, &did, sizeof(unsigned int), 1);
00579 }
00580 }
00581 wrt(fp, s->bweight, sizeof(PROB), s->mix_num);
00582 }
00583 j_printf("%d states written\n", st_num);
00584 }
00585
00593 static unsigned int
00594 search_stid(HTK_HMM_State *s)
00595 {
00596 unsigned int left = 0;
00597 unsigned int right = st_num - 1;
00598 unsigned int mid;
00599
00600 while (left < right) {
00601 mid = (left + right) / 2;
00602 if (st_index[mid] < s) {
00603 left = mid + 1;
00604 } else {
00605 right = mid;
00606 }
00607 }
00608 return(left);
00609 }
00610
00611
00623 static void
00624 wt_data(FILE *fp, HTK_HMM_INFO *hmm)
00625 {
00626 HTK_HMM_Data *d;
00627 unsigned int md_num;
00628 unsigned int sid, tid;
00629 int i;
00630
00631 md_num = hmm->totalhmmnum;
00632
00633 wrt(fp, &(md_num), sizeof(unsigned int), 1);
00634 for(d = hmm->start; d; d = d->next) {
00635 wrt_str(fp, d->name);
00636 wrt(fp, &(d->state_num), sizeof(short), 1);
00637 for (i=0;i<d->state_num;i++) {
00638 if (d->s[i] != NULL) {
00639 sid = search_stid(d->s[i]);
00640
00641 if (d->s[i] != st_index[sid]) j_error("index not match!!! data state\n");
00642 } else {
00643 sid = hmm->totalstatenum + 1;
00644 }
00645 wrt(fp, &sid, sizeof(unsigned int), 1);
00646 }
00647 tid = search_trid(d->tr);
00648
00649 if (d->tr != tr_index[tid]) j_error("index not match!!! data trans\n");
00650 wrt(fp, &tid, sizeof(unsigned int), 1);
00651 }
00652 j_printf("%d HMM model definition written\n", md_num);
00653 }
00654
00655
00664 boolean
00665 write_binhmm(FILE *fp, HTK_HMM_INFO *hmm)
00666 {
00667
00668 wt_header(fp);
00669
00670
00671 wt_opt(fp, &(hmm->opt));
00672
00673
00674 wt_type(fp, hmm);
00675
00676
00677 wt_trans(fp, hmm);
00678
00679
00680 wt_var(fp, hmm);
00681
00682
00683 wt_dens(fp, hmm);
00684
00685
00686 if (hmm->is_tied_mixture) {
00687 wt_tmix(fp, hmm);
00688 }
00689
00690
00691 wt_state(fp, hmm);
00692
00693
00694 wt_data(fp, hmm);
00695
00696
00697 free(tr_index);
00698 free(vr_index);
00699 free(dens_index);
00700 if (hmm->is_tied_mixture) free(tm_index);
00701 free(st_index);
00702
00703 return (TRUE);
00704 }