00001
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <sent/stddefs.h>
00037 #include <sent/htk_param.h>
00038 #include <sent/htk_hmm.h>
00039 #include <sent/mfcc.h>
00040
00041 #define wrt(A,B,C,D) if (wrtfunc(A,B,C,D) == FALSE) return FALSE
00042 #define wrt_str(A,B) if (wrt_strfunc(A,B) == FALSE) return FALSE
00043
00044
00053 static boolean
00054 wrtfunc(FILE *fp, void *buf, size_t unitbyte, size_t unitnum)
00055 {
00056 #ifndef WORDS_BIGENDIAN
00057 if (unitbyte != 1) {
00058 swap_bytes((char *)buf, unitbyte, unitnum);
00059 }
00060 #endif
00061 if (myfwrite(buf, unitbyte, unitnum, fp) < unitnum) {
00062 jlog("Error: write_binhmm: failed to write %d bytes", unitbyte * unitnum);
00063 return FALSE;
00064 }
00065 #ifndef WORDS_BIGENDIAN
00066 if (unitbyte != 1) {
00067 swap_bytes((char *)buf, unitbyte, unitnum);
00068 }
00069 #endif
00070 return TRUE;
00071 }
00072
00079 static boolean
00080 wrt_strfunc(FILE *fp, char *str)
00081 {
00082 static char noname = '\0';
00083 boolean ret;
00084
00085 if (str) {
00086 ret = wrtfunc(fp, str, sizeof(char), strlen(str)+1);
00087 } else {
00088 ret = wrtfunc(fp, &noname, sizeof(char), 1);
00089 }
00090 return ret;
00091 }
00092
00093
00094 static char *binhmm_header_v2 = BINHMM_HEADER_V2;
00095
00101 static boolean
00102 wt_header(FILE *fp, boolean emp, boolean inv)
00103 {
00104 char buf[50];
00105 char *p;
00106
00107 wrt_str(fp, binhmm_header_v2);
00108 p = &(buf[0]);
00109 if (emp) {
00110 *p++ = '_';
00111 *p++ = BINHMM_HEADER_V2_EMBEDPARA;
00112 }
00113 if (inv) {
00114 *p++ = '_';
00115 *p++ = BINHMM_HEADER_V2_VARINV;
00116 }
00117 *p = '\0';
00118 wrt_str(fp, buf);
00119
00120 return TRUE;
00121 }
00122
00123
00130 static boolean
00131 wt_para(FILE *fp, Value *para)
00132 {
00133 short version;
00134
00135 version = VALUE_VERSION;
00136 wrt(fp, &version, sizeof(short), 1);
00137
00138 wrt(fp, &(para->smp_period), sizeof(long), 1);
00139 wrt(fp, &(para->smp_freq), sizeof(long), 1);
00140 wrt(fp, &(para->framesize), sizeof(int), 1);
00141 wrt(fp, &(para->frameshift), sizeof(int), 1);
00142 wrt(fp, &(para->preEmph), sizeof(float), 1);
00143 wrt(fp, &(para->lifter), sizeof(int), 1);
00144 wrt(fp, &(para->fbank_num), sizeof(int), 1);
00145 wrt(fp, &(para->delWin), sizeof(int), 1);
00146 wrt(fp, &(para->accWin), sizeof(int), 1);
00147 wrt(fp, &(para->silFloor), sizeof(float), 1);
00148 wrt(fp, &(para->escale), sizeof(float), 1);
00149 wrt(fp, &(para->hipass), sizeof(int), 1);
00150 wrt(fp, &(para->lopass), sizeof(int), 1);
00151 wrt(fp, &(para->enormal), sizeof(int), 1);
00152 wrt(fp, &(para->raw_e), sizeof(int), 1);
00153 wrt(fp, &(para->zmeanframe), sizeof(int), 1);
00154
00155 return TRUE;
00156 }
00157
00158
00165 static boolean
00166 wt_opt(FILE *fp, HTK_HMM_Options *opt)
00167 {
00168 wrt(fp, &(opt->stream_info.num), sizeof(short), 1);
00169 wrt(fp, opt->stream_info.vsize, sizeof(short), 50);
00170 wrt(fp, &(opt->vec_size), sizeof(short), 1);
00171 wrt(fp, &(opt->cov_type), sizeof(short), 1);
00172 wrt(fp, &(opt->dur_type), sizeof(short), 1);
00173 wrt(fp, &(opt->param_type), sizeof(short), 1);
00174 return TRUE;
00175 }
00176
00183 static boolean
00184 wt_type(FILE *fp, HTK_HMM_INFO *hmm)
00185 {
00186 wrt(fp, &(hmm->is_tied_mixture), sizeof(boolean), 1);
00187 wrt(fp, &(hmm->maxmixturenum), sizeof(int), 1);
00188 return TRUE;
00189 }
00190
00191
00192
00193 static HTK_HMM_Trans **tr_index;
00194 static unsigned int tr_num;
00195
00205 static int
00206 qsort_tr_index(HTK_HMM_Trans **t1, HTK_HMM_Trans **t2)
00207 {
00208 if (*t1 > *t2) return 1;
00209 else if (*t1 < *t2) return -1;
00210 else return 0;
00211 }
00212
00224 static boolean
00225 wt_trans(FILE *fp, HTK_HMM_INFO *hmm)
00226 {
00227 HTK_HMM_Trans *t;
00228 unsigned int idx;
00229 int i;
00230
00231 tr_num = 0;
00232 for(t = hmm->trstart; t; t = t->next) tr_num++;
00233 tr_index = (HTK_HMM_Trans **)mymalloc(sizeof(HTK_HMM_Trans *) * tr_num);
00234 idx = 0;
00235 for(t = hmm->trstart; t; t = t->next) tr_index[idx++] = t;
00236 qsort(tr_index, tr_num, sizeof(HTK_HMM_Trans *), (int (*)(const void *, const void *))qsort_tr_index);
00237
00238 wrt(fp, &tr_num, sizeof(unsigned int), 1);
00239 for (idx = 0; idx < tr_num; idx++) {
00240 t = tr_index[idx];
00241 wrt_str(fp, t->name);
00242 wrt(fp, &(t->statenum), sizeof(short), 1);
00243 for(i=0;i<t->statenum;i++) {
00244 wrt(fp, t->a[i], sizeof(PROB), t->statenum);
00245 }
00246 }
00247
00248 jlog("Stat: write_binhmm: %d transition maxtix written\n", tr_num);
00249
00250 return TRUE;
00251 }
00252
00260 static unsigned int
00261 search_trid(HTK_HMM_Trans *t)
00262 {
00263 unsigned int left = 0;
00264 unsigned int right = tr_num - 1;
00265 unsigned int mid;
00266
00267 while (left < right) {
00268 mid = (left + right) / 2;
00269 if (tr_index[mid] < t) {
00270 left = mid + 1;
00271 } else {
00272 right = mid;
00273 }
00274 }
00275 return(left);
00276 }
00277
00278
00279
00280 static HTK_HMM_Var **vr_index;
00281 static unsigned int vr_num;
00282
00292 static int
00293 qsort_vr_index(HTK_HMM_Var **v1, HTK_HMM_Var **v2)
00294 {
00295 if (*v1 > *v2) return 1;
00296 else if (*v1 < *v2) return -1;
00297 else return 0;
00298 }
00299
00311 static boolean
00312 wt_var(FILE *fp, HTK_HMM_INFO *hmm)
00313 {
00314 HTK_HMM_Var *v;
00315 unsigned int idx;
00316
00317 vr_num = 0;
00318 for(v = hmm->vrstart; v; v = v->next) vr_num++;
00319 vr_index = (HTK_HMM_Var **)mymalloc(sizeof(HTK_HMM_Var *) * vr_num);
00320 idx = 0;
00321 for(v = hmm->vrstart; v; v = v->next) vr_index[idx++] = v;
00322 qsort(vr_index, vr_num, sizeof(HTK_HMM_Var *), (int (*)(const void *, const void *))qsort_vr_index);
00323
00324 wrt(fp, &vr_num, sizeof(unsigned int), 1);
00325 for (idx = 0; idx < vr_num; idx++) {
00326 v = vr_index[idx];
00327 wrt_str(fp, v->name);
00328 wrt(fp, &(v->len), sizeof(short), 1);
00329 wrt(fp, v->vec, sizeof(VECT), v->len);
00330 }
00331 jlog("Stat: write_binhmm: %d variance written\n", vr_num);
00332
00333 return TRUE;
00334 }
00335
00343 static unsigned int
00344 search_vid(HTK_HMM_Var *v)
00345 {
00346 unsigned int left = 0;
00347 unsigned int right = vr_num - 1;
00348 unsigned int mid;
00349
00350 while (left < right) {
00351 mid = (left + right) / 2;
00352 if (vr_index[mid] < v) {
00353 left = mid + 1;
00354 } else {
00355 right = mid;
00356 }
00357 }
00358 return(left);
00359 }
00360
00361
00362
00363 static HTK_HMM_Dens **dens_index;
00364 static unsigned int dens_num;
00365
00375 static int
00376 qsort_dens_index(HTK_HMM_Dens **d1, HTK_HMM_Dens **d2)
00377 {
00378 if (*d1 > *d2) return 1;
00379 else if (*d1 < *d2) return -1;
00380 else return 0;
00381 }
00382
00396 static boolean
00397 wt_dens(FILE *fp, HTK_HMM_INFO *hmm)
00398 {
00399 HTK_HMM_Dens *d;
00400 unsigned int idx;
00401 unsigned int vid;
00402
00403 dens_num = hmm->totalmixnum;
00404 dens_index = (HTK_HMM_Dens **)mymalloc(sizeof(HTK_HMM_Dens *) * dens_num);
00405 idx = 0;
00406 for(d = hmm->dnstart; d; d = d->next) dens_index[idx++] = d;
00407 qsort(dens_index, dens_num, sizeof(HTK_HMM_Dens *), (int (*)(const void *, const void *))qsort_dens_index);
00408
00409 wrt(fp, &dens_num, sizeof(unsigned int), 1);
00410 for (idx = 0; idx < dens_num; idx++) {
00411 d = dens_index[idx];
00412 wrt_str(fp, d->name);
00413 wrt(fp, &(d->meanlen), sizeof(short), 1);
00414 wrt(fp, d->mean, sizeof(VECT), d->meanlen);
00415 vid = search_vid(d->var);
00416
00417 if (d->var != vr_index[vid]) {
00418 jlog("Error: write_binhmm: index not match!!!\n");
00419 return FALSE;
00420 }
00421 wrt(fp, &vid, sizeof(unsigned int), 1);
00422 wrt(fp, &(d->gconst), sizeof(LOGPROB), 1);
00423 }
00424 jlog("Stat: write_binhmm: %d gaussian densities written\n", dens_num);
00425
00426 return TRUE;
00427 }
00428
00436 static unsigned int
00437 search_did(HTK_HMM_Dens *d)
00438 {
00439 unsigned int left = 0;
00440 unsigned int right = dens_num - 1;
00441 unsigned int mid;
00442
00443 while (left < right) {
00444 mid = (left + right) / 2;
00445 if (dens_index[mid] < d) {
00446 left = mid + 1;
00447 } else {
00448 right = mid;
00449 }
00450 }
00451 return(left);
00452 }
00453
00454
00455
00456 static GCODEBOOK **tm_index;
00457 static unsigned int tm_num;
00458 static unsigned int tm_idx;
00459
00465 static void
00466 tmix_list_callback(void *p)
00467 {
00468 GCODEBOOK *tm;
00469 tm = p;
00470 tm_index[tm_idx++] = tm;
00471 }
00472
00482 static int
00483 qsort_tm_index(GCODEBOOK **tm1, GCODEBOOK **tm2)
00484 {
00485 if (*tm1 > *tm2) return 1;
00486 else if (*tm1 < *tm2) return -1;
00487 else return 0;
00488 }
00489
00503 static boolean
00504 wt_tmix(FILE *fp, HTK_HMM_INFO *hmm)
00505 {
00506 GCODEBOOK *tm;
00507 unsigned int idx;
00508 unsigned int did;
00509 int i;
00510
00511 tm_num = hmm->codebooknum;
00512 tm_index = (GCODEBOOK **)mymalloc(sizeof(GCODEBOOK *) * tm_num);
00513 tm_idx = 0;
00514 aptree_traverse_and_do(hmm->codebook_root, tmix_list_callback);
00515 qsort(tm_index, tm_num, sizeof(GCODEBOOK *), (int (*)(const void *, const void *))qsort_tm_index);
00516
00517 wrt(fp, &tm_num, sizeof(unsigned int), 1);
00518 for (idx = 0; idx < tm_num; idx++) {
00519 tm = tm_index[idx];
00520 wrt_str(fp, tm->name);
00521 wrt(fp, &(tm->num), sizeof(int), 1);
00522 for(i=0;i<tm->num;i++) {
00523 if (tm->d[i] == NULL) {
00524 did = dens_num;
00525 } else {
00526 did = search_did(tm->d[i]);
00527
00528 if (tm->d[i] != dens_index[did]) {
00529 jlog("Error: write_binhmm: index not match!!!\n");
00530 return FALSE;
00531 }
00532 }
00533 wrt(fp, &did, sizeof(unsigned int), 1);
00534 }
00535 }
00536 jlog("Stat: write_binhmm: %d tied-mixture codebooks written\n", tm_num);
00537
00538 return TRUE;
00539 }
00540
00548 static unsigned int
00549 search_tmid(GCODEBOOK *tm)
00550 {
00551 unsigned int left = 0;
00552 unsigned int right = tm_num - 1;
00553 unsigned int mid;
00554
00555 while (left < right) {
00556 mid = (left + right) / 2;
00557 if (tm_index[mid] < tm) {
00558 left = mid + 1;
00559 } else {
00560 right = mid;
00561 }
00562 }
00563 return(left);
00564 }
00565
00566
00567
00568 static HTK_HMM_State **st_index;
00569 static unsigned int st_num;
00570
00580 static int
00581 qsort_st_index(HTK_HMM_State **s1, HTK_HMM_State **s2)
00582 {
00583 if (*s1 > *s2) return 1;
00584 else if (*s1 < *s2) return -1;
00585 else return 0;
00586 }
00587
00601 static boolean
00602 wt_state(FILE *fp, HTK_HMM_INFO *hmm)
00603 {
00604 HTK_HMM_State *s;
00605 unsigned int idx;
00606 unsigned int did;
00607 int i;
00608 short dummy;
00609
00610 st_num = hmm->totalstatenum;
00611 st_index = (HTK_HMM_State **)mymalloc(sizeof(HTK_HMM_State *) * st_num);
00612 idx = 0;
00613 for(s = hmm->ststart; s; s = s->next) st_index[idx++] = s;
00614 qsort(st_index, st_num, sizeof(HTK_HMM_State *), (int (*)(const void *, const void *))qsort_st_index);
00615
00616 wrt(fp, &st_num, sizeof(unsigned int), 1);
00617 for (idx = 0; idx < st_num; idx++) {
00618 s = st_index[idx];
00619 wrt_str(fp, s->name);
00620 if (hmm->is_tied_mixture) {
00621
00622 did = search_tmid((GCODEBOOK *)(s->b));
00623 if ((GCODEBOOK *)s->b == tm_index[did]) {
00624
00625 dummy = -1;
00626 wrt(fp, &dummy, sizeof(short), 1);
00627 wrt(fp, &did, sizeof(unsigned int), 1);
00628 } else {
00629
00630 wrt(fp, &(s->mix_num), sizeof(short), 1);
00631 for (i=0;i<s->mix_num;i++) {
00632 if (s->b[i] == NULL) {
00633 did = dens_num;
00634 } else {
00635 did = search_did(s->b[i]);
00636 if (s->b[i] != dens_index[did]) {
00637 jlog("Error: write_binhmm: index not match!!!\n");
00638 return FALSE;
00639 }
00640 }
00641 wrt(fp, &did, sizeof(unsigned int), 1);
00642 }
00643 }
00644 } else {
00645 wrt(fp, &(s->mix_num), sizeof(short), 1);
00646 for (i=0;i<s->mix_num;i++) {
00647 if (s->b[i] == NULL) {
00648 did = dens_num;
00649 } else {
00650 did = search_did(s->b[i]);
00651 if (s->b[i] != dens_index[did]) {
00652 jlog("Error: write_binhmm: index not match!!!\n");
00653 return FALSE;
00654 }
00655 }
00656 wrt(fp, &did, sizeof(unsigned int), 1);
00657 }
00658 }
00659 wrt(fp, s->bweight, sizeof(PROB), s->mix_num);
00660 }
00661 jlog("Stat: write_binhmm: %d states written\n", st_num);
00662
00663 return TRUE;
00664 }
00665
00673 static unsigned int
00674 search_stid(HTK_HMM_State *s)
00675 {
00676 unsigned int left = 0;
00677 unsigned int right = st_num - 1;
00678 unsigned int mid;
00679
00680 while (left < right) {
00681 mid = (left + right) / 2;
00682 if (st_index[mid] < s) {
00683 left = mid + 1;
00684 } else {
00685 right = mid;
00686 }
00687 }
00688 return(left);
00689 }
00690
00691
00703 static boolean
00704 wt_data(FILE *fp, HTK_HMM_INFO *hmm)
00705 {
00706 HTK_HMM_Data *d;
00707 unsigned int md_num;
00708 unsigned int sid, tid;
00709 int i;
00710
00711 md_num = hmm->totalhmmnum;
00712
00713 wrt(fp, &(md_num), sizeof(unsigned int), 1);
00714 for(d = hmm->start; d; d = d->next) {
00715 wrt_str(fp, d->name);
00716 wrt(fp, &(d->state_num), sizeof(short), 1);
00717 for (i=0;i<d->state_num;i++) {
00718 if (d->s[i] != NULL) {
00719 sid = search_stid(d->s[i]);
00720
00721 if (d->s[i] != st_index[sid]) {
00722 jlog("Error: write_binhmm: index not match!!!\n");
00723 return FALSE;
00724 }
00725 } else {
00726 sid = hmm->totalstatenum + 1;
00727 }
00728 wrt(fp, &sid, sizeof(unsigned int), 1);
00729 }
00730 tid = search_trid(d->tr);
00731
00732 if (d->tr != tr_index[tid]) {
00733 jlog("Error: write_binhmm: index not match!!!\n");
00734 return FALSE;
00735 }
00736 wrt(fp, &tid, sizeof(unsigned int), 1);
00737 }
00738 jlog("Stat: write_binhmm: %d HMM model definition written\n", md_num);
00739 return TRUE;
00740 }
00741
00742
00752 boolean
00753 write_binhmm(FILE *fp, HTK_HMM_INFO *hmm, Value *para)
00754 {
00755
00756
00757 if (wt_header(fp, (para ? TRUE : FALSE), hmm->variance_inversed) == FALSE) {
00758 jlog("Error: write_binhmm: failed to write header\n");
00759 return FALSE;
00760 }
00761
00762 if (para) {
00763
00764 if (wt_para(fp, para) == FALSE) {
00765 jlog("Error: write_binhmm: failed to write acoustic analysis parameters\n");
00766 return FALSE;
00767 }
00768 }
00769
00770
00771 if (wt_opt(fp, &(hmm->opt)) == FALSE) {
00772 jlog("Error: write_binhmm: failed to write option data\n");
00773 return FALSE;
00774 }
00775
00776
00777 if (wt_type(fp, hmm) == FALSE) {
00778 jlog("Error: write_binhmm: failed to write HMM type data\n");
00779 return FALSE;
00780 }
00781
00782
00783 if (wt_trans(fp, hmm) == FALSE) {
00784 jlog("Error: write_binhmm: failed to write HMM transition data\n");
00785 return FALSE;
00786 }
00787
00788
00789 if (wt_var(fp, hmm) == FALSE) {
00790 jlog("Error: write_binhmm: failed to write HMM variance data\n");
00791 return FALSE;
00792 }
00793
00794
00795 if (wt_dens(fp, hmm) == FALSE) {
00796 jlog("Error: write_binhmm: failed to write density data\n");
00797 return FALSE;
00798 }
00799
00800
00801 if (hmm->is_tied_mixture) {
00802 if (wt_tmix(fp, hmm) == FALSE) {
00803 jlog("Error: write_binhmm: failed to write tied-mixture codebook data\n");
00804 return FALSE;
00805 }
00806 }
00807
00808
00809 if (wt_state(fp, hmm) == FALSE) {
00810 jlog("Error: write_binhmm: failed to write HMM state data\n");
00811 return FALSE;
00812 }
00813
00814
00815 if (wt_data(fp, hmm) == FALSE) {
00816 jlog("Error: write_binhmm: failed to write HMM data\n");
00817 return FALSE;
00818 }
00819
00820
00821 free(tr_index);
00822 free(vr_index);
00823 free(dens_index);
00824 if (hmm->is_tied_mixture) free(tm_index);
00825 free(st_index);
00826
00827 return (TRUE);
00828 }