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 #include <time.h> 00028 00029 extern int module_sd; 00030 extern boolean separate_score_flag; 00031 00032 /**********************************************************************/ 00033 /* process online/offline status */ 00034 00045 static void 00046 status_process_online(Recog *recog, void *dummy) 00047 { 00048 module_send(module_sd, "<STARTPROC/>\n.\n"); 00049 } 00060 static void 00061 status_process_offline(Recog *recog, void *dummy) 00062 { 00063 module_send(module_sd, "<STOPPROC/>\n.\n"); 00064 } 00065 00066 /**********************************************************************/ 00067 /* decode outcode "WLPSwlps" to each boolean value */ 00068 /* default: "WLPS" */ 00069 static boolean out1_word = FALSE, out1_lm = FALSE, out1_phone = FALSE, out1_score = FALSE; 00070 static boolean out2_word = TRUE, out2_lm = TRUE, out2_phone = TRUE, out2_score = TRUE; 00071 static boolean out1_never = TRUE, out2_never = FALSE; 00072 #ifdef CONFIDENCE_MEASURE 00073 static boolean out2_cm = TRUE; 00074 #endif 00075 00088 void 00089 decode_output_selection(char *str) 00090 { 00091 int i; 00092 out1_word = out1_lm = out1_phone = out1_score = FALSE; 00093 out2_word = out2_lm = out2_phone = out2_score = FALSE; 00094 #ifdef CONFIDENCE_MEASURE 00095 out2_cm = FALSE; 00096 #endif 00097 for(i = strlen(str) - 1; i >= 0; i--) { 00098 switch(str[i]) { 00099 case 'W': out2_word = TRUE; break; 00100 case 'L': out2_lm = TRUE; break; 00101 case 'P': out2_phone = TRUE; break; 00102 case 'S': out2_score = TRUE; break; 00103 case 'w': out1_word = TRUE; break; 00104 case 'l': out1_lm = TRUE; break; 00105 case 'p': out1_phone = TRUE; break; 00106 case 's': out1_score = TRUE; break; 00107 #ifdef CONFIDENCE_MEASURE 00108 case 'C': out2_cm = TRUE; break; 00109 #endif 00110 default: 00111 fprintf(stderr, "Error: unknown outcode `%c', ignored\n", str[i]); 00112 break; 00113 } 00114 } 00115 out1_never = ! (out1_word | out1_lm | out1_phone | out1_score); 00116 out2_never = ! (out2_word | out2_lm | out2_phone | out2_score 00117 #ifdef CONFIDENCE_MEASURE 00118 | out2_cm 00119 #endif 00120 ); 00121 00122 } 00123 00138 static void 00139 msock_word_out1(WORD_ID w, RecogProcess *r) 00140 { 00141 int j; 00142 static char buf[MAX_HMMNAME_LEN]; 00143 WORD_INFO *winfo; 00144 00145 winfo = r->lm->winfo; 00146 00147 if (out1_word) { 00148 module_send(module_sd, " WORD=\"%s\"", winfo->woutput[w]); 00149 } 00150 if (out1_lm) { 00151 module_send(module_sd, " CLASSID=\"%s\"", winfo->wname[w]); 00152 } 00153 if (out1_phone) { 00154 module_send(module_sd, " PHONE=\""); 00155 for(j=0;j<winfo->wlen[w];j++) { 00156 center_name(winfo->wseq[w][j]->name, buf); 00157 if (j == 0) module_send(module_sd, "%s", buf); 00158 else module_send(module_sd, " %s", buf); 00159 } 00160 module_send(module_sd, "\""); 00161 } 00162 } 00163 00178 static void 00179 msock_word_out2(WORD_ID w, RecogProcess *r) 00180 { 00181 int j; 00182 static char buf[MAX_HMMNAME_LEN]; 00183 WORD_INFO *winfo; 00184 00185 winfo = r->lm->winfo; 00186 00187 if (out2_word) { 00188 module_send(module_sd, " WORD=\"%s\"", winfo->woutput[w]); 00189 } 00190 if (out2_lm) { 00191 module_send(module_sd, " CLASSID=\"%s\"", winfo->wname[w]); 00192 } 00193 if (out2_phone) { 00194 module_send(module_sd, " PHONE=\""); 00195 for(j=0;j<winfo->wlen[w];j++) { 00196 center_name(winfo->wseq[w][j]->name, buf); 00197 if (j == 0) module_send(module_sd, "%s", buf); 00198 else module_send(module_sd, " %s", buf); 00199 } 00200 module_send(module_sd, "\""); 00201 } 00202 } 00203 00204 00205 /**********************************************************************/ 00206 /* 1st pass output */ 00207 00218 static void 00219 status_pass1_begin(Recog *recog, void *dummy) 00220 { 00221 module_send(module_sd, "<STARTRECOG/>\n.\n"); 00222 } 00223 00246 static void 00247 result_pass1_current(Recog *recog, void *dummy) 00248 { 00249 int i; 00250 WORD_INFO *winfo; 00251 WORD_ID *seq; 00252 int num; 00253 RecogProcess *r; 00254 boolean multi; 00255 00256 if (out1_never) return; /* no output specified */ 00257 00258 if (recog->process_list->next != NULL) multi = TRUE; 00259 else multi = FALSE; 00260 00261 for(r=recog->process_list;r;r=r->next) { 00262 if (! r->live) continue; 00263 if (! r->have_interim) continue; 00264 00265 winfo = r->lm->winfo; 00266 seq = r->result.pass1.word; 00267 num = r->result.pass1.word_num; 00268 00269 if (multi) { 00270 module_send(module_sd, "<RECOGOUT ID=\"SR%02d\" NAME=\"%s\">\n", r->config->id, r->config->name); 00271 } else { 00272 module_send(module_sd, "<RECOGOUT>\n"); 00273 } 00274 if (out1_score) { 00275 module_send(module_sd, " <PHYPO PASS=\"1\" SCORE=\"%f\" FRAME=\"%d\" TIME=\"%ld\"/>\n", r->result.pass1.score, r->result.num_frame, time(NULL)); 00276 } else { 00277 module_send(module_sd, " <PHYPO PASS=\"1\" FRAME=\"%d\" TIME=\"%ld\"/>\n", r->result.num_frame, time(NULL)); 00278 } 00279 for (i=0;i<num;i++) { 00280 module_send(module_sd, " <WHYPO"); 00281 msock_word_out1(seq[i], r); 00282 module_send(module_sd, "/>\n"); 00283 } 00284 module_send(module_sd, " </PHYPO>\n</RECOGOUT>\n.\n"); 00285 } 00286 } 00287 00311 static void 00312 result_pass1_final(Recog *recog, void *dummy) 00313 { 00314 int i; 00315 RecogProcess *r; 00316 boolean multi; 00317 00318 if (out1_never) return; /* no output specified */ 00319 00320 if (recog->process_list->next != NULL) multi = TRUE; 00321 else multi = FALSE; 00322 00323 for(r=recog->process_list;r;r=r->next) { 00324 if (! r->live) continue; 00325 if (r->result.status < 0) continue; /* search already failed */ 00326 00327 if (multi) { 00328 module_send(module_sd, "<RECOGOUT ID=\"SR%02d\" NAME=\"%s\">\n", r->config->id, r->config->name); 00329 } else { 00330 module_send(module_sd, "<RECOGOUT>\n"); 00331 } 00332 if (out1_score) { 00333 module_send(module_sd, " <SHYPO PASS=\"1\" SCORE=\"%f\">\n", r->result.pass1.score); 00334 } else { 00335 module_send(module_sd, " <SHYPO PASS=\"1\">\n", r->result.pass1.score); 00336 } 00337 for (i=0;i<r->result.pass1.word_num;i++) { 00338 module_send(module_sd, " <WHYPO"); 00339 msock_word_out1(r->result.pass1.word[i], r); 00340 module_send(module_sd, "/>\n"); 00341 } 00342 module_send(module_sd, " </SHYPO>\n</RECOGOUT>\n.\n"); 00343 } 00344 } 00345 00356 static void 00357 status_pass1_end(Recog *recog, void *dummy) 00358 { 00359 module_send(module_sd, "<ENDRECOG/>\n.\n"); 00360 } 00361 00362 /**********************************************************************/ 00363 /* 2nd pass output */ 00364 00381 static void 00382 result_pass2(Recog *recog, void *dummy) 00383 { 00384 int i, n, num; 00385 WORD_INFO *winfo; 00386 WORD_ID *seq; 00387 int seqnum; 00388 Sentence *s; 00389 RecogProcess *r; 00390 boolean multi; 00391 SentenceAlign *align; 00392 00393 if (recog->process_list->next != NULL) multi = TRUE; 00394 else multi = FALSE; 00395 00396 for(r=recog->process_list;r;r=r->next) { 00397 if (! r->live) continue; 00398 00399 if (r->result.status < 0) { 00400 switch(r->result.status) { 00401 case J_RESULT_STATUS_REJECT_POWER: 00402 module_send(module_sd, "<REJECTED REASON=\"by power\""); 00403 break; 00404 case J_RESULT_STATUS_TERMINATE: 00405 module_send(module_sd, "<REJECTED REASON=\"input terminated by request\""); 00406 break; 00407 case J_RESULT_STATUS_ONLY_SILENCE: 00408 module_send(module_sd, "<REJECTED REASON=\"result has pause words only\""); 00409 break; 00410 case J_RESULT_STATUS_REJECT_GMM: 00411 module_send(module_sd, "<REJECTED REASON=\"by GMM\""); 00412 break; 00413 case J_RESULT_STATUS_REJECT_SHORT: 00414 module_send(module_sd, "<REJECTED REASON=\"too short input\""); 00415 break; 00416 case J_RESULT_STATUS_FAIL: 00417 module_send(module_sd, "<RECOGFAIL"); 00418 break; 00419 } 00420 if (multi) { 00421 module_send(module_sd, " ID=\"SR%02d\" NAME=\"%s\"", r->config->id, r->config->name); 00422 } 00423 module_send(module_sd, "/>\n.\n"); 00424 continue; 00425 } 00426 00427 if (out2_never) continue; /* no output specified */ 00428 00429 winfo = r->lm->winfo; 00430 num = r->result.sentnum; 00431 00432 if (multi) { 00433 module_send(module_sd, "<RECOGOUT ID=\"SR%02d\" NAME=\"%s\">\n", r->config->id, r->config->name); 00434 } else { 00435 module_send(module_sd, "<RECOGOUT>\n"); 00436 } 00437 for(n=0;n<num;n++) { 00438 s = &(r->result.sent[n]); 00439 seq = s->word; 00440 seqnum = s->word_num; 00441 00442 module_send(module_sd, " <SHYPO RANK=\"%d\"", n+1); 00443 if (out2_score) { 00444 module_send(module_sd, " SCORE=\"%f\"", s->score); 00445 if (r->lmtype == LM_PROB) { 00446 if (separate_score_flag) { 00447 module_send(module_sd, " AMSCORE=\"%f\" LMSCORE=\"%f\"", s->score_am, s->score_lm); 00448 } 00449 } 00450 } 00451 if (r->lmtype == LM_DFA) { 00452 /* output which grammar the best hypothesis belongs to */ 00453 module_send(module_sd, " GRAM=\"%d\"", s->gram_id); 00454 } 00455 00456 module_send(module_sd, ">\n"); 00457 for (i=0;i<seqnum;i++) { 00458 module_send(module_sd, " <WHYPO"); 00459 msock_word_out2(seq[i], r); 00460 #ifdef CONFIDENCE_MEASURE 00461 #ifdef CM_MULTIPLE_ALPHA 00462 /* currently not handle multiple alpha output */ 00463 #else 00464 if (out2_cm) { 00465 module_send(module_sd, " CM=\"%5.3f\"", s->confidence[i]); 00466 } 00467 #endif 00468 #endif /* CONFIDENCE_MEASURE */ 00469 /* output alignment result if exist */ 00470 for (align = s->align; align; align = align->next) { 00471 switch(align->unittype) { 00472 case PER_WORD: /* word alignment */ 00473 module_send(module_sd, " BEGINFRAME=\"%d\" ENDFRAME=\"%d\"", align->begin_frame[i], align->end_frame[i]); 00474 break; 00475 case PER_PHONEME: 00476 case PER_STATE: 00477 fprintf(stderr, "Error: \"-palign\" and \"-salign\" does not supported for module output\n"); 00478 break; 00479 } 00480 } 00481 00482 module_send(module_sd, "/>\n"); 00483 } 00484 module_send(module_sd, " </SHYPO>\n"); 00485 } 00486 module_send(module_sd, "</RECOGOUT>\n.\n"); 00487 00488 } 00489 00490 } 00491 00492 00493 /**********************************************************************/ 00494 /* word graph output */ 00495 00510 static void 00511 result_graph(Recog *recog, void *dummy) 00512 { 00513 WordGraph *wg; 00514 int i; 00515 int nodenum, arcnum; 00516 WORD_INFO *winfo; 00517 WordGraph *root; 00518 RecogProcess *r; 00519 boolean multi; 00520 00521 if (recog->process_list->next != NULL) multi = TRUE; 00522 else multi = FALSE; 00523 00524 for(r=recog->process_list;r;r=r->next) { 00525 if (! r->live) continue; 00526 if (r->result.wg == NULL) continue; /* no graph obtained */ 00527 00528 winfo = r->lm->winfo; 00529 root = r->result.wg; 00530 nodenum = r->graph_totalwordnum; 00531 arcnum = 0; 00532 for(wg=root;wg;wg=wg->next) { 00533 arcnum += wg->rightwordnum; 00534 } 00535 00536 module_send(module_sd, "<GRAPHOUT"); 00537 if (multi) module_send(module_sd, " ID=\"SR%02d\" NAME=\"%s\"", r->config->id, r->config->name); 00538 module_send(module_sd, " NODENUM=\"%d\" ARCNUM=\"%d\">\n", nodenum, arcnum); 00539 for(wg=root;wg;wg=wg->next) { 00540 module_send(module_sd, " <NODE GID=\"%d\"", wg->id); 00541 msock_word_out2(wg->wid, r); 00542 module_send(module_sd, " BEGIN=\"%d\"", wg->lefttime); 00543 module_send(module_sd, " END=\"%d\"", wg->righttime); 00544 module_send(module_sd, "/>\n"); 00545 } 00546 for(wg=root;wg;wg=wg->next) { 00547 for(i=0;i<wg->rightwordnum;i++) { 00548 module_send(module_sd, " <ARC FROM=\"%d\" TO=\"%d\"/>\n", wg->id, wg->rightword[i]->id); 00549 } 00550 } 00551 module_send(module_sd, "</GRAPHOUT>\n.\n"); 00552 } 00553 } 00554 00565 static void 00566 status_recready(Recog *recog, void *dummy) 00567 { 00568 module_send(module_sd, "<INPUT STATUS=\"LISTEN\" TIME=\"%ld\"/>\n.\n", time(NULL)); 00569 } 00570 00581 static void 00582 status_recstart(Recog *recog, void *dummy) 00583 { 00584 module_send(module_sd, "<INPUT STATUS=\"STARTREC\" TIME=\"%ld\"/>\n.\n", time(NULL)); 00585 } 00596 static void 00597 status_recend(Recog *recog, void *dummy) 00598 { 00599 module_send(module_sd, "<INPUT STATUS=\"ENDREC\" TIME=\"%ld\"/>\n.\n", time(NULL)); 00600 } 00613 static void 00614 status_param(Recog *recog, void *dummy) 00615 { 00616 MFCCCalc *mfcc; 00617 boolean multi; 00618 int frames; 00619 int msec; 00620 00621 if (recog->mfcclist->next != NULL) multi = TRUE; 00622 else multi = FALSE; 00623 00624 for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) { 00625 frames = mfcc->param->samplenum; 00626 msec = (float)mfcc->param->samplenum * (float)recog->jconf->input.period * (float)recog->jconf->input.frameshift / 10000.0; 00627 if (multi) { 00628 module_send(module_sd, "<INPUTPARAM MFCCID=\"%02d\" FRAMES=\"%d\" MSEC=\"%d\"/>\n.\n", mfcc->id, frames, msec); 00629 } else { 00630 module_send(module_sd, "<INPUTPARAM FRAMES=\"%d\" MSEC=\"%d\"/>\n.\n", frames, msec); 00631 } 00632 } 00633 } 00634 00635 /********************* RESULT OUTPUT FOR GMM *************************/ 00645 static void 00646 result_gmm(Recog *recog, void *dummy) 00647 { 00648 module_send(module_sd, "<GMM RESULT=\"%s\"", recog->gc->max_d->name); 00649 #ifdef CONFIDENCE_MEASURE 00650 module_send(module_sd, " CMSCORE=\"%f\"", recog->gc->gmm_max_cm); 00651 #endif 00652 module_send(module_sd, "/>\n.\n"); 00653 } 00654 00665 void 00666 send_gram_info(RecogProcess *r) 00667 { 00668 MULTIGRAM *m; 00669 char buf[1024]; 00670 00671 if (r->lmtype == LM_PROB) { 00672 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n"); 00673 return; 00674 } 00675 module_send(module_sd, "<GRAMINFO>\n"); 00676 for(m=r->lm->grammars;m;m=m->next) { 00677 buf[0] = '\0'; 00678 if (m->dfa) { 00679 snprintf(buf, 1024, ", %3d categories, %4d nodes", 00680 m->dfa->term_num, m->dfa->state_num); 00681 } 00682 if (m->newbie) strcat(buf, " (new)"); 00683 if (m->hook != 0) { 00684 strcat(buf, " (next:"); 00685 if (m->hook & MULTIGRAM_DELETE) { 00686 strcat(buf, " delete"); 00687 } 00688 if (m->hook & MULTIGRAM_ACTIVATE) { 00689 strcat(buf, " activate"); 00690 } 00691 if (m->hook & MULTIGRAM_DEACTIVATE) { 00692 strcat(buf, " deactivate"); 00693 } 00694 if (m->hook & MULTIGRAM_MODIFIED) { 00695 strcat(buf, " modified"); 00696 } 00697 strcat(buf, ")"); 00698 } 00699 module_send(module_sd, " #%2d: [%-11s] %4d words%s \"%s\"\n", 00700 m->id, 00701 m->active ? "active" : "inactive", 00702 m->winfo->num, 00703 buf, 00704 m->name); 00705 } 00706 if (r->lm->dfa != NULL) { 00707 module_send(module_sd, " Global: %4d words, %3d categories, %4d nodes\n", r->lm->winfo->num, r->lm->dfa->term_num, r->lm->dfa->state_num); 00708 } 00709 module_send(module_sd, "</GRAMINFO>\n.\n"); 00710 } 00711 00712 /**********************************************************************/ 00713 /* register functions for module output */ 00724 void 00725 setup_output_msock(Recog *recog, void *data) 00726 { 00727 callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, status_process_online, data); 00728 callback_add(recog, CALLBACK_EVENT_PROCESS_OFFLINE, status_process_offline, data); 00729 //callback_add(recog, CALLBACK_EVENT_STREAM_BEGIN, , data); 00730 //callback_add(recog, CALLBACK_EVENT_STREAM_END, , data); 00731 callback_add(recog, CALLBACK_EVENT_SPEECH_READY, status_recready, data); 00732 callback_add(recog, CALLBACK_EVENT_SPEECH_START, status_recstart, data); 00733 callback_add(recog, CALLBACK_EVENT_SPEECH_STOP, status_recend, data); 00734 callback_add(recog, CALLBACK_EVENT_PASS1_BEGIN, status_pass1_begin, data); 00735 callback_add(recog, CALLBACK_EVENT_PASS1_END, status_pass1_end, data); 00736 callback_add(recog, CALLBACK_RESULT_PASS1_INTERIM, result_pass1_current, data); 00737 callback_add(recog, CALLBACK_RESULT_PASS1, result_pass1_final, data); 00738 00739 callback_add(recog, CALLBACK_STATUS_PARAM, status_param, data); 00740 00741 callback_add(recog, CALLBACK_RESULT, result_pass2, data); // rejected, failed 00742 callback_add(recog, CALLBACK_RESULT_GMM, result_gmm, data); 00743 /* below will not be called if "-graphout" not specified */ 00744 callback_add(recog, CALLBACK_RESULT_GRAPH, result_graph, data); 00745 00746 //callback_add(recog, CALLBACK_EVENT_PAUSE, status_pause, data); 00747 //callback_add(recog, CALLBACK_EVENT_RESUME, status_resume, data); 00748 00749 }