00001
00018
00019
00020
00021
00022
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
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
00068
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
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;
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;
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;
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
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
00392 if (recog->process_list->next != NULL) multi = TRUE;
00393 else multi = FALSE;
00394
00395 for(r=recog->process_list;r;r=r->next) {
00396 if (! r->live) continue;
00397
00398 if (r->result.status < 0) {
00399 switch(r->result.status) {
00400 case J_RESULT_STATUS_REJECT_POWER:
00401 module_send(module_sd, "<REJECTED REASON=\"by power\"");
00402 break;
00403 case J_RESULT_STATUS_TERMINATE:
00404 module_send(module_sd, "<REJECTED REASON=\"input terminated by request\"");
00405 break;
00406 case J_RESULT_STATUS_ONLY_SILENCE:
00407 module_send(module_sd, "<REJECTED REASON=\"result has pause words only\"");
00408 break;
00409 case J_RESULT_STATUS_REJECT_GMM:
00410 module_send(module_sd, "<REJECTED REASON=\"by GMM\"");
00411 break;
00412 case J_RESULT_STATUS_REJECT_SHORT:
00413 module_send(module_sd, "<REJECTED REASON=\"too short input\"");
00414 break;
00415 case J_RESULT_STATUS_FAIL:
00416 module_send(module_sd, "<RECOGFAIL");
00417 break;
00418 }
00419 if (multi) {
00420 module_send(module_sd, " ID=\"SR%02d\" NAME=\"%s\"", r->config->id, r->config->name);
00421 }
00422 module_send(module_sd, "/>\n.\n");
00423 continue;
00424 }
00425
00426 if (out2_never) continue;
00427
00428 winfo = r->lm->winfo;
00429 num = r->result.sentnum;
00430
00431 if (multi) {
00432 module_send(module_sd, "<RECOGOUT ID=\"SR%02d\" NAME=\"%s\">\n", r->config->id, r->config->name);
00433 } else {
00434 module_send(module_sd, "<RECOGOUT>\n");
00435 }
00436 for(n=0;n<num;n++) {
00437 s = &(r->result.sent[n]);
00438 seq = s->word;
00439 seqnum = s->word_num;
00440
00441 module_send(module_sd, " <SHYPO RANK=\"%d\"", n+1);
00442 if (out2_score) {
00443 module_send(module_sd, " SCORE=\"%f\"", s->score);
00444 if (r->lmtype == LM_PROB) {
00445 if (separate_score_flag) {
00446 module_send(module_sd, " AMSCORE=\"%f\" LMSCORE=\"%f\"", s->score_am, s->score_lm);
00447 }
00448 }
00449 }
00450 if (r->lmtype == LM_DFA) {
00451
00452 module_send(module_sd, " GRAM=\"%d\"", s->gram_id);
00453 }
00454
00455 module_send(module_sd, ">\n");
00456 for (i=0;i<seqnum;i++) {
00457 module_send(module_sd, " <WHYPO");
00458 msock_word_out2(seq[i], r);
00459 #ifdef CONFIDENCE_MEASURE
00460 #ifdef CM_MULTIPLE_ALPHA
00461
00462 #else
00463 if (out2_cm) {
00464 module_send(module_sd, " CM=\"%5.3f\"", s->confidence[i]);
00465 }
00466 #endif
00467 #endif
00468 module_send(module_sd, "/>\n");
00469 }
00470 module_send(module_sd, " </SHYPO>\n");
00471 }
00472 module_send(module_sd, "</RECOGOUT>\n.\n");
00473
00474 }
00475
00476 }
00477
00478
00479
00480
00481
00496 static void
00497 result_graph(Recog *recog, void *dummy)
00498 {
00499 WordGraph *wg;
00500 int i;
00501 int nodenum, arcnum;
00502 WORD_INFO *winfo;
00503 WordGraph *root;
00504 RecogProcess *r;
00505 boolean multi;
00506
00507 if (recog->process_list->next != NULL) multi = TRUE;
00508 else multi = FALSE;
00509
00510 for(r=recog->process_list;r;r=r->next) {
00511 if (! r->live) continue;
00512 if (r->result.wg == NULL) continue;
00513
00514 winfo = r->lm->winfo;
00515 root = r->result.wg;
00516 nodenum = r->graph_totalwordnum;
00517 arcnum = 0;
00518 for(wg=root;wg;wg=wg->next) {
00519 arcnum += wg->rightwordnum;
00520 }
00521
00522 module_send(module_sd, "<GRAPHOUT");
00523 if (multi) module_send(module_sd, " ID=\"SR%02d\" NAME=\"%s\"", r->config->id, r->config->name);
00524 module_send(module_sd, " NODENUM=\"%d\" ARCNUM=\"%d\">\n", nodenum, arcnum);
00525 for(wg=root;wg;wg=wg->next) {
00526 module_send(module_sd, " <NODE GID=\"%d\"", wg->id);
00527 msock_word_out2(wg->wid, r);
00528 module_send(module_sd, " BEGIN=\"%d\"", wg->lefttime);
00529 module_send(module_sd, " END=\"%d\"", wg->righttime);
00530 module_send(module_sd, "/>\n");
00531 }
00532 for(wg=root;wg;wg=wg->next) {
00533 for(i=0;i<wg->rightwordnum;i++) {
00534 module_send(module_sd, " <ARC FROM=\"%d\" TO=\"%d\"/>\n", wg->id, wg->rightword[i]->id);
00535 }
00536 }
00537 module_send(module_sd, "</GRAPHOUT>\n.\n");
00538 }
00539 }
00540
00551 static void
00552 status_recready(Recog *recog, void *dummy)
00553 {
00554 module_send(module_sd, "<INPUT STATUS=\"LISTEN\" TIME=\"%ld\"/>\n.\n", time(NULL));
00555 }
00556
00567 static void
00568 status_recstart(Recog *recog, void *dummy)
00569 {
00570 module_send(module_sd, "<INPUT STATUS=\"STARTREC\" TIME=\"%ld\"/>\n.\n", time(NULL));
00571 }
00582 static void
00583 status_recend(Recog *recog, void *dummy)
00584 {
00585 module_send(module_sd, "<INPUT STATUS=\"ENDREC\" TIME=\"%ld\"/>\n.\n", time(NULL));
00586 }
00599 static void
00600 status_param(Recog *recog, void *dummy)
00601 {
00602 MFCCCalc *mfcc;
00603 boolean multi;
00604 int frames;
00605 int msec;
00606
00607 if (recog->mfcclist->next != NULL) multi = TRUE;
00608 else multi = FALSE;
00609
00610 for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
00611 frames = mfcc->param->samplenum;
00612 msec = (float)mfcc->param->samplenum * (float)recog->jconf->input.period * (float)recog->jconf->input.frameshift / 10000.0;
00613 if (multi) {
00614 module_send(module_sd, "<INPUTPARAM MFCCID=\"%02d\" FRAMES=\"%d\" MSEC=\"%d\"/>\n.\n", mfcc->id, frames, msec);
00615 } else {
00616 module_send(module_sd, "<INPUTPARAM FRAMES=\"%d\" MSEC=\"%d\"/>\n.\n", frames, msec);
00617 }
00618 }
00619 }
00620
00621
00631 static void
00632 result_gmm(Recog *recog, void *dummy)
00633 {
00634 module_send(module_sd, "<GMM RESULT=\"%s\"", recog->gc->max_d->name);
00635 #ifdef CONFIDENCE_MEASURE
00636 module_send(module_sd, " CMSCORE=\"%f\"", recog->gc->gmm_max_cm);
00637 #endif
00638 module_send(module_sd, "/>\n.\n");
00639 }
00640
00651 void
00652 send_gram_info(RecogProcess *r)
00653 {
00654 MULTIGRAM *m;
00655 char buf[1024];
00656
00657 if (r->lmtype == LM_PROB) {
00658 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n");
00659 return;
00660 }
00661 module_send(module_sd, "<GRAMINFO>\n");
00662 for(m=r->lm->grammars;m;m=m->next) {
00663 buf[0] = '\0';
00664 if (m->dfa) {
00665 snprintf(buf, 1024, ", %3d categories, %4d nodes",
00666 m->dfa->term_num, m->dfa->state_num);
00667 }
00668 if (m->newbie) strcat(buf, " (new)");
00669 if (m->hook != 0) {
00670 strcat(buf, " (next:");
00671 if (m->hook & MULTIGRAM_DELETE) {
00672 strcat(buf, " delete");
00673 }
00674 if (m->hook & MULTIGRAM_ACTIVATE) {
00675 strcat(buf, " activate");
00676 }
00677 if (m->hook & MULTIGRAM_DEACTIVATE) {
00678 strcat(buf, " deactivate");
00679 }
00680 if (m->hook & MULTIGRAM_MODIFIED) {
00681 strcat(buf, " modified");
00682 }
00683 strcat(buf, ")");
00684 }
00685 module_send(module_sd, " #%2d: [%-11s] %4d words%s \"%s\"\n",
00686 m->id,
00687 m->active ? "active" : "inactive",
00688 m->winfo->num,
00689 buf,
00690 m->name);
00691 }
00692 if (r->lm->dfa != NULL) {
00693 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);
00694 }
00695 module_send(module_sd, "</GRAMINFO>\n.\n");
00696 }
00697
00698
00699
00710 void
00711 setup_output_msock(Recog *recog, void *data)
00712 {
00713 callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, status_process_online, data);
00714 callback_add(recog, CALLBACK_EVENT_PROCESS_OFFLINE, status_process_offline, data);
00715
00716
00717 callback_add(recog, CALLBACK_EVENT_SPEECH_READY, status_recready, data);
00718 callback_add(recog, CALLBACK_EVENT_SPEECH_START, status_recstart, data);
00719 callback_add(recog, CALLBACK_EVENT_SPEECH_STOP, status_recend, data);
00720 callback_add(recog, CALLBACK_EVENT_PASS1_BEGIN, status_pass1_begin, data);
00721 callback_add(recog, CALLBACK_EVENT_PASS1_END, status_pass1_end, data);
00722 callback_add(recog, CALLBACK_RESULT_PASS1_INTERIM, result_pass1_current, data);
00723 callback_add(recog, CALLBACK_RESULT_PASS1, result_pass1_final, data);
00724
00725 callback_add(recog, CALLBACK_STATUS_PARAM, status_param, data);
00726
00727 callback_add(recog, CALLBACK_RESULT, result_pass2, data);
00728 callback_add(recog, CALLBACK_RESULT_GMM, result_gmm, data);
00729
00730 callback_add(recog, CALLBACK_RESULT_GRAPH, result_graph, data);
00731
00732
00733
00734
00735 }