Julius 4.2
julius/output_stdout.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 "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 }