Julius 4.2
|
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 */