Julius 4.2
libsent/src/hmminfo/write_binhmm.c
説明を見る。
00001 
00028 /*
00029  * Copyright (c) 2003-2005 Shikano Lab., Nara Institute of Science and Technology
00030  * Copyright (c) 2005-2011 Julius project team, Nagoya Institute of Technology
00031  * All rights reserved
00032  */
00033 
00034 /* $Id: write_binhmm.c,v 1.5 2011/04/29 05:09:16 sumomo Exp $ */
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 
00057   if (unitnum == 0) return TRUE;
00058 
00059 #ifndef WORDS_BIGENDIAN
00060   if (unitbyte != 1) {
00061     swap_bytes((char *)buf, unitbyte, unitnum);
00062   }
00063 #endif
00064   if (myfwrite(buf, unitbyte, unitnum, fp) < unitnum) {
00065     jlog("Error: write_binhmm: failed to write %d bytes", unitbyte * unitnum);
00066     return FALSE;
00067   }
00068 #ifndef WORDS_BIGENDIAN
00069   if (unitbyte != 1) {
00070     swap_bytes((char *)buf, unitbyte, unitnum);
00071   }
00072 #endif
00073   return TRUE;
00074 }
00075 
00082 static boolean
00083 wrt_strfunc(FILE *fp, char *str)
00084 {
00085   static char noname = '\0';
00086   boolean ret;
00087   
00088   if (str) {
00089     ret = wrtfunc(fp, str, sizeof(char), strlen(str)+1);
00090   } else {
00091     ret = wrtfunc(fp, &noname, sizeof(char), 1);
00092   }
00093   return ret;
00094 }
00095 
00096 
00097 static char *binhmm_header_v2 = BINHMM_HEADER_V2; 
00098 
00107 static boolean
00108 wt_header(FILE *fp, boolean emp, boolean inv, boolean mpdfmacro)
00109 {
00110   char buf[50];
00111   char *p;
00112 
00113   wrt_str(fp, binhmm_header_v2);
00114   p = &(buf[0]);
00115   if (emp) {
00116     *p++ = '_';
00117     *p++ = BINHMM_HEADER_V2_EMBEDPARA;
00118   }
00119   if (inv) {
00120     *p++ = '_';
00121     *p++ = BINHMM_HEADER_V2_VARINV;
00122   }
00123   if (mpdfmacro) {
00124     *p++ = '_';
00125     *p++ = BINHMM_HEADER_V2_MPDFMACRO;
00126   }
00127   *p = '\0';
00128   wrt_str(fp, buf);
00129   jlog("Stat: write_binhmm: written header: \"%s%s\"\n", binhmm_header_v2, buf);
00130 
00131   return TRUE;
00132 }
00133 
00134 
00141 static boolean
00142 wt_para(FILE *fp, Value *para)
00143 {
00144   short version;
00145 
00146   version = VALUE_VERSION;
00147   wrt(fp, &version, sizeof(short), 1);
00148 
00149   wrt(fp, &(para->smp_period), sizeof(long), 1);      
00150   wrt(fp, &(para->smp_freq), sizeof(long), 1);  
00151   wrt(fp, &(para->framesize), sizeof(int), 1);        
00152   wrt(fp, &(para->frameshift), sizeof(int), 1);       
00153   wrt(fp, &(para->preEmph), sizeof(float), 1);        
00154   wrt(fp, &(para->lifter), sizeof(int), 1);           
00155   wrt(fp, &(para->fbank_num), sizeof(int), 1);        
00156   wrt(fp, &(para->delWin), sizeof(int), 1);           
00157   wrt(fp, &(para->accWin), sizeof(int), 1);           
00158   wrt(fp, &(para->silFloor), sizeof(float), 1);       
00159   wrt(fp, &(para->escale), sizeof(float), 1);         
00160   wrt(fp, &(para->hipass), sizeof(int), 1);             
00161   wrt(fp, &(para->lopass), sizeof(int), 1);             
00162   wrt(fp, &(para->enormal), sizeof(int), 1);          
00163   wrt(fp, &(para->raw_e), sizeof(int), 1);            
00164   wrt(fp, &(para->zmeanframe), sizeof(int), 1); 
00165   wrt(fp, &(para->usepower), sizeof(int), 1);
00166 
00167   return TRUE;
00168 }
00169 
00170 
00177 static boolean
00178 wt_opt(FILE *fp, HTK_HMM_Options *opt)
00179 {
00180   wrt(fp, &(opt->stream_info.num), sizeof(short), 1);
00181   wrt(fp, opt->stream_info.vsize, sizeof(short), MAXSTREAMNUM);
00182   wrt(fp, &(opt->vec_size), sizeof(short), 1);
00183   wrt(fp, &(opt->cov_type), sizeof(short), 1);
00184   wrt(fp, &(opt->dur_type), sizeof(short), 1);
00185   wrt(fp, &(opt->param_type), sizeof(short), 1);
00186   return TRUE;
00187 }
00188 
00195 static boolean
00196 wt_type(FILE *fp, HTK_HMM_INFO *hmm)
00197 {
00198   wrt(fp, &(hmm->is_tied_mixture), sizeof(boolean), 1);
00199   wrt(fp, &(hmm->maxmixturenum), sizeof(int), 1);
00200   return TRUE;
00201 }
00202 
00203 
00204 /* write transition data */
00205 static HTK_HMM_Trans **tr_index; 
00206 static unsigned int tr_num;     
00207 
00217 static int
00218 qsort_tr_index(HTK_HMM_Trans **t1, HTK_HMM_Trans **t2)
00219 {
00220   if (*t1 > *t2) return 1;
00221   else if (*t1 < *t2) return -1;
00222   else return 0;
00223 }
00224 
00236 static boolean
00237 wt_trans(FILE *fp, HTK_HMM_INFO *hmm)
00238 {
00239   HTK_HMM_Trans *t;
00240   unsigned int idx;
00241   int i;
00242 
00243   tr_num = 0;
00244   for(t = hmm->trstart; t; t = t->next) tr_num++;
00245   tr_index = (HTK_HMM_Trans **)mymalloc(sizeof(HTK_HMM_Trans *) * tr_num);
00246   idx = 0;
00247   for(t = hmm->trstart; t; t = t->next) tr_index[idx++] = t;
00248   qsort(tr_index, tr_num, sizeof(HTK_HMM_Trans *), (int (*)(const void *, const void *))qsort_tr_index);
00249   
00250   wrt(fp, &tr_num, sizeof(unsigned int), 1);
00251   for (idx = 0; idx < tr_num; idx++) {
00252     t = tr_index[idx];
00253     wrt_str(fp, t->name);
00254     wrt(fp, &(t->statenum), sizeof(short), 1);
00255     for(i=0;i<t->statenum;i++) {
00256       wrt(fp, t->a[i], sizeof(PROB), t->statenum);
00257     }
00258   }
00259 
00260   jlog("Stat: write_binhmm: %d transition maxtix written\n", tr_num);
00261 
00262   return TRUE;
00263 }
00264 
00272 static unsigned int
00273 search_trid(HTK_HMM_Trans *t)
00274 {
00275   unsigned int left = 0;
00276   unsigned int right = tr_num - 1;
00277   unsigned int mid;
00278 
00279   while (left < right) {
00280     mid = (left + right) / 2;
00281     if (tr_index[mid] < t) {
00282       left = mid + 1;
00283     } else {
00284       right = mid;
00285     }
00286   }
00287   return(left);
00288 }
00289 
00290 
00291 /* write variance data */
00292 static HTK_HMM_Var **vr_index;  
00293 static unsigned int vr_num;     
00294 
00304 static int
00305 qsort_vr_index(HTK_HMM_Var **v1, HTK_HMM_Var **v2)
00306 {
00307   if (*v1 > *v2) return 1;
00308   else if (*v1 < *v2) return -1;
00309   else return 0;
00310 }
00311 
00323 static boolean
00324 wt_var(FILE *fp, HTK_HMM_INFO *hmm)
00325 {
00326   HTK_HMM_Var *v;
00327   unsigned int idx;
00328 
00329   vr_num = 0;
00330   for(v = hmm->vrstart; v; v = v->next) vr_num++;
00331   vr_index = (HTK_HMM_Var **)mymalloc(sizeof(HTK_HMM_Var *) * vr_num);
00332   idx = 0;
00333   for(v = hmm->vrstart; v; v = v->next) vr_index[idx++] = v;
00334   qsort(vr_index, vr_num, sizeof(HTK_HMM_Var *), (int (*)(const void *, const void *))qsort_vr_index);  
00335 
00336   wrt(fp, &vr_num, sizeof(unsigned int), 1);
00337   for (idx = 0; idx < vr_num; idx++) {
00338     v = vr_index[idx];
00339     wrt_str(fp, v->name);
00340     wrt(fp, &(v->len), sizeof(short), 1);
00341     wrt(fp, v->vec, sizeof(VECT), v->len);
00342   }
00343   jlog("Stat: write_binhmm: %d variance written\n", vr_num);
00344 
00345   return TRUE;
00346 }
00347 
00355 static unsigned int
00356 search_vid(HTK_HMM_Var *v)
00357 {
00358   unsigned int left = 0;
00359   unsigned int right = vr_num - 1;
00360   unsigned int mid;
00361 
00362   while (left < right) {
00363     mid = (left + right) / 2;
00364     if (vr_index[mid] < v) {
00365       left = mid + 1;
00366     } else {
00367       right = mid;
00368     }
00369   }
00370   return(left);
00371 }
00372 
00373 
00374 /* write density data */
00375 static HTK_HMM_Dens **dens_index; 
00376 static unsigned int dens_num;   
00377 
00387 static int
00388 qsort_dens_index(HTK_HMM_Dens **d1, HTK_HMM_Dens **d2)
00389 {
00390   if (*d1 > *d2) return 1;
00391   else if (*d1 < *d2) return -1;
00392   else return 0;
00393 }
00394 
00408 static boolean
00409 wt_dens(FILE *fp, HTK_HMM_INFO *hmm)
00410 {
00411   HTK_HMM_Dens *d;
00412   unsigned int idx;
00413   unsigned int vid;
00414 
00415   dens_num = hmm->totalmixnum;
00416   dens_index = (HTK_HMM_Dens **)mymalloc(sizeof(HTK_HMM_Dens *) * dens_num);
00417   idx = 0;
00418   for(d = hmm->dnstart; d; d = d->next) dens_index[idx++] = d;
00419   qsort(dens_index, dens_num, sizeof(HTK_HMM_Dens *), (int (*)(const void *, const void *))qsort_dens_index);
00420   
00421   wrt(fp, &dens_num, sizeof(unsigned int), 1);
00422   for (idx = 0; idx < dens_num; idx++) {
00423     d = dens_index[idx];
00424     wrt_str(fp, d->name);
00425     wrt(fp, &(d->meanlen), sizeof(short), 1);
00426     wrt(fp, d->mean, sizeof(VECT), d->meanlen);
00427     vid = search_vid(d->var);
00428     /* for debug */
00429     if (d->var != vr_index[vid]) {
00430       jlog("Error: write_binhmm: index not match!!!\n");
00431       return FALSE;
00432     }
00433     wrt(fp, &vid, sizeof(unsigned int), 1);
00434     wrt(fp, &(d->gconst), sizeof(LOGPROB), 1);
00435   }
00436   jlog("Stat: write_binhmm: %d gaussian densities written\n", dens_num);
00437 
00438   return TRUE;
00439 }
00440 
00448 static unsigned int
00449 search_did(HTK_HMM_Dens *d)
00450 {
00451   unsigned int left = 0;
00452   unsigned int right = dens_num - 1;
00453   unsigned int mid;
00454 
00455   while (left < right) {
00456     mid = (left + right) / 2;
00457     if (dens_index[mid] < d) {
00458       left = mid + 1;
00459     } else {
00460       right = mid;
00461     }
00462   }
00463   return(left);
00464 }
00465 
00466 /* write stream weight data */
00467 static HTK_HMM_StreamWeight **streamweight_index; 
00468 static unsigned int streamweight_num;   
00469 
00479 static int
00480 qsort_streamweight_index(HTK_HMM_StreamWeight **d1, HTK_HMM_StreamWeight **d2)
00481 {
00482   if (*d1 > *d2) return 1;
00483   else if (*d1 < *d2) return -1;
00484   else return 0;
00485 }
00486 
00500 static boolean
00501 wt_streamweight(FILE *fp, HTK_HMM_INFO *hmm)
00502 {
00503   HTK_HMM_StreamWeight *sw;
00504   unsigned int idx;
00505 
00506   streamweight_num = 0;
00507   for(sw=hmm->swstart;sw;sw=sw->next) streamweight_num++;
00508   streamweight_index = (HTK_HMM_StreamWeight **)mymalloc(sizeof(HTK_HMM_StreamWeight *) * streamweight_num);
00509   idx = 0;
00510   for(sw = hmm->swstart; sw; sw = sw->next) streamweight_index[idx++] = sw;
00511   qsort(streamweight_index, streamweight_num, sizeof(HTK_HMM_StreamWeight *), (int (*)(const void *, const void *))qsort_streamweight_index);
00512   
00513   wrt(fp, &streamweight_num, sizeof(unsigned int), 1);
00514   for (idx = 0; idx < streamweight_num; idx++) {
00515     sw = streamweight_index[idx];
00516     wrt_str(fp, sw->name);
00517     wrt(fp, &(sw->len), sizeof(short), 1);
00518     wrt(fp, sw->weight, sizeof(VECT), sw->len);
00519   }
00520   jlog("Stat: write_binhmm: %d stream weights written\n", streamweight_num);
00521 
00522   return TRUE;
00523 }
00524 
00532 static unsigned int
00533 search_swid(HTK_HMM_StreamWeight *sw)
00534 {
00535   unsigned int left = 0;
00536   unsigned int right = streamweight_num - 1;
00537   unsigned int mid;
00538 
00539   while (left < right) {
00540     mid = (left + right) / 2;
00541     if (streamweight_index[mid] < sw) {
00542       left = mid + 1;
00543     } else {
00544       right = mid;
00545     }
00546   }
00547   return(left);
00548 }
00549 
00550 
00551 /* write tmix data */
00552 static GCODEBOOK **tm_index; 
00553 static unsigned int tm_num;     
00554 static unsigned int tm_idx;     
00555 
00561 static void
00562 tmix_list_callback(void *p)
00563 {
00564   GCODEBOOK *tm;
00565   tm = p;
00566   tm_index[tm_idx++] = tm;
00567 }
00568 
00578 static int
00579 qsort_tm_index(GCODEBOOK **tm1, GCODEBOOK **tm2)
00580 {
00581   if (*tm1 > *tm2) return 1;
00582   else if (*tm1 < *tm2) return -1;
00583   else return 0;
00584 }
00585 
00599 static boolean
00600 wt_tmix(FILE *fp, HTK_HMM_INFO *hmm)
00601 {
00602   GCODEBOOK *tm;
00603   unsigned int idx;
00604   unsigned int did;
00605   int i;
00606 
00607   tm_num = hmm->codebooknum;
00608   tm_index = (GCODEBOOK **)mymalloc(sizeof(GCODEBOOK *) * tm_num);
00609   tm_idx = 0;
00610   aptree_traverse_and_do(hmm->codebook_root, tmix_list_callback);
00611   qsort(tm_index, tm_num, sizeof(GCODEBOOK *), (int (*)(const void *, const void *))qsort_tm_index);  
00612 
00613   wrt(fp, &tm_num, sizeof(unsigned int), 1);
00614   for (idx = 0; idx < tm_num; idx++) {
00615     tm = tm_index[idx];
00616     wrt_str(fp, tm->name);
00617     wrt(fp, &(tm->num), sizeof(int), 1);
00618     for(i=0;i<tm->num;i++) {
00619       if (tm->d[i] == NULL) {
00620         did = dens_num;
00621       } else {
00622         did = search_did(tm->d[i]);
00623         /* for debug */
00624         if (tm->d[i] != dens_index[did]) {
00625           jlog("Error: write_binhmm: index not match!!!\n");
00626           return FALSE;
00627         }
00628       }
00629       wrt(fp, &did, sizeof(unsigned int), 1);
00630     }
00631   }
00632   jlog("Stat: write_binhmm: %d tied-mixture codebooks written\n", tm_num);
00633 
00634   return TRUE;
00635 }
00636 
00644 static unsigned int
00645 search_tmid(GCODEBOOK *tm)
00646 {
00647   unsigned int left = 0;
00648   unsigned int right = tm_num - 1;
00649   unsigned int mid;
00650 
00651   while (left < right) {
00652     mid = (left + right) / 2;
00653     if (tm_index[mid] < tm) {
00654       left = mid + 1;
00655     } else {
00656       right = mid;
00657     }
00658   }
00659   return(left);
00660 }
00661 
00662 
00663 /* write mixture pdf data */
00664 static HTK_HMM_PDF **mpdf_index; 
00665 static unsigned int mpdf_num;   
00666 
00676 static int
00677 qsort_mpdf_index(HTK_HMM_PDF **d1, HTK_HMM_PDF **d2)
00678 {
00679   if (*d1 > *d2) return 1;
00680   else if (*d1 < *d2) return -1;
00681   else return 0;
00682 }
00683 
00694 static boolean
00695 wt_pdf_sub(FILE *fp, HTK_HMM_INFO *hmm, HTK_HMM_PDF *m)
00696 {
00697   unsigned int did;
00698   int i;
00699   short dummy;
00700   
00701   if (hmm->is_tied_mixture) {
00702     /* try tmix */
00703     did = search_tmid((GCODEBOOK *)(m->b));
00704     if ((GCODEBOOK *)m->b == tm_index[did]) {
00705       /* tmix */
00706       dummy = -1;
00707       wrt(fp, &dummy, sizeof(short), 1);
00708       wrt(fp, &did, sizeof(unsigned int), 1);
00709     } else {
00710       /* tmix failed -> normal mixture */
00711       wrt(fp, &(m->mix_num), sizeof(short), 1);
00712       for (i=0;i<m->mix_num;i++) {
00713         if (m->b[i] == NULL) {
00714           did = dens_num;
00715         } else {
00716           did = search_did(m->b[i]);
00717           if (m->b[i] != dens_index[did]) {
00718             jlog("Error: write_binhmm: index not match!!!\n");
00719             return FALSE;
00720           }
00721         }
00722         wrt(fp, &did, sizeof(unsigned int), 1);
00723       }
00724     }
00725   } else {                      /* not tied mixture */
00726     wrt(fp, &(m->mix_num), sizeof(short), 1);
00727     for (i=0;i<m->mix_num;i++) {
00728       if (m->b[i] == NULL) {
00729         did = dens_num;
00730       } else {
00731         did = search_did(m->b[i]);
00732         if (m->b[i] != dens_index[did]) {
00733           jlog("Error: write_binhmm: index not match!!!\n");
00734           return FALSE;
00735         }
00736       }
00737       wrt(fp, &did, sizeof(unsigned int), 1);
00738     }
00739   }
00740   wrt(fp, m->bweight, sizeof(PROB), m->mix_num);
00741 
00742   return TRUE;
00743 }
00744 
00758 static boolean
00759 wt_mpdf(FILE *fp, HTK_HMM_INFO *hmm)
00760 {
00761   HTK_HMM_PDF *m;
00762   unsigned int idx;
00763 
00764   mpdf_num = 0;
00765   for(m=hmm->pdfstart;m;m=m->next) mpdf_num++;
00766   mpdf_index = (HTK_HMM_PDF **)mymalloc(sizeof(HTK_HMM_PDF *) * mpdf_num);
00767   idx = 0;
00768   for(m=hmm->pdfstart;m;m=m->next) mpdf_index[idx++] = m;
00769   qsort(mpdf_index, mpdf_num, sizeof(HTK_HMM_PDF *), (int (*)(const void *, const void *))qsort_mpdf_index);
00770   
00771   wrt(fp, &mpdf_num, sizeof(unsigned int), 1);
00772   for (idx = 0; idx < mpdf_num; idx++) {
00773     m = mpdf_index[idx];
00774     wrt_str(fp, m->name);
00775     wrt(fp, &(m->stream_id), sizeof(short), 1);
00776     if (wt_pdf_sub(fp, hmm, m) == FALSE) return FALSE;
00777   }
00778 
00779   jlog("Stat: write_binhmm: %d mixture PDF written\n", mpdf_num);
00780 
00781   return TRUE;
00782 }
00783 
00791 static unsigned int
00792 search_mpdfid(HTK_HMM_PDF *m)
00793 {
00794   unsigned int left = 0;
00795   unsigned int right = mpdf_num - 1;
00796   unsigned int mid;
00797 
00798   while (left < right) {
00799     mid = (left + right) / 2;
00800     if (mpdf_index[mid] < m) {
00801       left = mid + 1;
00802     } else {
00803       right = mid;
00804     }
00805   }
00806   return(left);
00807 }
00808 
00809 
00810 /* write state data */
00811 static HTK_HMM_State **st_index; 
00812 static unsigned int st_num;     
00813 
00823 static int
00824 qsort_st_index(HTK_HMM_State **s1, HTK_HMM_State **s2)
00825 {
00826   if (*s1 > *s2) return 1;
00827   else if (*s1 < *s2) return -1;
00828   else return 0;
00829 }
00830 
00845 static boolean
00846 wt_state(FILE *fp, HTK_HMM_INFO *hmm, boolean mpdf_macro)
00847 {
00848   HTK_HMM_State *s;
00849   unsigned int idx;
00850   unsigned int mid;
00851   unsigned int swid;
00852   int m;
00853 
00854   st_num = hmm->totalstatenum;
00855   st_index = (HTK_HMM_State **)mymalloc(sizeof(HTK_HMM_State *) * st_num);
00856   idx = 0;
00857   for(s = hmm->ststart; s; s = s->next) st_index[idx++] = s;
00858   qsort(st_index, st_num, sizeof(HTK_HMM_State *), (int (*)(const void *, const void *))qsort_st_index);
00859   
00860   wrt(fp, &st_num, sizeof(unsigned int), 1);
00861   for (idx = 0; idx < st_num; idx++) {
00862     s = st_index[idx];
00863     wrt_str(fp, s->name);
00864     if (mpdf_macro) {
00865       /* mpdf are already written, so write index */
00866       for(m=0;m<s->nstream;m++) {
00867         if (s->pdf[m] == NULL) {
00868           mid = mpdf_num;
00869         } else {
00870           mid = search_mpdfid(s->pdf[m]);
00871           if (s->pdf[m] != mpdf_index[mid]) {
00872             jlog("Error: write_binhmm: index not match!!!\n");
00873             return FALSE;
00874           }
00875         }
00876         wrt(fp, &mid, sizeof(unsigned int), 1);
00877       }
00878     } else {
00879       /* mpdf should be written here */
00880       for(m=0;m<s->nstream;m++) {
00881         /* stream_id will not be written */
00882         if (wt_pdf_sub(fp, hmm, s->pdf[m]) == FALSE) return FALSE;
00883       }
00884     }
00885     if (hmm->opt.stream_info.num > 1) {
00886       /* write steam weight */
00887       if (s->w == NULL) {
00888         swid = streamweight_num;
00889       } else {
00890         swid = search_swid(s->w);
00891         if (s->w != streamweight_index[swid]) {
00892           jlog("Error: write_binhmm: index not match!!!\n");
00893           return FALSE;
00894         }
00895       }
00896       wrt(fp, &swid, sizeof(unsigned int), 1);
00897     }
00898   }
00899 
00900   jlog("Stat: write_binhmm: %d states written\n", st_num);
00901 
00902   return TRUE;
00903 }
00904 
00912 static unsigned int
00913 search_stid(HTK_HMM_State *s)
00914 {
00915   unsigned int left = 0;
00916   unsigned int right = st_num - 1;
00917   unsigned int mid;
00918 
00919   while (left < right) {
00920     mid = (left + right) / 2;
00921     if (st_index[mid] < s) {
00922       left = mid + 1;
00923     } else {
00924       right = mid;
00925     }
00926   }
00927   return(left);
00928 }
00929 
00930 
00942 static boolean
00943 wt_data(FILE *fp, HTK_HMM_INFO *hmm)
00944 {
00945   HTK_HMM_Data *d;
00946   unsigned int md_num;
00947   unsigned int sid, tid;
00948   int i;
00949 
00950   md_num = hmm->totalhmmnum;
00951 
00952   wrt(fp, &(md_num), sizeof(unsigned int), 1);
00953   for(d = hmm->start; d; d = d->next) {
00954     wrt_str(fp, d->name);
00955     wrt(fp, &(d->state_num), sizeof(short), 1);
00956     for (i=0;i<d->state_num;i++) {
00957       if (d->s[i] != NULL) {
00958         sid = search_stid(d->s[i]);
00959         /* for debug */
00960         if (d->s[i] != st_index[sid]) {
00961           jlog("Error: write_binhmm: index not match!!!\n");
00962           return FALSE;
00963         }
00964       } else {
00965         sid = hmm->totalstatenum + 1; /* error value */
00966       }
00967       wrt(fp, &sid, sizeof(unsigned int), 1);
00968     }
00969     tid = search_trid(d->tr);
00970     /* for debug */
00971     if (d->tr != tr_index[tid]) {
00972       jlog("Error: write_binhmm: index not match!!!\n");
00973       return FALSE;
00974     }
00975     wrt(fp, &tid, sizeof(unsigned int), 1);
00976   }
00977   jlog("Stat: write_binhmm: %d HMM model definition written\n", md_num);
00978   return TRUE;
00979 }
00980 
00981 
00991 boolean
00992 write_binhmm(FILE *fp, HTK_HMM_INFO *hmm, Value *para)
00993 {
00994   boolean mpdf_macro;
00995 
00996   if (hmm->pdf_root != NULL) {
00997     /* "~p" macro definition exist */
00998     /* save mixture pdf separatedly from state definition */
00999     mpdf_macro = TRUE;
01000     jlog("Stat: write_binhmm: mixture PDF macro \"~p\" used, use qualifier \'M\'\n");
01001   } else {
01002     mpdf_macro = FALSE;
01003   }
01004 
01005   /* write header */
01006   if (wt_header(fp, (para ? TRUE : FALSE), hmm->variance_inversed, mpdf_macro) == FALSE) {
01007     jlog("Error: write_binhmm: failed to write header\n");
01008     return FALSE;
01009   }
01010 
01011   if (para) {
01012     /* write acoustic analysis parameter info */
01013     if (wt_para(fp, para) == FALSE) {
01014       jlog("Error: write_binhmm: failed to write acoustic analysis parameters\n");
01015       return FALSE;
01016     }
01017   }
01018   
01019   /* write option data */
01020   if (wt_opt(fp, &(hmm->opt)) == FALSE) {
01021     jlog("Error: write_binhmm: failed to write option data\n");
01022     return FALSE;
01023   }
01024 
01025   /* write type data */
01026   if (wt_type(fp, hmm) == FALSE) {
01027     jlog("Error: write_binhmm: failed to write HMM type data\n");
01028     return FALSE;
01029   }
01030 
01031   /* write transition data */
01032   if (wt_trans(fp, hmm) == FALSE) {
01033     jlog("Error: write_binhmm: failed to write HMM transition data\n");
01034     return FALSE;
01035   }
01036 
01037   /* write variance data */
01038   if (wt_var(fp, hmm) == FALSE) {
01039     jlog("Error: write_binhmm: failed to write HMM variance data\n");
01040     return FALSE;
01041   }
01042 
01043   /* write density data */
01044   if (wt_dens(fp, hmm) == FALSE) {
01045     jlog("Error: write_binhmm: failed to write density data\n");
01046     return FALSE;
01047   }
01048 
01049   /* write stream weight data */
01050   if (hmm->opt.stream_info.num > 1) {
01051     if (wt_streamweight(fp, hmm) == FALSE) {
01052       jlog("Error: write_binhmm: failed to write stream weights data\n");
01053       return FALSE;
01054     }
01055   }
01056 
01057   /* write tmix data */
01058   if (hmm->is_tied_mixture) {
01059     if (wt_tmix(fp, hmm) == FALSE) {
01060       jlog("Error: write_binhmm: failed to write tied-mixture codebook data\n");
01061       return FALSE;
01062     }
01063   }
01064 
01065   /* write mixture pdf data */
01066   if (mpdf_macro) {
01067     if (wt_mpdf(fp, hmm) == FALSE) {
01068       jlog("Error: write_binhmm: failed to write mixture pdf data\n");
01069       return FALSE;
01070     }
01071   }
01072     
01073   /* write state data */
01074   if (wt_state(fp, hmm, mpdf_macro) == FALSE) {
01075     jlog("Error: write_binhmm: failed to write HMM state data\n");
01076     return FALSE;
01077   }
01078 
01079   /* write model data */
01080   if (wt_data(fp, hmm) == FALSE) {
01081     jlog("Error: write_binhmm: failed to write HMM data\n");
01082     return FALSE;
01083   }
01084 
01085   /* free pointer->index work area */
01086   if (mpdf_macro) free(mpdf_index);
01087   free(tr_index);
01088   free(vr_index);
01089   if (hmm->opt.stream_info.num > 1) free(streamweight_index);
01090   free(dens_index);
01091   if (hmm->is_tied_mixture) free(tm_index);
01092   free(st_index);
01093 
01094   return (TRUE);
01095 }