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 "app.h" 00026 00027 extern boolean separate_score_flag; 00028 00029 static boolean have_progout = FALSE; 00030 00031 /* for short pause segmentation and successive decoding */ 00032 static WORD_ID confword[MAXSEQNUM]; 00033 static int confwordnum; 00034 00035 #ifdef CHARACTER_CONVERSION 00036 #define MAXBUFLEN 4096 ///< Maximum line length of a message sent from a client 00037 static char inbuf[MAXBUFLEN]; 00038 static char outbuf[MAXBUFLEN]; 00039 void 00040 myprintf(char *fmt, ...) 00041 { 00042 va_list ap; 00043 int ret; 00044 00045 va_start(ap,fmt); 00046 ret = vsnprintf(inbuf, MAXBUFLEN, fmt, ap); 00047 va_end(ap); 00048 if (ret > 0) { /* success */ 00049 printf("%s", charconv(inbuf, outbuf, MAXBUFLEN)); 00050 } 00051 } 00052 #else 00053 #define myprintf printf 00054 #endif 00055 00060 #define TEXTWIDTH 70 00061 00067 #define SPTEXTWIDTH 72 00068 #define SPTEXT_FULLWIDTH 76 00069 00070 /**********************************************************************/ 00071 /* process online/offline status */ 00072 00084 static void 00085 status_process_online(Recog *recog, void *dummy) 00086 { 00087 /* nop */ 00088 } 00100 static void 00101 status_process_offline(Recog *recog, void *dummy) 00102 { 00103 /* nop */ 00104 } 00105 00106 /**********************************************************************/ 00107 /* output recording status changes */ 00108 00119 static void 00120 status_recready(Recog *recog, void *dummy) 00121 { 00122 if (recog->jconf->input.speech_input == SP_MIC || recog->jconf->input.speech_input == SP_NETAUDIO) { 00123 if (!recog->process_segment) { 00124 fprintf(stderr, "<<< please speak >>>"); 00125 } 00126 } 00127 } 00138 static void 00139 status_recstart(Recog *recog, void *dummy) 00140 { 00141 if (recog->jconf->input.speech_input == SP_MIC || recog->jconf->input.speech_input == SP_NETAUDIO) { 00142 if (!recog->process_segment) { 00143 fprintf(stderr, "\r \r"); 00144 } 00145 } 00146 } 00157 static void 00158 status_recend(Recog *recog, void *dummy) 00159 { 00160 /* nop */ 00161 } 00174 static void 00175 status_param(Recog *recog, void *dummy) 00176 { 00177 if (verbose_flag) { 00178 // put_param_info(stdout, recog->param); 00179 } 00180 } 00181 00182 /**********************************************************************/ 00183 /* recognition begin / end */ 00184 00198 static void 00199 status_recognition_begin(Recog *recog, void *dummy) 00200 { 00201 if (recog->jconf->decodeopt.segment) { /* short pause segmentation */ 00202 if (have_progout) { 00203 confwordnum = 0; 00204 } 00205 } 00206 } 00207 00220 static void 00221 status_recognition_end(Recog *recog, void *dummy) 00222 { 00223 if (recog->process_segment) { 00224 if (verbose_flag) { 00225 printf("Segmented by short pause, continue to next...\n"); 00226 } else { 00227 //printf("-->\n"); 00228 } 00229 } 00230 if (recog->jconf->decodeopt.segment) { /* short pause segmentation */ 00231 if (have_progout) { 00232 if (confwordnum > 0) { 00233 printf("\n"); 00234 } 00235 } 00236 } 00237 } 00238 00249 static void 00250 status_segment_begin(Recog *recog, void *dummy) 00251 { 00252 /* no output */ 00253 } 00254 00265 static void 00266 status_segment_end(Recog *recog, void *dummy) 00267 { 00268 /* nop */ 00269 } 00270 00271 /**********************************************************************/ 00272 /* 1st pass output */ 00273 00274 static int wst; 00275 static int writelen; 00276 00277 00288 static void 00289 status_pass1_begin(Recog *recog, void *dummy) 00290 { 00291 if (!recog->jconf->decodeopt.realtime_flag) { 00292 VERMES("### Recognition: 1st pass (LR beam)\n"); 00293 } 00294 00295 wst = 0; 00296 00297 if (recog->jconf->decodeopt.segment) { /* short pause segmentation */ 00298 if (have_progout) { 00299 writelen = 0; 00300 } 00301 } 00302 00303 } 00304 00305 00328 static void 00329 result_pass1_current(Recog *recog, void *dummy) 00330 { 00331 int i, j, bgn; 00332 int len, num; 00333 WORD_INFO *winfo; 00334 WORD_ID *seq; 00335 RecogProcess *r; 00336 00337 for(r=recog->process_list;r;r=r->next) { 00338 if (! r->live) continue; 00339 if (! r->have_interim) continue; 00340 00341 winfo = r->lm->winfo; 00342 seq = r->result.pass1.word; 00343 num = r->result.pass1.word_num; 00344 00345 /* update output line with folding */ 00346 printf("\r"); 00347 00348 if (r->config->successive.enabled) { /* short pause segmentation */ 00349 00350 if (have_progout) { 00351 00352 /* progressive output */ 00353 /* first, print already confirmed words */ 00354 len = 0; 00355 for(i=0;i<confwordnum;i++) { 00356 if (len + strlen(winfo->woutput[confword[i]]) > SPTEXTWIDTH) { 00357 for(j=len;j<writelen;j++) printf(" "); 00358 printf("\n"); 00359 for(j=i;j<confwordnum;j++) confword[j-i] = confword[j]; 00360 confwordnum -= i; 00361 len = 0; 00362 i = 0; 00363 writelen = 0; 00364 } 00365 myprintf("%s", winfo->woutput[confword[i]]); 00366 len += strlen(winfo->woutput[confword[i]]); 00367 } 00368 00369 /* output nothing if we are in the first pause area */ 00370 if (!r->pass1.first_sparea) { 00371 printf("|"); 00372 len++; 00373 /* the first word of a segment is the same as last segment, so do not output */ 00374 if (confword[confwordnum-1] == seq[0]) { 00375 bgn = 1; 00376 } else { 00377 bgn = 0; 00378 } 00379 /* next, print current candidate words */ 00380 for(i=bgn;i<num;i++) { 00381 if (len + strlen(winfo->woutput[seq[i]]) > SPTEXT_FULLWIDTH) { 00382 if (i < num - 1) continue; 00383 myprintf("*"); 00384 len += 1; 00385 } else { 00386 myprintf("%s", winfo->woutput[seq[i]]); 00387 len += strlen(winfo->woutput[seq[i]]); 00388 } 00389 } 00390 printf("|"); 00391 len++; 00392 } 00393 00394 fflush(stdout); 00395 /* store maximum written length */ 00396 if (writelen < len) writelen = len; 00397 00398 return; 00399 } 00400 } 00401 00402 len = 0; 00403 if (wst == 0) { /* first line */ 00404 len += 11; 00405 printf("pass1_best:"); 00406 } 00407 00408 bgn = wst; /* output only the last line */ 00409 for (i=bgn;i<num;i++) { 00410 len += strlen(winfo->woutput[seq[i]]) + 1; 00411 if (len > FILLWIDTH) { /* fold line */ 00412 wst = i; 00413 printf("\n"); 00414 len = 0; 00415 } 00416 myprintf(" %s",winfo->woutput[seq[i]]); 00417 } 00418 if (writelen < len) writelen = len; 00419 00420 } 00421 00422 fflush(stdout); /* flush */ 00423 } 00424 00425 00449 static void 00450 result_pass1(Recog *recog, void *dummy) 00451 { 00452 int i,j; 00453 static char buf[MAX_HMMNAME_LEN]; 00454 WORD_INFO *winfo; 00455 WORD_ID *seq; 00456 int num; 00457 RecogProcess *r; 00458 boolean multi; 00459 int len; 00460 00461 if (recog->process_list->next != NULL) multi = TRUE; 00462 else multi = FALSE; 00463 00464 for(r=recog->process_list;r;r=r->next) { 00465 if (! r->live) continue; 00466 if (r->result.status < 0) continue; /* search already failed */ 00467 if (have_progout && r->config->successive.enabled) continue; /* short pause segmentation */ 00468 if (r->config->output.progout_flag) printf("\r"); 00469 00470 winfo = r->lm->winfo; 00471 seq = r->result.pass1.word; 00472 num = r->result.pass1.word_num; 00473 00474 /* words */ 00475 if (multi) printf("[#%d %s]\n", r->config->id, r->config->name); 00476 printf("pass1_best:"); 00477 if (r->config->output.progout_flag) { 00478 len = 0; 00479 for (i=0;i<num;i++) { 00480 len += strlen(winfo->woutput[seq[i]]) + 1; 00481 myprintf(" %s",winfo->woutput[seq[i]]); 00482 } 00483 for(j=len;j<writelen;j++) printf(" "); 00484 } else { 00485 for (i=0;i<num;i++) { 00486 myprintf(" %s",winfo->woutput[seq[i]]); 00487 } 00488 } 00489 printf("\n"); 00490 00491 if (verbose_flag) { /* output further info */ 00492 /* N-gram entries */ 00493 printf("pass1_best_wordseq:"); 00494 for (i=0;i<num;i++) { 00495 myprintf(" %s",winfo->wname[seq[i]]); 00496 } 00497 printf("\n"); 00498 /* phoneme sequence */ 00499 printf("pass1_best_phonemeseq:"); 00500 for (i=0;i<num;i++) { 00501 for (j=0;j<winfo->wlen[seq[i]];j++) { 00502 center_name(winfo->wseq[seq[i]][j]->name, buf); 00503 myprintf(" %s", buf); 00504 } 00505 if (i < num-1) printf(" |"); 00506 } 00507 printf("\n"); 00508 if (debug2_flag) { 00509 /* logical HMMs */ 00510 printf("pass1_best_HMMseq_logical:"); 00511 for (i=0;i<num;i++) { 00512 for (j=0;j<winfo->wlen[seq[i]];j++) { 00513 myprintf(" %s", winfo->wseq[seq[i]][j]->name); 00514 } 00515 if (i < num-1) printf(" |"); 00516 } 00517 printf("\n"); 00518 } 00519 /* score */ 00520 printf("pass1_best_score: %f", r->result.pass1.score); 00521 if (r->lmtype == LM_PROB) { 00522 if (separate_score_flag) { 00523 printf(" (AM: %f LM: %f)", 00524 r->result.pass1.score_am, 00525 r->result.pass1.score_lm); 00526 } 00527 } 00528 printf("\n"); 00529 } 00530 //printf("\n"); 00531 } 00532 } 00533 00534 #ifdef WORD_GRAPH 00535 static void 00536 result_pass1_graph(Recog *recog, void *dummy) 00537 { 00538 WordGraph *wg; 00539 WORD_INFO *winfo; 00540 RecogProcess *r; 00541 boolean multi; 00542 int n; 00543 int tw1, tw2, i; 00544 00545 if (recog->process_list->next != NULL) multi = TRUE; 00546 else multi = FALSE; 00547 00548 for(r=recog->process_list;r;r=r->next) { 00549 if (! r->live) continue; 00550 if (r->result.wg1 == NULL) continue; 00551 if (multi) printf("[#%d %s]\n", r->config->id, r->config->name); 00552 printf("--- begin wordgraph data pass1 ---\n"); 00553 00554 winfo = r->lm->winfo; 00555 /* debug: output all graph word info */ 00556 wordgraph_dump(stdout, r->result.wg1, winfo); 00557 for(wg=r->result.wg1;wg;wg=wg->next) { 00558 tw1 = (TEXTWIDTH * wg->lefttime) / recog->peseqlen; 00559 tw2 = (TEXTWIDTH * wg->righttime) / recog->peseqlen; 00560 printf("%4d:", wg->id); 00561 for(i=0;i<tw1;i++) printf(" "); 00562 myprintf(" %s\n", winfo->woutput[wg->wid]); 00563 printf("%4d:", wg->lefttime); 00564 for(i=0;i<tw1;i++) printf(" "); 00565 printf("|"); 00566 for(i=tw1+1;i<tw2;i++) printf("-"); 00567 printf("|\n"); 00568 } 00569 printf("--- end wordgraph data pass1 ---\n"); 00570 00571 } 00572 } 00573 00574 #endif 00575 00586 static void 00587 status_pass1_end(Recog *recog, void *dummy) 00588 { 00589 if (recog->jconf->decodeopt.segment) { /* short pause segmentation */ 00590 if (have_progout) return; 00591 } 00592 /* no op */ 00593 //printf("\n"); 00594 } 00595 00596 /**********************************************************************/ 00597 /* 2nd pass output */ 00598 00613 static void 00614 put_hypo_woutput(WORD_ID *seq, int n, WORD_INFO *winfo) 00615 { 00616 int i; 00617 00618 if (seq != NULL) { 00619 for (i=0;i<n;i++) { 00620 myprintf(" %s",winfo->woutput[seq[i]]); 00621 } 00622 } 00623 printf("\n"); 00624 } 00625 00640 static void 00641 put_hypo_wname(WORD_ID *seq, int n, WORD_INFO *winfo) 00642 { 00643 int i; 00644 00645 if (seq != NULL) { 00646 for (i=0;i<n;i++) { 00647 myprintf(" %s",winfo->wname[seq[i]]); 00648 } 00649 } 00650 printf("\n"); 00651 } 00652 00667 static void 00668 put_hypo_phoneme(WORD_ID *seq, int n, WORD_INFO *winfo) 00669 { 00670 int i,j; 00671 WORD_ID w; 00672 static char buf[MAX_HMMNAME_LEN]; 00673 00674 if (seq != NULL) { 00675 for (i=0;i<n;i++) { 00676 if (i > 0) printf(" |"); 00677 w = seq[i]; 00678 for (j=0;j<winfo->wlen[w];j++) { 00679 center_name(winfo->wseq[w][j]->name, buf); 00680 myprintf(" %s", buf); 00681 } 00682 } 00683 } 00684 printf("\n"); 00685 } 00686 #ifdef CONFIDENCE_MEASURE 00687 00699 #ifdef CM_MULTIPLE_ALPHA 00700 static void 00701 put_hypo_cmscore(NODE *hypo, int id) 00702 { 00703 int i; 00704 int j; 00705 00706 if (hypo != NULL) { 00707 for (i=hypo->seqnum-1;i>=0;i--) { 00708 printf(" %5.3f", hypo->cmscore[i][id]); 00709 } 00710 } 00711 printf("\n"); 00712 } 00713 #else 00714 static void 00715 put_hypo_cmscore(LOGPROB *cmscore, int n) 00716 { 00717 int i; 00718 00719 if (cmscore != NULL) { 00720 for (i=0;i<n;i++) { 00721 printf(" %5.3f", cmscore[i]); 00722 } 00723 } 00724 printf("\n"); 00725 } 00726 #endif 00727 #endif /* CONFIDENCE_MEASURE */ 00728 00745 static void 00746 //ttyout_pass2(NODE *hypo, int rank, Recog *recog) 00747 result_pass2(Recog *recog, void *dummy) 00748 { 00749 int i, j; 00750 int len; 00751 char ec[5] = {0x1b, '[', '1', 'm', 0}; 00752 WORD_INFO *winfo; 00753 WORD_ID *seq; 00754 int seqnum; 00755 int n, num; 00756 Sentence *s; 00757 RecogProcess *r; 00758 boolean multi; 00759 HMM_Logical *p; 00760 SentenceAlign *align; 00761 00762 if (recog->process_list->next != NULL) multi = TRUE; 00763 else multi = FALSE; 00764 00765 for(r=recog->process_list;r;r=r->next) { 00766 if (! r->live) continue; 00767 if (multi) printf("[#%d %s]\n", r->config->id, r->config->name); 00768 00769 if (r->config->successive.enabled) { /* short pause segmentation */ 00770 if (r->result.status < 0 && r->config->output.progout_flag) { 00771 /* search failed */ 00772 00773 printf("\r"); 00774 winfo = r->lm->winfo; 00775 00776 if (r->result.status == J_RESULT_STATUS_FAIL) { 00777 /* search fail */ 00778 /* output pass1 result as final */ 00779 seq = r->result.pass1.word; 00780 seqnum = r->result.pass1.word_num; 00781 j = 0; 00782 /* skip output if head word is the same as previous segment */ 00783 if (confword[confwordnum-1] == seq[0]) j++; 00784 00785 /* store 1st pass result as final */ 00786 for (i=j;i<seqnum;i++) { 00787 confword[confwordnum++] = seq[i]; 00788 } 00789 } /* else (rejection), output nothing new */ 00790 00791 len = 0; 00792 /* output all confirmed words */ 00793 for(i=0;i<confwordnum;i++) { 00794 if (len + strlen(winfo->woutput[confword[i]]) > SPTEXTWIDTH) { 00795 for(j=len;j<writelen;j++) printf(" "); 00796 printf("\n"); 00797 for(j=i;j<confwordnum;j++) confword[j-i] = confword[j]; 00798 confwordnum -= i; 00799 len = 0; 00800 i = 0; 00801 writelen = 0; 00802 } 00803 myprintf("%s", winfo->woutput[confword[i]]); 00804 len += strlen(winfo->woutput[confword[i]]); 00805 } 00806 for(i=len;i<writelen;i++) printf(" "); 00807 fflush(stdout); 00808 00809 continue; 00810 } 00811 } 00812 00813 if (r->result.status < 0) { 00814 switch(r->result.status) { 00815 case J_RESULT_STATUS_REJECT_POWER: 00816 printf("<input rejected by power>\n"); 00817 break; 00818 case J_RESULT_STATUS_TERMINATE: 00819 printf("<input teminated by request>\n"); 00820 break; 00821 case J_RESULT_STATUS_ONLY_SILENCE: 00822 printf("<input rejected by decoder (silence input result)>\n"); 00823 break; 00824 case J_RESULT_STATUS_REJECT_GMM: 00825 printf("<input rejected by GMM>\n"); 00826 break; 00827 case J_RESULT_STATUS_REJECT_SHORT: 00828 printf("<input rejected by short input>\n"); 00829 break; 00830 case J_RESULT_STATUS_FAIL: 00831 printf("<search failed>\n"); 00832 break; 00833 } 00834 continue; 00835 } 00836 00837 winfo = r->lm->winfo; 00838 num = r->result.sentnum; 00839 00840 for(n=0;n<num;n++) { 00841 s = &(r->result.sent[n]); 00842 seq = s->word; 00843 seqnum = s->word_num; 00844 00845 if (r->config->successive.enabled) { /* short pause segmentation */ 00846 if (r->config->output.progout_flag) { 00847 printf("\r"); 00848 00849 j = 0; 00850 /* skip output if head word is the same as previous segment */ 00851 if (confword[confwordnum-1] == seq[0]) j++; 00852 for (i=j;i<seqnum;i++) { 00853 confword[confwordnum++] = seq[i]; 00854 } 00855 00856 /* output all confirmed words */ 00857 len = 0; 00858 for(i=0;i<confwordnum;i++) { 00859 if (len + strlen(winfo->woutput[confword[i]]) > SPTEXTWIDTH) { 00860 for(j=len;j<writelen;j++) printf(" "); 00861 printf("\n"); 00862 for(j=i;j<confwordnum;j++) confword[j-i] = confword[j]; 00863 confwordnum -= i; 00864 len = 0; 00865 i = 0; 00866 writelen = 0; 00867 } 00868 myprintf("%s", winfo->woutput[confword[i]]); 00869 len += strlen(winfo->woutput[confword[i]]); 00870 } 00871 for(i=len;i<writelen;i++) printf(" "); 00872 00873 break; 00874 } 00875 } 00876 00877 if (debug2_flag) { 00878 printf("\n%s",ec); /* newline & bold on */ 00879 } 00880 printf("sentence%d:", n+1); 00881 put_hypo_woutput(seq, seqnum, winfo); 00882 if (verbose_flag) { 00883 printf("wseq%d:", n+1); 00884 put_hypo_wname(seq, seqnum, winfo); 00885 printf("phseq%d:", n+1); 00886 put_hypo_phoneme(seq, seqnum, winfo); 00887 #ifdef CONFIDENCE_MEASURE 00888 #ifdef CM_MULTIPLE_ALPHA 00889 { 00890 int i; 00891 for(i=0;i<r->config->annotate.cm_alpha_num;i++) { 00892 printf("cmscore%d[%f]:", rank, r->config->annotate.cm_alpha_bgn + i * r->config->annotate.cm_alpha_step); 00893 put_hypo_cmscore(hypo, i); 00894 } 00895 } 00896 #else 00897 printf("cmscore%d:", n+1); 00898 put_hypo_cmscore(s->confidence, seqnum); 00899 #endif 00900 #endif /* CONFIDENCE_MEASURE */ 00901 } 00902 if (debug2_flag) { 00903 ec[2] = '0'; 00904 printf("%s\n",ec); /* bold off & newline */ 00905 } 00906 if (verbose_flag) { 00907 printf("score%d: %f", n+1, s->score); 00908 if (r->lmtype == LM_PROB) { 00909 if (separate_score_flag) { 00910 printf(" (AM: %f LM: %f)", s->score_am, s->score_lm); 00911 } 00912 } 00913 printf("\n"); 00914 if (r->lmtype == LM_DFA) { 00915 /* output which grammar the hypothesis belongs to on multiple grammar */ 00916 /* determine only by the last word */ 00917 if (multigram_get_all_num(r->lm) > 1) { 00918 printf("grammar%d: %d\n", n+1, s->gram_id); 00919 } 00920 } 00921 } 00922 00923 /* output alignment result if exist */ 00924 for (align = s->align; align; align = align->next) { 00925 printf("=== begin forced alignment ===\n"); 00926 switch(align->unittype) { 00927 case PER_WORD: 00928 printf("-- word alignment --\n"); break; 00929 case PER_PHONEME: 00930 printf("-- phoneme alignment --\n"); break; 00931 case PER_STATE: 00932 printf("-- state alignment --\n"); break; 00933 } 00934 printf(" id: from to n_score unit\n"); 00935 printf(" ----------------------------------------\n"); 00936 for(i=0;i<align->num;i++) { 00937 printf("[%4d %4d] %f ", align->begin_frame[i], align->end_frame[i], align->avgscore[i]); 00938 switch(align->unittype) { 00939 case PER_WORD: 00940 myprintf("%s\t[%s]\n", winfo->wname[align->w[i]], winfo->woutput[align->w[i]]); 00941 break; 00942 case PER_PHONEME: 00943 p = align->ph[i]; 00944 if (p->is_pseudo) { 00945 printf("{%s}\n", p->name); 00946 } else if (strmatch(p->name, p->body.defined->name)) { 00947 printf("%s\n", p->name); 00948 } else { 00949 printf("%s[%s]\n", p->name, p->body.defined->name); 00950 } 00951 break; 00952 case PER_STATE: 00953 p = align->ph[i]; 00954 if (p->is_pseudo) { 00955 printf("{%s}", p->name); 00956 } else if (strmatch(p->name, p->body.defined->name)) { 00957 printf("%s", p->name); 00958 } else { 00959 printf("%s[%s]", p->name, p->body.defined->name); 00960 } 00961 if (r->am->hmminfo->multipath) { 00962 if (align->is_iwsp[i]) { 00963 printf(" #%d (sp)\n", align->loc[i]); 00964 } else { 00965 printf(" #%d\n", align->loc[i]); 00966 } 00967 } else { 00968 printf(" #%d\n", align->loc[i]); 00969 } 00970 break; 00971 } 00972 } 00973 00974 printf("re-computed AM score: %f\n", align->allscore); 00975 00976 printf("=== end forced alignment ===\n"); 00977 } 00978 } 00979 } 00980 00981 fflush(stdout); 00982 00983 } 00984 00997 static void 00998 status_pass2_begin(Recog *recog, void *dummy) 00999 { 01000 VERMES("### Recognition: 2nd pass (RL heuristic best-first)\n"); 01001 //if (verbose_flag) printf("samplenum=%d\n", recog->param->samplenum); 01002 //if (debug2_flag) VERMES("getting %d candidates...\n", recog->jconf->search.pass2.nbest); 01003 } 01004 01015 static void 01016 status_pass2_end(Recog *recog, void *dummy) 01017 { 01018 fflush(stdout); 01019 } 01020 01021 /**********************************************************************/ 01022 /* word graph output */ 01023 01024 #define TEXTWIDTH 70 01025 01040 static void 01041 result_graph(Recog *recog, void *dummy) 01042 { 01043 WordGraph *wg; 01044 int tw1, tw2, i; 01045 WORD_INFO *winfo; 01046 RecogProcess *r; 01047 boolean multi; 01048 01049 if (recog->process_list->next != NULL) multi = TRUE; 01050 else multi = FALSE; 01051 01052 for(r=recog->process_list;r;r=r->next) { 01053 if (! r->live) continue; 01054 if (r->result.wg == NULL) continue; /* no graphout specified */ 01055 if (multi) printf("[#%d %s]\n", r->config->id, r->config->name); 01056 01057 winfo = r->lm->winfo; 01058 01059 /* debug: output all graph word info */ 01060 wordgraph_dump(stdout, r->result.wg, winfo); 01061 01062 printf("-------------------------- begin wordgraph show -------------------------\n"); 01063 for(wg=r->result.wg;wg;wg=wg->next) { 01064 tw1 = (TEXTWIDTH * wg->lefttime) / r->peseqlen; 01065 tw2 = (TEXTWIDTH * wg->righttime) / r->peseqlen; 01066 printf("%4d:", wg->id); 01067 for(i=0;i<tw1;i++) printf(" "); 01068 myprintf(" %s\n", winfo->woutput[wg->wid]); 01069 printf("%4d:", wg->lefttime); 01070 for(i=0;i<tw1;i++) printf(" "); 01071 printf("|"); 01072 for(i=tw1+1;i<tw2;i++) printf("-"); 01073 printf("|\n"); 01074 } 01075 printf("-------------------------- end wordgraph show ---------------------------\n"); 01076 } 01077 } 01078 01089 static void 01090 result_confnet(Recog *recog, void *dummy) 01091 { 01092 CN_CLUSTER *c; 01093 int i; 01094 RecogProcess *r; 01095 boolean multi; 01096 01097 if (recog->process_list->next != NULL) multi = TRUE; 01098 else multi = FALSE; 01099 01100 for(r=recog->process_list;r;r=r->next) { 01101 if (! r->live) continue; 01102 if (r->result.confnet == NULL) continue; /* no confnet obtained */ 01103 if (multi) printf("[#%d %s]\n", r->config->id, r->config->name); 01104 01105 printf("---- begin confusion network ---\n"); 01106 for(c=r->result.confnet;c;c=c->next) { 01107 for(i=0;i<c->wordsnum;i++) { 01108 myprintf("(%s:%.3f)", (c->words[i] == WORD_INVALID) ? "-" : r->lm->winfo->woutput[c->words[i]], c->pp[i]); 01109 if (i == 0) printf(" "); 01110 } 01111 printf("\n"); 01112 #if 0 01113 /* output details - break down all words clustered into this class */ 01114 for(i=0;i<c->wgnum;i++) { 01115 printf(" "); 01116 put_wordgraph(stdout, c->wg[i], r->lm->winfo); 01117 } 01118 #endif 01119 } 01120 printf("---- end confusion network ---\n"); 01121 } 01122 } 01123 01124 /********************* RESULT OUTPUT FOR GMM *************************/ 01134 static void 01135 result_gmm(Recog *recog, void *dummy) 01136 { 01137 HTK_HMM_Data *d; 01138 GMMCalc *gc; 01139 int i; 01140 01141 gc = recog->gc; 01142 01143 if (debug2_flag) { 01144 printf("--- GMM result begin ---\n"); 01145 i = 0; 01146 for(d=recog->gmm->start;d;d=d->next) { 01147 myprintf(" [%8s: total=%f avg=%f]\n", d->name, gc->gmm_score[i], gc->gmm_score[i] / (float)gc->framecount); 01148 i++; 01149 } 01150 myprintf(" max = \"%s\"", gc->max_d->name); 01151 #ifdef CONFIDENCE_MEASURE 01152 printf(" (CM: %f)", gc->gmm_max_cm); 01153 #endif 01154 printf("\n"); 01155 printf("--- GMM result end ---\n"); 01156 } else if (verbose_flag) { 01157 myprintf("GMM: max = \"%s\"", gc->max_d->name); 01158 #ifdef CONFIDENCE_MEASURE 01159 printf(" (CM: %f)", gc->gmm_max_cm); 01160 #endif 01161 printf("\n"); 01162 } else { 01163 if (recog->jconf->decodeopt.segment) { /* short pause segmentation */ 01164 if (!have_progout) { 01165 myprintf("[GMM: %s]\n", gc->max_d->name); 01166 } 01167 } else { 01168 myprintf("[GMM: %s]\n", gc->max_d->name); 01169 } 01170 } 01171 } 01172 01183 void 01184 print_all_gram(Recog *recog) 01185 { 01186 MULTIGRAM *m; 01187 RecogProcess *r; 01188 boolean multi; 01189 char buf[1024]; 01190 01191 if (recog->process_list->next != NULL) multi = TRUE; 01192 else multi = FALSE; 01193 01194 for(r=recog->process_list;r;r=r->next) { 01195 if (! r->live) continue; 01196 if (multi) printf("[#%d %s]\n", r->config->id, r->config->name); 01197 if (r->lmtype == LM_PROB) { 01198 printf("NOT A GRAMMAR-BASED LM\n"); 01199 continue; 01200 } 01201 printf("[grammars]\n"); 01202 for(m=r->lm->grammars;m;m=m->next) { 01203 buf[0] = '\0'; 01204 if (m->dfa) { 01205 snprintf(buf, 1024, ", %3d categories, %4d nodes", 01206 m->dfa->term_num, m->dfa->state_num); 01207 } 01208 if (m->newbie) strcat(buf, " (new)"); 01209 if (m->hook != 0) { 01210 strcat(buf, " (next:"); 01211 if (m->hook & MULTIGRAM_DELETE) { 01212 strcat(buf, " delete"); 01213 } 01214 if (m->hook & MULTIGRAM_ACTIVATE) { 01215 strcat(buf, " activate"); 01216 } 01217 if (m->hook & MULTIGRAM_DEACTIVATE) { 01218 strcat(buf, " deactivate"); 01219 } 01220 if (m->hook & MULTIGRAM_MODIFIED) { 01221 strcat(buf, " modified"); 01222 } 01223 strcat(buf, ")"); 01224 } 01225 myprintf(" #%2d: [%-11s] %4d words%s \"%s\"\n", 01226 m->id, 01227 m->active ? "active" : "inactive", 01228 m->winfo->num, 01229 buf, 01230 m->name); 01231 } 01232 if (r->lm->dfa != NULL) { 01233 printf(" Global: %4d words, %3d categories, %4d nodes\n", r->lm->winfo->num, r->lm->dfa->term_num, r->lm->dfa->state_num); 01234 } 01235 } 01236 } 01237 01238 static void 01239 levelmeter(Recog *recog, SP16 *buf, int len, void *dummy) 01240 { 01241 float d; 01242 int level; 01243 int i, n; 01244 01245 level = 0; 01246 for(i=0;i<len;i++) { 01247 if (level < buf[i]) level = buf[i]; 01248 } 01249 01250 d = log((float)(level+1)) / 10.3971466; /* 10.3971466 = log(32767) */ 01251 01252 n = d * 8.0; 01253 fprintf(stderr, "\r"); 01254 for(i=0;i<n;i++) fprintf(stderr, ">"); 01255 01256 } 01257 01258 01259 static void 01260 frame_indicator(Recog *recog, void *dummy) 01261 { 01262 RecogProcess *r; 01263 01264 if (recog->jconf->decodeopt.segment) { 01265 for(r=recog->process_list;r;r=r->next) { 01266 if (! r->live) continue; 01267 if (r->pass1.in_sparea) { 01268 fprintf(stderr, "."); 01269 break; 01270 } 01271 } 01272 if (!r) { 01273 fprintf(stderr, "-"); 01274 } 01275 } else { 01276 fprintf(stderr, "."); 01277 } 01278 } 01279 01280 01281 void 01282 setup_output_tty(Recog *recog, void *data) 01283 { 01284 callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, status_process_online, data); 01285 callback_add(recog, CALLBACK_EVENT_PROCESS_OFFLINE, status_process_offline, data); 01286 callback_add(recog, CALLBACK_EVENT_SPEECH_READY, status_recready, data); 01287 callback_add(recog, CALLBACK_EVENT_SPEECH_START, status_recstart, data); 01288 callback_add(recog, CALLBACK_EVENT_SPEECH_STOP, status_recend, data); 01289 callback_add(recog, CALLBACK_EVENT_RECOGNITION_BEGIN, status_recognition_begin, data); 01290 callback_add(recog, CALLBACK_EVENT_RECOGNITION_END, status_recognition_end, data); 01291 if (recog->jconf->decodeopt.segment) { /* short pause segmentation */ 01292 callback_add(recog, CALLBACK_EVENT_SEGMENT_BEGIN, status_segment_begin, data); 01293 callback_add(recog, CALLBACK_EVENT_SEGMENT_END, status_segment_end, data); 01294 } 01295 callback_add(recog, CALLBACK_EVENT_PASS1_BEGIN, status_pass1_begin, data); 01296 { 01297 JCONF_SEARCH *s; 01298 boolean ok_p; 01299 ok_p = TRUE; 01300 for(s=recog->jconf->search_root;s;s=s->next) { 01301 if (s->output.progout_flag) ok_p = FALSE; 01302 } 01303 if (ok_p) { 01304 have_progout = FALSE; 01305 } else { 01306 have_progout = TRUE; 01307 } 01308 } 01309 if (!recog->jconf->decodeopt.realtime_flag && verbose_flag && ! have_progout) { 01310 callback_add(recog, CALLBACK_EVENT_PASS1_FRAME, frame_indicator, data); 01311 } 01312 callback_add(recog, CALLBACK_RESULT_PASS1_INTERIM, result_pass1_current, data); 01313 callback_add(recog, CALLBACK_RESULT_PASS1, result_pass1, data); 01314 #ifdef WORD_GRAPH 01315 callback_add(recog, CALLBACK_RESULT_PASS1_GRAPH, result_pass1_graph, data); 01316 #endif 01317 callback_add(recog, CALLBACK_EVENT_PASS1_END, status_pass1_end, data); 01318 callback_add(recog, CALLBACK_STATUS_PARAM, status_param, data); 01319 callback_add(recog, CALLBACK_EVENT_PASS2_BEGIN, status_pass2_begin, data); 01320 callback_add(recog, CALLBACK_EVENT_PASS2_END, status_pass2_end, data); 01321 callback_add(recog, CALLBACK_RESULT, result_pass2, data); // rejected, failed 01322 callback_add(recog, CALLBACK_RESULT_GMM, result_gmm, data); 01323 /* below will be called when "-lattice" is specified */ 01324 callback_add(recog, CALLBACK_RESULT_GRAPH, result_graph, data); 01325 /* below will be called when "-confnet" is specified */ 01326 callback_add(recog, CALLBACK_RESULT_CONFNET, result_confnet, data); 01327 01328 //callback_add_adin(CALLBACK_ADIN_CAPTURED, levelmeter, data); 01329 }