00001 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 #include <sent/stddefs.h>
00044 #include <sent/htk_param.h>
00045 #include <sent/htk_hmm.h>
00046 
00047 #define MAXBUFLEN  4096         
00048 
00049 char *rdhmmdef_token;           
00050 static char *buf = NULL;        
00051 static int line;                
00052 
00053 
00054 
00060 void
00061 rderr(char *str)
00062 {
00063   if (rdhmmdef_token == NULL) { 
00064     jlog("Error: rdhmmdef: %s on end of file\n", str);
00065   } else {
00066     jlog("Error: rdhmmdef: read error at line %d: %s\n", line, (str) ? str : "parse error");
00067   }
00068   jlog_flush();
00069   exit(1);
00070 }
00071 
00079 char *
00080 read_token(FILE *fp)
00081 {
00082   if (buf != NULL) {
00083     
00084     if ((rdhmmdef_token = mystrtok_quote(NULL, HMMDEF_DELM)) != NULL) {
00085       
00086       return rdhmmdef_token;
00087     }
00088   } else {
00089     
00090     buf = (char *)mymalloc(MAXBUFLEN);
00091     line = 1;
00092   }
00093   
00094   if (getl(buf, MAXBUFLEN, fp) == NULL) {
00095     rdhmmdef_token = NULL;
00096   } else {
00097     rdhmmdef_token = mystrtok_quote(buf, HMMDEF_DELM);
00098     line++;
00099   }
00100   return rdhmmdef_token;
00101 }
00102 
00108 static void
00109 conv_log_arc(HTK_HMM_INFO *hmm)
00110 {
00111   HTK_HMM_Trans *tr;
00112   int i,j;
00113   LOGPROB l;
00114 
00115   for (tr = hmm->trstart; tr; tr = tr->next) {
00116     for(i=0;i<tr->statenum;i++) {
00117       for(j=0;j<tr->statenum;j++) {
00118         l = tr->a[i][j];
00119         tr->a[i][j] = (l != 0.0) ? (float)log10(l) : LOG_ZERO;
00120       }
00121     }
00122   }
00123 }
00129 void
00130 htk_hmm_inverse_variances(HTK_HMM_INFO *hmm)
00131 {
00132   HTK_HMM_Var *v;
00133   int i;
00134 
00135   for (v = hmm->vrstart; v; v = v->next) {
00136     for(i=0;i<v->len;i++) {
00137       v->vec[i] = 1 / v->vec[i];
00138     }
00139   }
00140 }
00141 
00142 
00154 boolean
00155 rdhmmdef(FILE *fp, HTK_HMM_INFO *hmm)
00156 {
00157   char macrosw;
00158   char *name;
00159 
00160   
00161   hmm->variance_inversed = FALSE;
00162 
00163   
00164   read_token(fp);
00165   
00166   
00167   while (rdhmmdef_token != NULL) {
00168     if (rdhmmdef_token[0] != '~') { 
00169       return FALSE;
00170     }
00171     macrosw = rdhmmdef_token[1];
00172     read_token(fp);             
00173     switch(macrosw) {
00174     case 'o':                   
00175       set_global_opt(fp,hmm);
00176       break;
00177     case 't':                   
00178       name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
00179       if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
00180       read_token(fp);
00181       def_trans_macro(name, fp, hmm);
00182       break;
00183     case 's':                   
00184       name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
00185       if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
00186       read_token(fp);
00187       def_state_macro(name, fp, hmm);
00188       break;
00189     case 'm':                   
00190       name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
00191       if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
00192       read_token(fp);
00193       def_dens_macro(name, fp, hmm);
00194       break;
00195     case 'h':                   
00196       name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
00197       if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
00198       read_token(fp);
00199       def_HMM(name, fp, hmm);
00200       break;
00201     case 'v':                   
00202       name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
00203       if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
00204       read_token(fp);
00205       def_var_macro(name, fp, hmm);
00206       break;
00207     case 'r':                   
00208       name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
00209       if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
00210       read_token(fp);
00211       def_regtree_macro(name, fp, hmm);
00212       break;
00213     }
00214   }
00215 
00216   
00217   conv_log_arc(hmm);
00218 
00219   jlog("Stat: rdhmmdef: ascii format HMM definition\n");
00220   
00221   
00222   if (check_all_hmm_limit(hmm)) {
00223     jlog("Stat: rdhmmdef: limit check passed\n");
00224   } else {
00225     jlog("Error: rdhmmdef: cannot handle this HMM due to system limitation\n");
00226     return FALSE;
00227   }
00228 
00229   
00230   hmm->need_multipath = htk_hmm_has_several_arc_on_edge(hmm);
00231   if (hmm->need_multipath) {
00232     jlog("Stat: rdhmmdef: this HMM requires multipath handling at decoding\n");
00233   } else {
00234     jlog("Stat: rdhmmdef: this HMM does not need multipath handling\n");
00235   }
00236   
00237   
00238   if (! hmm->variance_inversed) {
00239     htk_hmm_inverse_variances(hmm);
00240     hmm->variance_inversed = TRUE;
00241   }
00242 
00243   
00244   if (!check_hmm_options(hmm)) {
00245     jlog("Error: rdhmmdef: hmm options check failed\n");
00246     return FALSE;
00247   }
00248 
00249   
00250   
00251   {
00252     HTK_HMM_State *stmp;
00253     int n, max;
00254     n = 0;
00255     max = 0;
00256     for (stmp = hmm->ststart; stmp; stmp = stmp->next) {
00257       if (max < stmp->mix_num) max = stmp->mix_num;
00258       stmp->id = n++;
00259       if (n >= MAX_STATE_NUM) {
00260         jlog("Error: rdhmmdef: too much states in a model > %d\n", MAX_STATE_NUM);
00261         jlog("Error: you can try changing value of MAX_STATE_NUM\n");
00262         return FALSE;
00263       }
00264     }
00265     hmm->totalstatenum = n;
00266     hmm->maxmixturenum = max;
00267   }
00268   
00269   {
00270     HTK_HMM_Data *dtmp;
00271     int n, maxlen;
00272     n = 0;
00273     maxlen = 0;
00274     for (dtmp = hmm->start; dtmp; dtmp = dtmp->next) {
00275       if (maxlen < dtmp->state_num) maxlen = dtmp->state_num;
00276       n++;
00277     }
00278     hmm->maxstatenum = maxlen;
00279     hmm->totalhmmnum = n;
00280   }
00281   
00282   {
00283     HTK_HMM_Dens *dtmp;
00284     int n = 0;
00285     for (dtmp = hmm->dnstart; dtmp; dtmp = dtmp->next) {
00286       n++;
00287     }
00288     hmm->totalmixnum = n;
00289   }
00290   
00291   {
00292     HTK_HMM_Dens *dtmp;
00293     int n = 0;
00294     for (dtmp = hmm->dnstart; dtmp; dtmp = dtmp->next) {
00295       n++;
00296     }
00297     hmm->totalmixnum = n;
00298   }
00299 
00300   return(TRUE);                 
00301 }