Julius 4.2
libjulius/src/hmm_check.c
説明を見る。
00001 
00018 /*
00019  * Copyright (c) 1991-2011 Kawahara Lab., Kyoto University
00020  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00021  * Copyright (c) 2005-2011 Julius project team, Nagoya Institute of Technology
00022  * All rights reserved
00023  */
00024 
00025 #include <julius/julius.h>
00026 
00027 #define PHSTEP 10               ///< Malloc step for phoneme conversion
00028 
00080 static HMM_Logical **
00081 new_str2phseq(char *str, HTK_HMM_INFO *hmminfo, int *len_ret)
00082 {
00083   char **tokens;
00084   boolean *word_end;
00085   int phnum;
00086   boolean word_mode = FALSE;
00087   HMM_Logical **new;
00088   static char buf[MAX_HMMNAME_LEN];
00089   
00090   /* read in string and divide into token unit */
00091   {
00092     char *p;
00093     int tokenmax;
00094     tokenmax = PHSTEP;
00095     tokens = (char **)mymalloc(sizeof(char *) * tokenmax);
00096     word_end = (boolean *)mymalloc(sizeof(boolean) * tokenmax);
00097     phnum = 0;
00098     for(p = strtok(str, DELM); p; p = strtok(NULL, DELM)) {
00099       if (strmatch(p, "|")) {
00100         word_mode = TRUE;
00101         if (phnum > 0) word_end[phnum-1] = TRUE;
00102         continue;
00103       }
00104       if (phnum >= tokenmax) {
00105         tokenmax += PHSTEP;
00106         tokens = (char **)myrealloc(tokens, sizeof(char *) * tokenmax);
00107         word_end = (boolean *)myrealloc(word_end, sizeof(boolean) * tokenmax);
00108       }
00109       tokens[phnum] = strcpy((char *)mymalloc(strlen(p)+1), p);
00110       word_end[phnum] = FALSE;
00111       phnum++;
00112     }
00113     if (phnum == 0) {
00114       jlog("ERROR: hmm_check: no phone specified\n");
00115       printf("ERROR: hmm_check: no phone specified\n");
00116       new = NULL;
00117       goto spend;
00118     }
00119     word_end[phnum-1] = TRUE;
00120   }
00121   /* check if the phonemes exist in basephone list */
00122   {
00123     BASEPHONE *ph;
00124     int i;
00125     boolean ok_flag = TRUE;
00126     for (i=0;i<phnum;i++) {
00127       ph = aptree_search_data(tokens[i], hmminfo->basephone.root);
00128       if (ph == NULL || ! strmatch(ph->name, tokens[i])) {
00129         jlog("ERROR: hmm_check: %2d - unknown phone \"%s\"\n", i+1, tokens[i]);
00130         printf("ERROR: hmm_check: %2d - unknown phone \"%s\"\n", i+1, tokens[i]);
00131         ok_flag = FALSE;
00132         continue;
00133       }
00134     }
00135     if (! ok_flag) {
00136       jlog("ERROR: hmm_check: unknown phone(s)\n");
00137       printf("ERROR: hmm_check: unknown phone(s)\n");
00138       new = NULL;
00139       goto spend;
00140     }
00141   }
00142   /* token -> original logical name -> logical HMM -> physical/pseudo phone */
00143   /* cross-word conversion and fallback to bi/mono-phone is also considered */
00144   {
00145     int i;
00146     char *hmmstr;
00147     HMM_Logical *lg;
00148     boolean ok_flag = TRUE;
00149 
00150     new = (HMM_Logical **)mymalloc(sizeof(HMM_Logical *) * phnum);
00151 
00152     /* original logical name, applied logical HMM name (defined by HMMList),
00153        and the actual physical/pseudo HMM name (defined in hmmdefs) */
00154     printf("\n  id     original   logical    physical/pseudo\n");
00155     printf(" -------------------------------------------------\n");
00156 
00157 
00158     if (hmminfo->is_triphone) {
00159       cycle_triphone(NULL);
00160       cycle_triphone(tokens[0]);
00161       for (i = 0; i < phnum; i++) {
00162         if (i < phnum - 1) {
00163           hmmstr = cycle_triphone(tokens[i+1]);
00164         } else {
00165           hmmstr = cycle_triphone_flush();
00166         }
00167         lg = htk_hmmdata_lookup_logical(hmminfo, hmmstr);
00168         if (lg == NULL) {
00169           if (word_mode) {
00170             if (i > 0 && word_end[i-1]) {
00171               if (word_end[i]) {
00172                 center_name(hmmstr, buf);
00173               } else {
00174                 rightcenter_name(hmmstr, buf);
00175               }
00176             } else if (word_end[i]) {
00177               leftcenter_name(hmmstr, buf);
00178             }
00179             lg = htk_hmmdata_lookup_logical(hmminfo, buf);
00180             if (lg == NULL) {
00181               jlog("ERROR: hmm_check: no defined/pseudo HMM for \"%s\"??\n", buf);
00182               printf("ERROR: hmm_check: no defined/pseudo HMM for \"%s\"??\n", buf);
00183               ok_flag = FALSE;
00184               continue;
00185             }
00186             if (lg->is_pseudo) {
00187               printf("  %2d: %11s -> (pseudo) -> {%s}\n", i+1, hmmstr, lg->body.pseudo->name);
00188             } else {
00189               printf("  %2d: %11s -> %8s -> [%s]\n", i+1, hmmstr, lg->name, lg->body.defined->name);
00190             }
00191           } else {
00192             jlog("ERROR: hmm_check: UNKNOWN %2d: (%s)\n", i+1, hmmstr);
00193             printf("ERROR: hmm_check: UNKNOWN %2d: (%s)\n", i+1, hmmstr);
00194             ok_flag = FALSE;
00195             continue;
00196           }
00197         } else {
00198           if (lg->is_pseudo) {
00199             printf("  %2d: %11s -> (pseudo) -> {%s}\n", i+1, hmmstr, lg->body.pseudo->name);
00200           } else {
00201             printf("  %2d: %11s -> %8s -> [%s]\n", i+1, hmmstr, " ", lg->body.defined->name);
00202           }
00203         }
00204         new[i] = lg;
00205       }
00206     } else {
00207       for (i = 0; i < phnum; i++) {
00208         lg = htk_hmmdata_lookup_logical(hmminfo, tokens[i]);
00209         if (lg == NULL) {
00210           jlog("ERROR: hmm_check: %2d - unknown logical HMM \"%s\"\n", i+1, tokens[i]);
00211           printf("ERROR: hmm_check: %2d - unknown logical HMM \"%s\"\n", i+1, tokens[i]);
00212           ok_flag = FALSE;
00213           continue;
00214         }
00215         new[i] = lg;
00216       }
00217     }
00218     if (ok_flag) {
00219       printf("succeeded\n");
00220     } else {
00221       jlog("ERROR: hmm_check: failed\n");
00222       printf("failed\n");
00223       free(new);
00224       new = NULL;
00225       goto spend;
00226     }
00227       
00228   }
00229 
00230  spend:
00231   {
00232     int i;
00233     for(i=0;i<phnum;i++) {
00234       free(tokens[i]);
00235     }
00236     free(tokens);
00237     free(word_end);
00238   }
00239 
00240   *len_ret = phnum;
00241 
00242   return new;
00243 }
00244 
00259 static boolean
00260 test_expand_triphone(HTK_HMM_INFO *hmminfo)
00261 {
00262   char *buf;
00263   int newline;
00264   HMM_Logical **phseq;
00265   int phlen;
00266   boolean flag = FALSE;
00267 
00268   buf = (char *)mymalloc(4096);
00269   for(;;) {
00270     /* read in phoneme sequence from stdin */
00271     printf(">>> input phone sequence (word delimiter is `|', blank to return)\n");
00272     if (fgets(buf, 4096, stdin) == NULL) {
00273       flag = TRUE;
00274       break;
00275     }
00276     newline = strlen(buf)-1;    /* chop newline */
00277     if (buf[newline] == '\n') buf[newline] = '\0';
00278     if (buf[0] == '\0') break;
00279     /* convert string to phseq and output */
00280     phseq = new_str2phseq(buf, hmminfo, &phlen);
00281     free(phseq);
00282   }
00283   free(buf);
00284   return flag;
00285 }
00286 
00302 void
00303 hmm_check(RecogProcess *r)
00304 {
00305   boolean endflag;
00306   static char cmd[MAX_HMMNAME_LEN];
00307   int newline;
00308 
00309   printf("*************************************************\n");
00310   printf("********  TRIPHONE COHERENCE CHECK MODE  ********\n");
00311   printf("*************************************************\n");
00312 
00313   printf("hmmdefs=%s\n", r->am->config->hmmfilename);
00314   if (r->am->config->mapfilename != NULL) {
00315     printf("hmmlist=%s\n", r->am->config->mapfilename);
00316   }
00317   printf("dict=%s\n", r->lm->config->dictfilename);
00318   printf("headsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->head_silwid);
00319   printf("tailsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->tail_silwid);
00320 
00321   if (make_base_phone(r->am->hmminfo, r->lm->winfo) == FALSE) {
00322     jlog("ERROR: hmm_check: error in making base phone list\n");
00323     printf("ERROR: hmm_check: error in making base phone list\n");
00324     return;
00325   }
00326 
00327   print_phone_info(stdout, r->am->hmminfo);
00328 
00329   for(endflag = FALSE; endflag == FALSE;) {
00330     printf("===== command (\"H\" for help) > ");
00331     if (fgets(cmd, MAX_HMMNAME_LEN, stdin) == NULL) break;
00332     newline = strlen(cmd)-1;    /* chop newline */
00333     if (cmd[newline] == '\n') cmd[newline] = '\0';
00334     if (cmd[0] == '\0') continue; /* if blank line, read next */
00335 
00336     switch(cmd[0]) {
00337     case 'a':                   /* all */
00338       /* check if logical HMMs cover all possible variants */
00339       test_interword_triphone(r->am->hmminfo, r->lm->winfo);
00340       break;
00341     case 'c':                   /* conv */
00342       /* try to expand triphone for given phoneme sequence */
00343       endflag = test_expand_triphone(r->am->hmminfo);
00344       break;
00345     case 'i':                   /* info */
00346       /* output data source */
00347       printf("hmmdefs=%s\n", r->am->config->hmmfilename);
00348       if (r->am->config->mapfilename != NULL) {
00349         printf("hmmlist=%s\n", r->am->config->mapfilename);
00350       }
00351       printf("dict=%s\n", r->lm->config->dictfilename);
00352       printf("headsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->head_silwid);
00353       printf("tailsil = "); put_voca(stdout, r->lm->winfo, r->lm->winfo->tail_silwid);
00354       print_phone_info(stdout, r->am->hmminfo);
00355       break;
00356     case 'p':                   /* phonelist */
00357       /* output basephone */
00358       print_all_basephone_name(&(r->am->hmminfo->basephone));
00359       break;
00360     case 'd':                   /* phonelist in detail */
00361       /* output basephone */
00362       print_all_basephone_detail(&(r->am->hmminfo->basephone));
00363       break;
00364     case 'q':                   /* quit */
00365       /* quit this check mode */
00366       endflag = TRUE;
00367       break;
00368     default:
00369       printf("COMMANDS:\n");
00370       printf(" info      --- output HMM information\n");
00371       printf(" conv      --- try HMM conversion for given phone sequence\n");
00372       printf(" phonelist --- print base phone list\n");
00373       printf(" all       --- check if all possible IW-triphone is covered\n");
00374       printf(" quit      --- quit\n");
00375       break;
00376     }
00377   }
00378   printf("*************************************************\n");
00379   printf("*****  END OF TRIPHONE COHERENCE CHECK MODE  ****\n");
00380   printf("*************************************************\n");
00381 }
00382 /* end of file */