Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

outprob_style.c

Go to the documentation of this file.
00001 
00073 /*
00074  * Copyright (c) 1991-2006 Kawahara Lab., Kyoto University
00075  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00076  * Copyright (c) 2005-2006 Julius project team, Nagoya Institute of Technology, Nagoya Institute of Technology
00077  * All rights reserved
00078  */
00079 
00080 #include <julius.h>
00081 
00082 static char rbuf[MAX_HMMNAME_LEN]; 
00083 
00084 #ifdef PASS1_IWCD
00085 
00098 void
00099 outprob_style_cache_init(WCHMM_INFO *wchmm)
00100 {
00101   int n;
00102   for(n=0;n<wchmm->n;n++) {
00103 #ifdef MULTIPATH_VERSION
00104     if (wchmm->state[n].out.state == NULL) continue;
00105 #endif
00106     if (wchmm->outstyle[n] == AS_RSET) {
00107       (wchmm->state[n].out.rset)->cache.state = NULL;
00108     } else if (wchmm->outstyle[n] == AS_LRSET) {
00109       (wchmm->state[n].out.lrset)->cache.state = NULL;
00110     }
00111   }
00112 }
00113 
00114 
00115 /**********************************************************************/
00116 #ifdef CATEGORY_TREE
00117 
00118 static char lccbuf[MAX_HMMNAME_LEN+7]; 
00119 static char lccbuf2[MAX_HMMNAME_LEN+7]; 
00120 
00143 CD_Set *
00144 lcdset_lookup_with_category(WCHMM_INFO *wchmm, HMM_Logical *hmm, WORD_ID category)
00145 {
00146   CD_Set *cd;
00147 
00148   leftcenter_name(hmm->name, lccbuf);
00149   sprintf(lccbuf2, "%s::%04d", lccbuf, category);
00150   if (wchmm->lcdset_category_root != NULL) {
00151     cd = aptree_search_data(lccbuf2, wchmm->lcdset_category_root);
00152     if (strmatch(lccbuf2, cd->name)) {
00153       return cd;
00154     }
00155   }
00156   return NULL;
00157 }
00158 
00208 static void
00209 lcdset_register_with_category(WCHMM_INFO *wchmm, HTK_HMM_INFO *hmminfo, DFA_INFO *dfa, HMM_Logical *hmm, WORD_ID category)
00210 {
00211   CD_Set *ret;
00212   WORD_ID c2, i, w;
00213   HMM_Logical *ltmp;
00214 
00215   int cnt_c, cnt_w, cnt_p;
00216 
00217   if (lcdset_lookup_with_category(wchmm, hmm, category) == NULL) {
00218     leftcenter_name(hmm->name, lccbuf);
00219     sprintf(lccbuf2, "%s::%04d", lccbuf, category);
00220     if (debug2_flag) {
00221       j_printf("category-aware lcdset {%s}...", lccbuf2);
00222     }
00223     cnt_c = cnt_w = cnt_p = 0;
00224     /* search for category that can connect after this category */
00225     for(c2=0;c2<dfa->term_num;c2++) {
00226       if (! dfa_cp(dfa, category, c2)) continue;
00227       /* for each word in the category, register triphone whose right context
00228          is the beginning phones  */
00229       for(i=0;i<dfa->term.wnum[c2];i++) {
00230         w = dfa->term.tw[c2][i];
00231         ltmp = get_right_context_HMM(hmm, winfo->wseq[w][0]->name, hmminfo);
00232         if (ltmp == NULL) {
00233           ltmp = hmm;
00234           if (ltmp->is_pseudo) {
00235             error_missing_right_triphone(hmm, winfo->wseq[w][0]->name);
00236           }
00237         }
00238         if (! ltmp->is_pseudo) {
00239           if (regist_cdset(&(wchmm->lcdset_category_root), ltmp->body.defined, lccbuf2)) {
00240             cnt_p++;
00241           }
00242         }
00243       }
00244       cnt_c++;
00245       cnt_w += dfa->term.wnum[c2];
00246     }
00247     if (debug2_flag) {
00248       j_printf("%d categories (%d words) can follow, %d HMMs registered\n", cnt_c, cnt_w, cnt_p);
00249     }
00250   }
00251 }
00252 
00272 void
00273 lcdset_register_with_category_all(WCHMM_INFO *wchmm, HTK_HMM_INFO *hmminfo, WORD_INFO *winfo, DFA_INFO *dfa)
00274 {
00275   WORD_ID c1, w, w_prev;
00276   int i;
00277   HMM_Logical *ltmp;
00278   
00279   /* (1) 単語終端の音素について */
00280   /*     word end phone */
00281   for(w=0;w<winfo->num;w++) {
00282     ltmp = winfo->wseq[w][winfo->wlen[w]-1];
00283     lcdset_register_with_category(wchmm, hmminfo, dfa, ltmp, winfo->wton[w]);
00284   }
00285   /* (2)1音素単語の場合, 先行しうる単語の終端音素を考慮 */
00286   /*    for one-phoneme word, possible left context should be also considered */
00287   for(w=0;w<winfo->num;w++) {
00288     if (winfo->wlen[w] > 1) continue;
00289     for(c1=0;c1<dfa->term_num;c1++) {
00290       if (! dfa_cp(dfa, c1, winfo->wton[w])) continue;
00291       for(i=0;i<dfa->term.wnum[c1];i++) {
00292         w_prev = dfa->term.tw[c1][i];
00293         ltmp = get_left_context_HMM(winfo->wseq[w][0], winfo->wseq[w_prev][winfo->wlen[w_prev]-1]->name, hmminfo);
00294         if (ltmp == NULL) continue; /* 1音素自身のlcd_setは(1)で作成済 */
00295         if (ltmp->is_pseudo) continue; /* pseudo phone ならlcd_setはいらない */
00296         lcdset_register_with_category(wchmm, hmminfo, dfa, ltmp, winfo->wton[w]);
00297       }
00298     }
00299   }
00300 }
00301 
00314 static void
00315 callback_free_lcdset_content(void *arg)
00316 {
00317   CD_Set *d;
00318   int j;
00319 
00320   d = arg;
00321   for(j=1;j<d->state_num-1;j++) {
00322     free(d->stateset[j].s);
00323   }
00324   free(d->stateset);
00325 }
00326 
00342 void
00343 lcdset_remove_with_category_all(WCHMM_INFO *wchmm)
00344 {
00345   if (wchmm->lcdset_category_root != NULL) {
00346     aptree_traverse_and_do(wchmm->lcdset_category_root, callback_free_lcdset_content);
00347     free_aptree(wchmm->lcdset_category_root);
00348     wchmm->lcdset_category_root = NULL;
00349   }
00350 }
00351 
00352 #endif /* CATEGORY_TREE */
00353 
00354 #endif /* PASS1_IWCD */
00355 
00382 LOGPROB
00383 outprob_style(WCHMM_INFO *wchmm, int node, int last_wid, int t, HTK_Param *param)
00384 {
00385 
00386 #ifndef PASS1_IWCD
00387   
00388   /* if cross-word triphone handling is disabled, we simply compute the
00389      output prob of the state */
00390   return(outprob_state(t, wchmm->state[node].out, param));
00391   
00392 #else  /* PASS1_IWCD */
00393 
00394   /* state type and context cache is considered */
00395   HMM_Logical *ohmm, *rhmm;
00396   RC_INFO *rset;
00397   LRC_INFO *lrset;
00398   CD_Set *lcd;
00399   WORD_INFO *winfo = wchmm->winfo;
00400   HTK_HMM_INFO *hmminfo = wchmm->hmminfo;
00401 
00402   /* the actual computation is different according to their context dependency
00403      handling */
00404   switch(wchmm->outstyle[node]) {
00405   case AS_STATE:
00406     /* normal state (word-internal or context-independent )*/
00407     /* compute as usual */
00408     return(outprob_state(t, wchmm->state[node].out.state, param));
00409   case AS_LSET:
00410     /* node in word end phone */
00411     /* compute approximated value using the state set in pseudo phone */
00412     return(outprob_cd(t, wchmm->state[node].out.lset, param));
00413   case AS_RSET:
00414     /* note in the beginning phone of word */
00415     /* depends on the last word hypothesis to compute the actual triphone */
00416     rset = wchmm->state[node].out.rset;
00417     /* consult cache */
00418     if (rset->lastwid_cache != last_wid || rset->cache.state == NULL) {
00419       /* cache miss...calculate */
00420       /* rset contains either defined biphone or pseudo biphone */
00421       if (last_wid != WORD_INVALID) {
00422         /* lookup triphone with left-context (= last phoneme) */
00423         if ((ohmm = get_left_context_HMM(rset->hmm, (winfo->wseq[last_wid][winfo->wlen[last_wid]-1])->name, hmminfo)) != NULL) {
00424           rhmm = ohmm;
00425         } else {
00426           /* if triphone not found, try to use the bi-phone itself */
00427           rhmm = rset->hmm;
00428           /* If the bi-phone is explicitly specified in hmmdefs/HMMList,
00429              use it.  if both triphone and biphone not found in user-given
00430              hmmdefs/HMMList, use "pseudo" phone, as same as the end of word */
00431           if (debug2_flag) {
00432             if (rhmm->is_pseudo) {
00433             error_missing_left_triphone(rset->hmm, (winfo->wseq[last_wid][winfo->wlen[last_wid]-1])->name);
00434             }
00435           }
00436         }
00437       } else {
00438         /* if last word is WORD_INVALID try to use the bi-phone itself */
00439         rhmm = rset->hmm;
00440         /* If the bi-phone is explicitly specified in hmmdefs/HMMList,
00441            use it.  if not, use "pseudo" phone, as same as the end of word */
00442         if (debug2_flag) {
00443           if (rhmm->is_pseudo) {
00444             error_missing_left_triphone(rset->hmm, (winfo->wseq[last_wid][winfo->wlen[last_wid]-1])->name);
00445           }
00446         }
00447       }
00448       /* rhmm may be a pseudo phone */
00449       /* store to cache */
00450       if (rhmm->is_pseudo) {
00451         rset->last_is_lset  = TRUE;
00452         rset->cache.lset    = &(rhmm->body.pseudo->stateset[rset->state_loc]);
00453       } else {
00454         rset->last_is_lset  = FALSE;
00455         rset->cache.state   = rhmm->body.defined->s[rset->state_loc];
00456       }
00457       rset->lastwid_cache = last_wid;
00458     }
00459     /* calculate outprob and return */
00460     if (rset->last_is_lset) {
00461       return(outprob_cd(t, rset->cache.lset, param));
00462     } else {
00463       return(outprob_state(t, rset->cache.state, param));
00464     }
00465   case AS_LRSET:
00466     /* node in word with only one phoneme --- both beginning and end */
00467     lrset = wchmm->state[node].out.lrset;
00468     if (lrset->lastwid_cache != last_wid || lrset->cache.state == NULL) {
00469       /* cache miss...calculate */
00470       rhmm = lrset->hmm;
00471       /* lookup cdset for given left context (= last phoneme) */
00472       strcpy(rbuf, rhmm->name);
00473       if (last_wid != WORD_INVALID) {
00474         add_left_context(rbuf, (winfo->wseq[last_wid][winfo->wlen[last_wid]-1])->name);
00475       }
00476 #ifdef CATEGORY_TREE
00477       if (!old_iwcd_flag) {
00478         /* use category-indexed cdset */
00479         if (last_wid != WORD_INVALID &&
00480             (ohmm = get_left_context_HMM(rhmm, (winfo->wseq[last_wid][winfo->wlen[last_wid]-1])->name, hmminfo)) != NULL) {
00481           lcd = lcdset_lookup_with_category(wchmm, ohmm, lrset->category);
00482         } else {
00483           lcd = lcdset_lookup_with_category(wchmm, rhmm, lrset->category);
00484         }
00485       } else {
00486         lcd = lcdset_lookup_by_hmmname(hmminfo, rbuf);
00487       }
00488 #else
00489       lcd = lcdset_lookup_by_hmmname(hmminfo, rbuf);
00490 #endif /* CATEGORY_TREE */
00491       if (lcd != NULL) {        /* found, set to cache */
00492         lrset->last_is_lset  = TRUE;
00493         lrset->cache.lset    = &(lcd->stateset[lrset->state_loc]);
00494         lrset->lastwid_cache = last_wid;
00495       } else {
00496         /* no relating lcdset found, falling to normal state */
00497         if (rhmm->is_pseudo) {
00498           lrset->last_is_lset  = TRUE;
00499           lrset->cache.lset    = &(rhmm->body.pseudo->stateset[lrset->state_loc]);
00500           lrset->lastwid_cache = last_wid;
00501         } else {
00502           lrset->last_is_lset  = FALSE;
00503           lrset->cache.state   = rhmm->body.defined->s[lrset->state_loc];
00504           lrset->lastwid_cache = last_wid;
00505         }
00506       }
00507       /*printf("[%s->%s]\n", lrset->hmm->name, rhmm->name);*/
00508     }
00509     /* calculate outprob and return */
00510     if (lrset->last_is_lset) {
00511       return(outprob_cd(t, lrset->cache.lset, param));
00512     } else {
00513       return(outprob_state(t, lrset->cache.state, param));
00514     }
00515   default:
00516     /* should not happen */
00517     j_error("InternalError: no outprob style??\n");
00518     return(LOG_ZERO);
00519   }
00520 
00521 #endif  /* PASS1_IWCD */
00522 
00523 }
00524 
00541 void
00542 error_missing_right_triphone(HMM_Logical *base, char *rc_name)
00543 {
00544   /* only output message */
00545   strcpy(rbuf, base->name);
00546   add_right_context(rbuf, rc_name);
00547   j_printerr("Warning: IW-triphone for word end \"%s\" not found, fallback to pseudo {%s}\n", rbuf, base->name);
00548 }
00549 
00566 void
00567 error_missing_left_triphone(HMM_Logical *base, char *lc_name)
00568 {
00569   /* only output message */
00570   strcpy(rbuf, base->name);
00571   add_left_context(rbuf, lc_name);
00572   j_printerr("Warning: IW-triphone for word head \"%s\" not found, fallback to pseudo {%s}\n", rbuf, base->name);
00573 }

Generated on Tue Mar 28 16:17:42 2006 for Julius by  doxygen 1.4.2