/**
* @file output_stdout.c
*
*
* @brief 認識結果を標準出力へ出力する.
*
*
*
* @brief Output recoginition result to standard output
*
*
* @author Akinobu Lee
* @date Tue Sep 06 17:18:46 2005
*
* $Revision: 1.10 $
*
*/
/*
* Copyright (c) 1991-2012 Kawahara Lab., Kyoto University
* Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
* Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology
* All rights reserved
*/
#include "app.h"
extern boolean separate_score_flag;
static boolean have_progout = FALSE;
/* for short pause segmentation and successive decoding */
static WORD_ID confword[MAXSEQNUM];
static int confwordnum;
#ifdef CHARACTER_CONVERSION
#define MAXBUFLEN 4096 ///< Maximum line length of a message sent from a client
static char inbuf[MAXBUFLEN];
static char outbuf[MAXBUFLEN];
void
myprintf(char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap,fmt);
ret = vsnprintf(inbuf, MAXBUFLEN, fmt, ap);
va_end(ap);
if (ret > 0) { /* success */
printf("%s", charconv(inbuf, outbuf, MAXBUFLEN));
}
}
#else
#define myprintf printf
#endif
/**
* Assumed tty width for graph view output
*
*/
#define TEXTWIDTH 70
/**
* tty width for short-pause segmentation output
*
*/
#define SPTEXTWIDTH 72
#define SPTEXT_FULLWIDTH 76
/**********************************************************************/
/* process online/offline status */
/**
*
* 起動が終わったとき,あるいは中断状態から復帰したときに
* メッセージを表示する.
*
*
*
* Output message when processing was started or resumed.
*
*
*/
static void
status_process_online(Recog *recog, void *dummy)
{
/* nop */
}
/**
*
* プロセスが中断状態へ移行したときにメッセージを表示する. モジュールモード
* で呼ばれる.
*
*
*
* Output message when the process paused by external command.
*
*
*/
static void
status_process_offline(Recog *recog, void *dummy)
{
/* nop */
}
/**********************************************************************/
/* output recording status changes */
/**
*
* 準備が終了して、認識可能状態(入力待ち状態)に入ったときの出力
*
*
*
* Output when ready to recognize and start waiting speech input.
*
*
*/
static void
status_recready(Recog *recog, void *dummy)
{
if (recog->jconf->input.speech_input == SP_MIC || recog->jconf->input.speech_input == SP_NETAUDIO) {
if (!recog->process_segment) {
fprintf(stderr, "<<< please speak >>>");
}
}
}
/**
*
* 入力の開始を検出したときの出力
*
*
*
* Output when input starts.
*
*
*/
static void
status_recstart(Recog *recog, void *dummy)
{
if (recog->jconf->input.speech_input == SP_MIC || recog->jconf->input.speech_input == SP_NETAUDIO) {
if (!recog->process_segment) {
fprintf(stderr, "\r \r");
}
}
}
/**
*
* 入力終了を検出したときの出力
*
*
*
* Output when input ends.
*
*
*/
static void
status_recend(Recog *recog, void *dummy)
{
/* nop */
}
/**
*
* 入力長などの入力パラメータ情報を出力.
*
* @param param [in] 入力パラメータ構造体
*
*
* Output input parameter status such as length.
*
* @param param [in] input parameter structure
*
*/
static void
status_param(Recog *recog, void *dummy)
{
if (verbose_flag) {
// put_param_info(stdout, recog->param);
}
}
/**********************************************************************/
/* recognition begin / end */
/**
*
* 音声入力が検知され認識処理を開始した時点でメッセージを表示する.
* ショートポーズセグメンテーション時は,最初のセグメント開始時点で出力される.
*
*
*
* Output message when recognition is just started for an incoming input.
* When short-pause segmentation mode, this will be called for the first input.
* segment.
*
*
*/
static void
status_recognition_begin(Recog *recog, void *dummy)
{
if (recog->jconf->decodeopt.segment) { /* short pause segmentation */
if (have_progout) {
confwordnum = 0;
}
}
}
/**
*
* 入力終了し認識処理が終了した時点でメッセージを表示する.
* ショートポーズセグメンテーション時は,1入力の最後のセグメントの終了時に
* 呼ばれる.
*
*
* Output message when the whole recognition procedure was just finished for
* an input. When short-pause segmentation mode, this will be called
* after all the segmentd input fragments are recognized.
*
*/
static void
status_recognition_end(Recog *recog, void *dummy)
{
if (recog->process_segment) {
if (verbose_flag) {
printf("Segmented by short pause, continue to next...\n");
} else {
//printf("-->\n");
}
}
if (recog->jconf->decodeopt.segment) { /* short pause segmentation */
if (have_progout) {
if (confwordnum > 0) {
printf("\n");
}
}
}
}
/**
*
* ショートポーズセグメンテーション時に,区切られたある入力断片に対して
* 認識を開始したときにメッセージを出力する.
*
*
* Output a message when recognition was just started for a segment in a
* input.
*
*/
static void
status_segment_begin(Recog *recog, void *dummy)
{
/* no output */
}
/**
*
* ショートポーズセグメンテーション時に,区切られたある入力断片に対して
* 認識を終了したときにメッセージを出力する.
*
*
* Output a message when recognition was just finished for a segment in a
* input.
*
*/
static void
status_segment_end(Recog *recog, void *dummy)
{
/* nop */
}
/**********************************************************************/
/* 1st pass output */
static int wst; ///< Number of words at previous output line
static int writelen; ///< written string length on this tty line
/**
*
* 第1パス:音声認識を開始する際の出力(音声入力開始時に呼ばれる).
*
*
*
* 1st pass: output when recognition begins (will be called at input start).
*
*
*/
static void
status_pass1_begin(Recog *recog, void *dummy)
{
if (!recog->jconf->decodeopt.realtime_flag) {
VERMES("### Recognition: 1st pass (LR beam)\n");
}
wst = 0;
if (recog->jconf->decodeopt.segment) { /* short pause segmentation */
if (have_progout) {
writelen = 0;
}
}
}
/**
*
* 第1パス:途中結果を出力する(第1パスの一定時間ごとに呼ばれる)
*
* @param t [in] 現在の時間フレーム
* @param seq [in] 現在の一位候補単語列
* @param num [in] @a seq の長さ
* @param score [in] 上記のこれまでの累積スコア
* @param LMscore [in] 上記の最後の単語の信頼度
* @param winfo [in] 単語辞書
*
*
* 1st pass: output current result while search (called periodically while 1st pass).
*
* @param t [in] current time frame
* @param seq [in] current best word sequence at time @a t.
* @param num [in] length of @a seq.
* @param score [in] accumulated score of the current best sequence at @a t.
* @param LMscore [in] confidence score of last word on the sequence
* @param winfo [in] word dictionary
*
*/
static void
result_pass1_current(Recog *recog, void *dummy)
{
int i, j, bgn;
int len, num;
WORD_INFO *winfo;
WORD_ID *seq;
RecogProcess *r;
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (! r->have_interim) continue;
winfo = r->lm->winfo;
seq = r->result.pass1.word;
num = r->result.pass1.word_num;
/* update output line with folding */
printf("\r");
if (r->config->successive.enabled) { /* short pause segmentation */
if (have_progout) {
/* progressive output */
/* first, print already confirmed words */
len = 0;
for(i=0;iwoutput[confword[i]]) > SPTEXTWIDTH) {
for(j=len;jwoutput[confword[i]]);
len += strlen(winfo->woutput[confword[i]]);
}
/* output nothing if we are in the first pause area */
if (!r->pass1.first_sparea) {
printf("|");
len++;
/* the first word of a segment is the same as last segment, so do not output */
if (confword[confwordnum-1] == seq[0]) {
bgn = 1;
} else {
bgn = 0;
}
/* next, print current candidate words */
for(i=bgn;iwoutput[seq[i]]) > SPTEXT_FULLWIDTH) {
if (i < num - 1) continue;
myprintf("*");
len += 1;
} else {
myprintf("%s", winfo->woutput[seq[i]]);
len += strlen(winfo->woutput[seq[i]]);
}
}
printf("|");
len++;
}
fflush(stdout);
/* store maximum written length */
if (writelen < len) writelen = len;
return;
}
}
len = 0;
if (wst == 0) { /* first line */
len += 11;
printf("pass1_best:");
}
bgn = wst; /* output only the last line */
for (i=bgn;iwoutput[seq[i]]) + 1;
if (len > FILLWIDTH) { /* fold line */
wst = i;
printf("\n");
len = 0;
}
myprintf(" %s",winfo->woutput[seq[i]]);
}
if (writelen < len) writelen = len;
}
fflush(stdout); /* flush */
}
/**
*
* 第1パス:終了時に第1パスの結果を出力する(第1パス終了後、第2パスが
* 始まる前に呼ばれる. 認識に失敗した場合は呼ばれない).
*
* @param seq [in] 第1パスの1位候補の単語列
* @param num [in] 上記の長さ
* @param score [in] 1位の累積仮説スコア
* @param LMscore [in] @a score のうち言語スコア
* @param winfo [in] 単語辞書
*
*
* 1st pass: output final result of the 1st pass (will be called just after
* the 1st pass ends and before the 2nd pass begins, and will not if search
* failed).
*
* @param seq [in] word sequence of the best hypothesis at the 1st pass.
* @param num [in] length of @a seq.
* @param score [in] accumulated hypothesis score of @a seq.
* @param LMscore [in] language score in @a score.
* @param winfo [in] word dictionary.
*
*/
static void
result_pass1(Recog *recog, void *dummy)
{
int i,j;
static char buf[MAX_HMMNAME_LEN];
WORD_INFO *winfo;
WORD_ID *seq;
int num;
RecogProcess *r;
boolean multi;
int len;
if (recog->process_list->next != NULL) multi = TRUE;
else multi = FALSE;
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (r->result.status < 0) continue; /* search already failed */
if (have_progout && r->config->successive.enabled) continue; /* short pause segmentation */
if (r->config->output.progout_flag) printf("\r");
winfo = r->lm->winfo;
seq = r->result.pass1.word;
num = r->result.pass1.word_num;
/* words */
if (multi) printf("[#%d %s]\n", r->config->id, r->config->name);
printf("pass1_best:");
if (r->config->output.progout_flag) {
len = 0;
for (i=0;iwoutput[seq[i]]) + 1;
myprintf(" %s",winfo->woutput[seq[i]]);
}
for(j=len;jwoutput[seq[i]]);
}
}
printf("\n");
if (verbose_flag) { /* output further info */
/* N-gram entries */
printf("pass1_best_wordseq:");
for (i=0;iwname[seq[i]]);
}
printf("\n");
/* phoneme sequence */
printf("pass1_best_phonemeseq:");
for (i=0;iwlen[seq[i]];j++) {
center_name(winfo->wseq[seq[i]][j]->name, buf);
myprintf(" %s", buf);
}
if (i < num-1) printf(" |");
}
printf("\n");
if (debug2_flag) {
/* logical HMMs */
printf("pass1_best_HMMseq_logical:");
for (i=0;iwlen[seq[i]];j++) {
myprintf(" %s", winfo->wseq[seq[i]][j]->name);
}
if (i < num-1) printf(" |");
}
printf("\n");
}
/* score */
printf("pass1_best_score: %f", r->result.pass1.score);
if (r->lmtype == LM_PROB) {
if (separate_score_flag) {
printf(" (AM: %f LM: %f)",
r->result.pass1.score_am,
r->result.pass1.score_lm);
}
}
printf("\n");
}
//printf("\n");
}
}
#ifdef WORD_GRAPH
static void
result_pass1_graph(Recog *recog, void *dummy)
{
WordGraph *wg;
WORD_INFO *winfo;
RecogProcess *r;
boolean multi;
int n;
int tw1, tw2, i;
if (recog->process_list->next != NULL) multi = TRUE;
else multi = FALSE;
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (r->result.wg1 == NULL) continue;
if (multi) printf("[#%d %s]\n", r->config->id, r->config->name);
printf("--- begin wordgraph data pass1 ---\n");
winfo = r->lm->winfo;
/* debug: output all graph word info */
wordgraph_dump(stdout, r->result.wg1, winfo);
for(wg=r->result.wg1;wg;wg=wg->next) {
tw1 = (TEXTWIDTH * wg->lefttime) / r->peseqlen;
tw2 = (TEXTWIDTH * wg->righttime) / r->peseqlen;
printf("%4d:", wg->id);
for(i=0;iwoutput[wg->wid]);
printf("%4d:", wg->lefttime);
for(i=0;i
* 第1パス:終了時の出力(第1パスの終了時に必ず呼ばれる)
*
*
*
* 1st pass: end of output (will be called at the end of the 1st pass).
*
*
*/
static void
status_pass1_end(Recog *recog, void *dummy)
{
if (recog->jconf->decodeopt.segment) { /* short pause segmentation */
if (have_progout) return;
}
/* no op */
//printf("\n");
}
/**********************************************************************/
/* 2nd pass output */
/**
*
* 仮説中の単語情報を出力する
*
* @param hypo [in] 仮説
* @param winfo [in] 単語辞書
*
*
* Output word sequence of a hypothesis.
*
* @param hypo [in] sentence hypothesis
* @param winfo [in] word dictionary
*
*/
static void
put_hypo_woutput(WORD_ID *seq, int n, WORD_INFO *winfo)
{
int i;
if (seq != NULL) {
for (i=0;iwoutput[seq[i]]);
}
}
printf("\n");
}
/**
*
* 仮説のN-gram情報(Julianではカテゴリ番号列)を出力する.
*
* @param hypo [in] 文仮説
* @param winfo [in] 単語辞書
*
*
* Output LM word sequence (N-gram entry/DFA category) of a hypothesis.
*
* @param hypo [in] sentence hypothesis
* @param winfo [in] word dictionary
*
*/
static void
put_hypo_wname(WORD_ID *seq, int n, WORD_INFO *winfo)
{
int i;
if (seq != NULL) {
for (i=0;iwname[seq[i]]);
}
}
printf("\n");
}
/**
*
* 仮説の音素系列を出力する.
*
* @param hypo [in] 文仮説
* @param winfo [in] 単語情報
*
*
* Output phoneme sequence of a hypothesis.
*
* @param hypo [in] sentence hypothesis
* @param winfo [in] word dictionary
*
*/
static void
put_hypo_phoneme(WORD_ID *seq, int n, WORD_INFO *winfo)
{
int i,j;
WORD_ID w;
static char buf[MAX_HMMNAME_LEN];
if (seq != NULL) {
for (i=0;i 0) printf(" |");
w = seq[i];
for (j=0;jwlen[w];j++) {
center_name(winfo->wseq[w][j]->name, buf);
myprintf(" %s", buf);
}
}
}
printf("\n");
}
#ifdef CONFIDENCE_MEASURE
/**
*
* 仮説の単語ごとの信頼度を出力する.
*
* @param hypo [in] 文仮説
*
*
* Output confidence score of words in a sentence hypothesis.
*
* @param hypo
*
*/
#ifdef CM_MULTIPLE_ALPHA
static void
put_hypo_cmscore(NODE *hypo, int id)
{
int i;
int j;
if (hypo != NULL) {
for (i=hypo->seqnum-1;i>=0;i--) {
printf(" %5.3f", hypo->cmscore[i][id]);
}
}
printf("\n");
}
#else
static void
put_hypo_cmscore(LOGPROB *cmscore, int n)
{
int i;
if (cmscore != NULL) {
for (i=0;i
* 第2パス:得られた文仮説候補を1つ出力する.
*
* @param hypo [in] 得られた文仮説
* @param rank [in] @a hypo の順位
* @param winfo [in] 単語辞書
*
*
* 2nd pass: output a sentence hypothesis found in the 2nd pass.
*
* @param hypo [in] sentence hypothesis to be output
* @param rank [in] rank of @a hypo
* @param winfo [in] word dictionary
*
*/
static void
//ttyout_pass2(NODE *hypo, int rank, Recog *recog)
result_pass2(Recog *recog, void *dummy)
{
int i, j;
int len;
char ec[5] = {0x1b, '[', '1', 'm', 0};
WORD_INFO *winfo;
WORD_ID *seq;
int seqnum;
int n, num;
Sentence *s;
RecogProcess *r;
boolean multi;
HMM_Logical *p;
SentenceAlign *align;
if (recog->process_list->next != NULL) multi = TRUE;
else multi = FALSE;
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (multi) printf("[#%d %s]\n", r->config->id, r->config->name);
if (r->config->successive.enabled) { /* short pause segmentation */
if (r->result.status < 0 && r->config->output.progout_flag) {
/* search failed */
printf("\r");
winfo = r->lm->winfo;
if (r->result.status == J_RESULT_STATUS_FAIL) {
/* search fail */
/* output pass1 result as final */
seq = r->result.pass1.word;
seqnum = r->result.pass1.word_num;
j = 0;
/* skip output if head word is the same as previous segment */
if (confword[confwordnum-1] == seq[0]) j++;
/* store 1st pass result as final */
for (i=j;iwoutput[confword[i]]) > SPTEXTWIDTH) {
for(j=len;jwoutput[confword[i]]);
len += strlen(winfo->woutput[confword[i]]);
}
for(i=len;iresult.status < 0) {
switch(r->result.status) {
case J_RESULT_STATUS_REJECT_POWER:
printf("\n");
break;
case J_RESULT_STATUS_TERMINATE:
printf("\n");
break;
case J_RESULT_STATUS_ONLY_SILENCE:
printf("\n");
break;
case J_RESULT_STATUS_REJECT_GMM:
printf("\n");
break;
case J_RESULT_STATUS_REJECT_SHORT:
printf("\n");
break;
case J_RESULT_STATUS_FAIL:
printf("\n");
break;
}
continue;
}
winfo = r->lm->winfo;
num = r->result.sentnum;
for(n=0;nresult.sent[n]);
seq = s->word;
seqnum = s->word_num;
if (r->config->successive.enabled) { /* short pause segmentation */
if (r->config->output.progout_flag) {
printf("\r");
j = 0;
/* skip output if head word is the same as previous segment */
if (confword[confwordnum-1] == seq[0]) j++;
for (i=j;iwoutput[confword[i]]) > SPTEXTWIDTH) {
for(j=len;jwoutput[confword[i]]);
len += strlen(winfo->woutput[confword[i]]);
}
for(i=len;iconfig->annotate.cm_alpha_num;i++) {
printf("cmscore%d[%f]:", rank, r->config->annotate.cm_alpha_bgn + i * r->config->annotate.cm_alpha_step);
put_hypo_cmscore(hypo, i);
}
}
#else
printf("cmscore%d:", n+1);
put_hypo_cmscore(s->confidence, seqnum);
#endif
#endif /* CONFIDENCE_MEASURE */
}
if (debug2_flag) {
ec[2] = '0';
printf("%s\n",ec); /* bold off & newline */
}
if (verbose_flag) {
printf("score%d: %f", n+1, s->score);
if (r->lmtype == LM_PROB) {
if (separate_score_flag) {
printf(" (AM: %f LM: %f)", s->score_am, s->score_lm);
}
}
printf("\n");
if (r->lmtype == LM_DFA) {
/* output which grammar the hypothesis belongs to on multiple grammar */
/* determine only by the last word */
if (multigram_get_all_num(r->lm) > 1) {
printf("grammar%d: %d\n", n+1, s->gram_id);
}
}
}
/* output alignment result if exist */
for (align = s->align; align; align = align->next) {
printf("=== begin forced alignment ===\n");
switch(align->unittype) {
case PER_WORD:
printf("-- word alignment --\n"); break;
case PER_PHONEME:
printf("-- phoneme alignment --\n"); break;
case PER_STATE:
printf("-- state alignment --\n"); break;
}
printf(" id: from to n_score unit\n");
printf(" ----------------------------------------\n");
for(i=0;inum;i++) {
printf("[%4d %4d] %f ", align->begin_frame[i], align->end_frame[i], align->avgscore[i]);
switch(align->unittype) {
case PER_WORD:
myprintf("%s\t[%s]\n", winfo->wname[align->w[i]], winfo->woutput[align->w[i]]);
break;
case PER_PHONEME:
p = align->ph[i];
if (p->is_pseudo) {
printf("{%s}\n", p->name);
} else if (strmatch(p->name, p->body.defined->name)) {
printf("%s\n", p->name);
} else {
printf("%s[%s]\n", p->name, p->body.defined->name);
}
break;
case PER_STATE:
p = align->ph[i];
if (p->is_pseudo) {
printf("{%s}", p->name);
} else if (strmatch(p->name, p->body.defined->name)) {
printf("%s", p->name);
} else {
printf("%s[%s]", p->name, p->body.defined->name);
}
if (r->am->hmminfo->multipath) {
if (align->is_iwsp[i]) {
printf(" #%d (sp)\n", align->loc[i]);
} else {
printf(" #%d\n", align->loc[i]);
}
} else {
printf(" #%d\n", align->loc[i]);
}
break;
}
}
printf("re-computed AM score: %f\n", align->allscore);
printf("=== end forced alignment ===\n");
}
}
}
fflush(stdout);
}
/**
*
* 第2パス:音声認識結果の出力を開始する際の出力. 認識結果を出力する際に、
* 一番最初に出力される.
*
*
*
* 2nd pass: output at the start of result output (will be called before
* all the result output in the 2nd pass).
*
*
*/
static void
status_pass2_begin(Recog *recog, void *dummy)
{
VERMES("### Recognition: 2nd pass (RL heuristic best-first)\n");
//if (verbose_flag) printf("samplenum=%d\n", recog->param->samplenum);
//if (debug2_flag) VERMES("getting %d candidates...\n", recog->jconf->search.pass2.nbest);
}
/**
*
* 第2パス:終了時
*
*
*
* 2nd pass: end output
*
*
*/
static void
status_pass2_end(Recog *recog, void *dummy)
{
fflush(stdout);
}
/**********************************************************************/
/* word graph output */
#define TEXTWIDTH 70
/**
*
* 得られた単語グラフ全体を出力する.
*
* @param root [in] グラフ単語集合の先頭要素へのポインタ
* @param winfo [in] 単語辞書
*
*
* Output the whole word graph.
*
* @param root [in] pointer to the first element of graph words
* @param winfo [in] word dictionary
*
*/
static void
result_graph(Recog *recog, void *dummy)
{
WordGraph *wg;
int tw1, tw2, i;
WORD_INFO *winfo;
RecogProcess *r;
boolean multi;
if (recog->process_list->next != NULL) multi = TRUE;
else multi = FALSE;
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (r->result.wg == NULL) continue; /* no graphout specified */
if (multi) printf("[#%d %s]\n", r->config->id, r->config->name);
winfo = r->lm->winfo;
/* debug: output all graph word info */
wordgraph_dump(stdout, r->result.wg, winfo);
printf("-------------------------- begin wordgraph show -------------------------\n");
for(wg=r->result.wg;wg;wg=wg->next) {
tw1 = (TEXTWIDTH * wg->lefttime) / r->peseqlen;
tw2 = (TEXTWIDTH * wg->righttime) / r->peseqlen;
printf("%4d:", wg->id);
for(i=0;iwoutput[wg->wid]);
printf("%4d:", wg->lefttime);
for(i=0;i
* 得られたコンフュージョンネットワークを出力する.
*
*
*
* Output the obtained confusion network.
*
*
*/
static void
result_confnet(Recog *recog, void *dummy)
{
CN_CLUSTER *c;
int i;
RecogProcess *r;
boolean multi;
if (recog->process_list->next != NULL) multi = TRUE;
else multi = FALSE;
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (r->result.confnet == NULL) continue; /* no confnet obtained */
if (multi) printf("[#%d %s]\n", r->config->id, r->config->name);
printf("---- begin confusion network ---\n");
for(c=r->result.confnet;c;c=c->next) {
for(i=0;iwordsnum;i++) {
myprintf("(%s:%.3f)", (c->words[i] == WORD_INVALID) ? "-" : r->lm->winfo->woutput[c->words[i]], c->pp[i]);
if (i == 0) printf(" ");
}
printf("\n");
#if 0
/* output details - break down all words clustered into this class */
for(i=0;iwgnum;i++) {
printf(" ");
put_wordgraph(stdout, c->wg[i], r->lm->winfo);
}
#endif
}
printf("---- end confusion network ---\n");
}
}
/********************* RESULT OUTPUT FOR GMM *************************/
/**
*
* GMMの計算結果を標準出力に出力する. ("-result tty" 用)
*
*
* Output result of GMM computation to standard out.
* (for "-result tty" option)
*
*/
static void
result_gmm(Recog *recog, void *dummy)
{
HTK_HMM_Data *d;
GMMCalc *gc;
int i;
gc = recog->gc;
if (debug2_flag) {
printf("--- GMM result begin ---\n");
i = 0;
for(d=recog->gmm->start;d;d=d->next) {
myprintf(" [%8s: total=%f avg=%f]\n", d->name, gc->gmm_score[i], gc->gmm_score[i] / (float)gc->framecount);
i++;
}
myprintf(" max = \"%s\"", gc->max_d->name);
#ifdef CONFIDENCE_MEASURE
printf(" (CM: %f)", gc->gmm_max_cm);
#endif
printf("\n");
printf("--- GMM result end ---\n");
} else if (verbose_flag) {
myprintf("GMM: max = \"%s\"", gc->max_d->name);
#ifdef CONFIDENCE_MEASURE
printf(" (CM: %f)", gc->gmm_max_cm);
#endif
printf("\n");
} else {
if (recog->jconf->decodeopt.segment) { /* short pause segmentation */
if (!have_progout) {
myprintf("[GMM: %s]\n", gc->max_d->name);
}
} else {
myprintf("[GMM: %s]\n", gc->max_d->name);
}
}
}
/**
*
* 現在保持している文法のリストを標準出力に出力する.
*
*
*
* Output current list of grammars to stdout.
*
*
*/
void
print_all_gram(Recog *recog)
{
MULTIGRAM *m;
RecogProcess *r;
boolean multi;
char buf[1024];
if (recog->process_list->next != NULL) multi = TRUE;
else multi = FALSE;
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (multi) printf("[#%d %s]\n", r->config->id, r->config->name);
if (r->lmtype == LM_PROB) {
printf("NOT A GRAMMAR-BASED LM\n");
continue;
}
printf("[grammars]\n");
for(m=r->lm->grammars;m;m=m->next) {
buf[0] = '\0';
if (m->dfa) {
snprintf(buf, 1024, ", %3d categories, %4d nodes",
m->dfa->term_num, m->dfa->state_num);
}
if (m->newbie) strcat(buf, " (new)");
if (m->hook != 0) {
strcat(buf, " (next:");
if (m->hook & MULTIGRAM_DELETE) {
strcat(buf, " delete");
}
if (m->hook & MULTIGRAM_ACTIVATE) {
strcat(buf, " activate");
}
if (m->hook & MULTIGRAM_DEACTIVATE) {
strcat(buf, " deactivate");
}
if (m->hook & MULTIGRAM_MODIFIED) {
strcat(buf, " modified");
}
strcat(buf, ")");
}
myprintf(" #%2d: [%-11s] %4d words%s \"%s\"\n",
m->id,
m->active ? "active" : "inactive",
m->winfo->num,
buf,
m->name);
}
if (r->lm->dfa != NULL) {
printf(" Global: %4d words, %3d categories, %4d nodes\n", r->lm->winfo->num, r->lm->dfa->term_num, r->lm->dfa->state_num);
}
}
}
static void
levelmeter(Recog *recog, SP16 *buf, int len, void *dummy)
{
float d;
int level;
int i, n;
level = 0;
for(i=0;i");
}
static void
frame_indicator(Recog *recog, void *dummy)
{
RecogProcess *r;
if (recog->jconf->decodeopt.segment) {
for(r=recog->process_list;r;r=r->next) {
if (! r->live) continue;
if (r->pass1.in_sparea) {
fprintf(stderr, ".");
break;
}
}
if (!r) {
fprintf(stderr, "-");
}
} else {
fprintf(stderr, ".");
}
}
void
setup_output_tty(Recog *recog, void *data)
{
callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, status_process_online, data);
callback_add(recog, CALLBACK_EVENT_PROCESS_OFFLINE, status_process_offline, data);
callback_add(recog, CALLBACK_EVENT_SPEECH_READY, status_recready, data);
callback_add(recog, CALLBACK_EVENT_SPEECH_START, status_recstart, data);
callback_add(recog, CALLBACK_EVENT_SPEECH_STOP, status_recend, data);
callback_add(recog, CALLBACK_EVENT_RECOGNITION_BEGIN, status_recognition_begin, data);
callback_add(recog, CALLBACK_EVENT_RECOGNITION_END, status_recognition_end, data);
if (recog->jconf->decodeopt.segment) { /* short pause segmentation */
callback_add(recog, CALLBACK_EVENT_SEGMENT_BEGIN, status_segment_begin, data);
callback_add(recog, CALLBACK_EVENT_SEGMENT_END, status_segment_end, data);
}
callback_add(recog, CALLBACK_EVENT_PASS1_BEGIN, status_pass1_begin, data);
{
JCONF_SEARCH *s;
boolean ok_p;
ok_p = TRUE;
for(s=recog->jconf->search_root;s;s=s->next) {
if (s->output.progout_flag) ok_p = FALSE;
}
if (ok_p) {
have_progout = FALSE;
} else {
have_progout = TRUE;
}
}
if (!recog->jconf->decodeopt.realtime_flag && verbose_flag && ! have_progout) {
callback_add(recog, CALLBACK_EVENT_PASS1_FRAME, frame_indicator, data);
}
callback_add(recog, CALLBACK_RESULT_PASS1_INTERIM, result_pass1_current, data);
callback_add(recog, CALLBACK_RESULT_PASS1, result_pass1, data);
#ifdef WORD_GRAPH
callback_add(recog, CALLBACK_RESULT_PASS1_GRAPH, result_pass1_graph, data);
#endif
callback_add(recog, CALLBACK_EVENT_PASS1_END, status_pass1_end, data);
callback_add(recog, CALLBACK_STATUS_PARAM, status_param, data);
callback_add(recog, CALLBACK_EVENT_PASS2_BEGIN, status_pass2_begin, data);
callback_add(recog, CALLBACK_EVENT_PASS2_END, status_pass2_end, data);
callback_add(recog, CALLBACK_RESULT, result_pass2, data); // rejected, failed
callback_add(recog, CALLBACK_RESULT_GMM, result_gmm, data);
/* below will be called when "-lattice" is specified */
callback_add(recog, CALLBACK_RESULT_GRAPH, result_graph, data);
/* below will be called when "-confnet" is specified */
callback_add(recog, CALLBACK_RESULT_CONFNET, result_confnet, data);
//callback_add_adin(CALLBACK_ADIN_CAPTURED, levelmeter, data);
}