/**
* @file m_chkparam.c
*
*
* @brief パラメータ設定の後処理.
*
* jconf ファイルおよびコマンドオプションによって与えられた
* パラメータについて後処理を行い,最終的に認識処理で使用する値を確定する.
*
*
*
* @brief Post processing of parameters for recognition.
*
* These functions will finalize the parameter values for recognition.
* They check for parameters given from jconf file or command line,
* set default values if needed, and prepare for recognition.
*
*
*
* @author Akinobu LEE
* @date Fri Mar 18 16:31:45 2005
*
* $Revision: 1.7 $
*
*/
/*
* 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
/**
*
* ファイルが存在して読み込み可能かチェックする.
*
* @param filename [in] ファイルパス名
*
*
* Check if a file actually exist and is readable.
*
* @param filename [in] file path name
*
*
*/
boolean
checkpath(char *filename)
{
if (access(filename, R_OK) == -1) {
jlog("ERROR: m_chkparam: cannot access %s\n", filename);
return FALSE;
}
return TRUE;
}
/**
*
* @brief jconf設定パラメータを最終的に決定する
*
* この関数は,jconf ファイルやコマンドオプションによって与えられた
* jconf 内のパラメータについて精査を行う. 具体的には,値の範囲のチェッ
* クや,競合のチェック,設定から算出される各種パラメータの計算,使用
* するモデルに対する指定の有効性などをチェックする.
*
* この関数は,アプリケーションによって jconf の各値の指定が終了した直後,
* エンジンインスタンスの作成やモデルのロードが行われる前に呼び出される
* べきである.
*
*
*
* @brief Check and finalize jconf parameters.
*
* This functions parse through the global jconf configuration parameters.
* This function checks for value range of variables, file existence,
* competing specifications among variables or between variables and models,
* calculate some parameters from the given values, etc.
*
* This function should be called just after all values are set by
* jconf, command argument or by user application, and before creating
* engine instance and loading models.
*
*
*
* @param jconf [i/o] global jconf configuration structure
*
* @return TRUE when all check has been passed, or FALSE if not passed.
*
* @callgraph
* @callergraph
* @ingroup jconf
*/
boolean
j_jconf_finalize(Jconf *jconf)
{
boolean ok_p;
JCONF_LM *lm;
JCONF_AM *am;
JCONF_SEARCH *s, *hs;
ok_p = TRUE;
/* update and tailor configuration */
/* if a search config has progout_flag enabled, set it to all config */
hs = NULL;
for(s=jconf->search_root;s;s=s->next) {
if (s->output.progout_flag) {
hs = s;
break;
}
}
if (hs != NULL) {
for(s=jconf->search_root;s;s=s->next) {
s->output.progout_flag = hs->output.progout_flag;
s->output.progout_interval = hs->output.progout_interval;
}
}
/* if an instance has short-pause segmentation enabled,
set it to global opt for parameter handling
(only a recognizer with this option will decide the segmentation,
but the segmentation should be synchronized for all the recognizer)
*/
for(s=jconf->search_root;s;s=s->next) {
if (s->successive.enabled) {
jconf->decodeopt.segment = TRUE;
break;
}
}
#ifdef GMM_VAD
/* if GMM VAD enabled, set it to global */
if (jconf->reject.gmm_filename) {
jconf->decodeopt.segment = TRUE;
}
#endif
for(lm = jconf->lm_root; lm; lm = lm->next) {
if (lm->lmtype == LM_UNDEF) {
/* determine LM type from the specified LM files */
if (lm->ngram_filename_lr_arpa || lm->ngram_filename_rl_arpa || lm->ngram_filename) {
/* n-gram specified */
lm->lmtype = LM_PROB;
lm->lmvar = LM_NGRAM;
}
if (lm->gramlist_root) {
/* DFA grammar specified */
if (lm->lmtype != LM_UNDEF) {
jlog("ERROR: m_chkparam: LM conflicts: several LM of different type specified?\n");
return FALSE;
}
lm->lmtype = LM_DFA;
lm->lmvar = LM_DFA_GRAMMAR;
}
if (lm->dfa_filename) {
/* DFA grammar specified by "-dfa" */
if (lm->lmtype != LM_UNDEF && lm->lmvar != LM_DFA_GRAMMAR) {
jlog("ERROR: m_chkparam: LM conflicts: several LM of different type specified?\n");
return FALSE;
}
lm->lmtype = LM_DFA;
lm->lmvar = LM_DFA_GRAMMAR;
}
if (lm->wordlist_root) {
/* word list specified */
if (lm->lmtype != LM_UNDEF) {
jlog("ERROR: m_chkparam: LM conflicts: several LM of different type specified?\n");
return FALSE;
}
lm->lmtype = LM_DFA;
lm->lmvar = LM_DFA_WORD;
}
}
if (lm->lmtype == LM_UNDEF) { /* an LM is not specified */
jlog("ERROR: m_chkparam: you should specify at least one LM to run Julius!\n");
return FALSE;
}
if (lm->lmtype == LM_PROB) {
if (lm->dictfilename == NULL) {
jlog("ERROR: m_chkparam: needs dictionary file (-v dict_file)\n");
ok_p = FALSE;
}
}
/* file existence check */
if (lm->dictfilename != NULL)
if (!checkpath(lm->dictfilename)) ok_p = FALSE;
if (lm->ngram_filename != NULL)
if (!checkpath(lm->ngram_filename)) ok_p = FALSE;
if (lm->ngram_filename_lr_arpa != NULL)
if (!checkpath(lm->ngram_filename_lr_arpa)) ok_p = FALSE;
if (lm->ngram_filename_rl_arpa != NULL)
if (!checkpath(lm->ngram_filename_rl_arpa)) ok_p = FALSE;
if (lm->dfa_filename != NULL)
if (!checkpath(lm->dfa_filename)) ok_p = FALSE;
}
for(am = jconf->am_root; am; am = am->next) {
/* check if needed files are specified */
if (am->hmmfilename == NULL) {
jlog("ERROR: m_chkparam: needs HMM definition file (-h hmmdef_file)\n");
ok_p = FALSE;
}
/* file existence check */
if (am->hmmfilename != NULL)
if (!checkpath(am->hmmfilename)) ok_p = FALSE;
if (am->mapfilename != NULL)
if (!checkpath(am->mapfilename)) ok_p = FALSE;
if (am->hmm_gs_filename != NULL)
if (!checkpath(am->hmm_gs_filename)) ok_p = FALSE;
/* cmn{save,load}_filename allows missing file (skipped if missing) */
if (am->frontend.ssload_filename != NULL)
if (!checkpath(am->frontend.ssload_filename)) ok_p = FALSE;
}
if (jconf->reject.gmm_filename != NULL)
if (!checkpath(jconf->reject.gmm_filename)) ok_p = FALSE;
if (jconf->input.inputlist_filename != NULL) {
if (jconf->input.speech_input != SP_RAWFILE && jconf->input.speech_input != SP_MFCFILE) {
jlog("WARNING: m_chkparam: not file input, \"-filelist %s\" ignored\n", jconf->input.inputlist_filename);
} else {
if (!checkpath(jconf->input.inputlist_filename)) ok_p = FALSE;
}
}
/* set default realtime flag according to input mode */
if (jconf->decodeopt.force_realtime_flag) {
if (jconf->input.type == INPUT_VECTOR) {
jlog("WARNING: m_chkparam: real-time concurrent processing is not needed on feature vector input\n");
jlog("WARNING: m_chkparam: real-time flag has turned off\n");
jconf->decodeopt.realtime_flag = FALSE;
} else {
jconf->decodeopt.realtime_flag = jconf->decodeopt.forced_realtime;
}
}
/* check for cmn */
if (jconf->decodeopt.realtime_flag) {
for(am = jconf->am_root; am; am = am->next) {
if (am->analysis.cmn_update == FALSE && am->analysis.cmnload_filename == NULL) {
jlog("ERROR: m_chkparam: when \"-cmnnoupdate\", initial cepstral normalisation data should be given by \"-cmnload\"\n");
ok_p = FALSE;
}
}
}
/* set values for search config */
for(s=jconf->search_root;s;s=s->next) {
lm = s->lmconf;
am = s->amconf;
/* force context dependency handling flag for word-recognition mode */
if (lm->lmtype == LM_DFA && lm->lmvar == LM_DFA_WORD) {
/* disable inter-word context dependent handling ("-no_ccd") */
s->ccd_handling = FALSE;
s->force_ccd_handling = TRUE;
/* force 1pass ("-1pass") */
s->compute_only_1pass = TRUE;
}
/* set default iwcd1 method from lm */
/* WARNING: THIS WILL BEHAVE WRONG IF MULTIPLE LM TYPE SPECIFIED */
/* RECOMMEND USING EXPLICIT OPTION */
if (am->iwcdmethod == IWCD_UNDEF) {
switch(lm->lmtype) {
case LM_PROB:
am->iwcdmethod = IWCD_NBEST; break;
case LM_DFA:
am->iwcdmethod = IWCD_AVG; break;
}
}
}
/* check option validity with the current lm type */
/* just a warning message for user */
for(s=jconf->search_root;s;s=s->next) {
lm = s->lmconf;
am = s->amconf;
if (lm->lmtype != LM_PROB) {
/* in case not a probabilistic model */
if (s->lmp.lmp_specified) {
jlog("WARNING: m_chkparam: \"-lmp\" only for N-gram, ignored\n");
}
if (s->lmp.lmp2_specified) {
jlog("WARNING: m_chkparam: \"-lmp2\" only for N-gram, ignored\n");
}
if (s->lmp.lm_penalty_trans != 0.0) {
jlog("WARNING: m_chkparam: \"-transp\" only for N-gram, ignored\n");
}
if (lm->head_silname && !strmatch(lm->head_silname, BEGIN_WORD_DEFAULT)) {
jlog("WARNING: m_chkparam: \"-silhead\" only for N-gram, ignored\n");
}
if (lm->tail_silname && !strmatch(lm->tail_silname, END_WORD_DEFAULT)) {
jlog("WARNING: m_chkparam: \"-siltail\" only for N-gram, ignored\n");
}
if (lm->enable_iwspword) {
jlog("WARNING: m_chkparam: \"-iwspword\" only for N-gram, ignored\n");
}
if (lm->iwspentry && !strmatch(lm->iwspentry, IWSPENTRY_DEFAULT)) {
jlog("WARNING: m_chkparam: \"-iwspentry\" only for N-gram, ignored\n");
}
#ifdef HASH_CACHE_IW
if (s->pass1.iw_cache_rate != 10) {
jlog("WARNING: m_chkparam: \"-iwcache\" only for N-gram, ignored\n");
}
#endif
#ifdef SEPARATE_BY_UNIGRAM
if (lm->separate_wnum != 150) {
jlog("WARNING: m_chkparam: \"-sepnum\" only for N-gram, ignored\n");
}
#endif
}
if (lm->lmtype != LM_DFA) {
/* in case not a deterministic model */
if (s->pass2.looktrellis_flag) {
jlog("WARNING: m_chkparam: \"-looktrellis\" only for grammar, ignored\n");
}
if (s->output.multigramout_flag) {
jlog("WARNING: m_chkparam: \"-multigramout\" only for grammar, ignored\n");
}
if (s->lmp.penalty1 != 0.0) {
jlog("WARNING: m_chkparam: \"-penalty1\" only for grammar, ignored\n");
}
if (s->lmp.penalty2 != 0.0) {
jlog("WARNING: m_chkparam: \"-penalty2\" only for grammar, ignored\n");
}
}
}
if (!ok_p) {
jlog("ERROR: m_chkparam: could not pass parameter check\n");
} else {
jlog("STAT: jconf successfully finalized\n");
}
if (debug2_flag) {
print_jconf_overview(jconf);
}
return ok_p;
}
/**
*
* @brief あらかじめ定められた第1パスのデフォルトビーム幅を返す.
*
* デフォルトのビーム幅は,認識エンジンのコンパイル時設定や
* 使用する音響モデルに従って選択される. これらの値は,20k の
* IPA 評価セットで得られた最適値(精度を保ちつつ最大速度が得られる値)
* である.
*
* @return 実行時の条件によって選択されたビーム幅
*
*
* @brief Returns the pre-defined default beam width on 1st pass of
* beam search.
*
* The default beam width will be selected from the pre-defined values
* according to the compilation-time engine setting and the type of
* acoustic model. The pre-defined values were determined from the
* development experiments on IPA evaluation testset of Japanese 20k-word
* dictation task.
*
* @return the selected default beam width.
*
*/
static int
default_width(HTK_HMM_INFO *hmminfo)
{
if (strmatch(JULIUS_SETUP, "fast")) { /* for fast setup */
if (hmminfo->is_triphone) {
if (hmminfo->is_tied_mixture) {
/* tied-mixture triphones (PTM etc.) */
return(600);
} else {
/* shared-state triphone */
#ifdef PASS1_IWCD
return(800);
#else
/* v2.1 compliant (no IWCD on 1st pass) */
return(1000);
#endif
}
} else {
/* monophone */
return(400);
}
} else { /* for standard / v2.1 setup */
if (hmminfo->is_triphone) {
if (hmminfo->is_tied_mixture) {
/* tied-mixture triphones (PTM etc.) */
return(800);
} else {
/* shared-state triphone */
#ifdef PASS1_IWCD
return(1500);
#else
return(1500); /* v2.1 compliant (no IWCD on 1st pass) */
#endif
}
} else {
/* monophone */
return(700);
}
}
}
/**
*
* @brief 第1パスのビーム幅を決定する.
*
* ユーザが "-b" オプションでビーム幅を指定しなかった場合は,
* 下記のうち小さい方がビーム幅として採用される.
* - default_width() の値
* - sqrt(語彙数) * 15
*
* @param wchmm [in] 木構造化辞書
* @param specified [in] ユーザ指定ビーム幅(0: 全探索 -1: 未指定)
*
* @return 採用されたビーム幅.
*
*
* @brief Determine beam width on the 1st pass.
*
* @param wchmm [in] tree lexicon data
* @param specified [in] user-specified beam width (0: full search,
* -1: not specified)
*
* @return the final beam width to be used.
*
*
* @callgraph
* @callergraph
*/
int
set_beam_width(WCHMM_INFO *wchmm, int specified)
{
int width;
int standard_width;
if (specified == 0) { /* full search */
jlog("WARNING: doing full search (can be extremely slow)\n");
width = wchmm->n;
} else if (specified == -1) { /* not specified */
standard_width = default_width(wchmm->hmminfo); /* system default */
width = (int)(sqrt(wchmm->winfo->num) * 15.0); /* heuristic value!! */
if (width > standard_width) width = standard_width;
/* 2007/1/20 bgn */
if (width < MINIMAL_BEAM_WIDTH) {
width = MINIMAL_BEAM_WIDTH;
}
/* 2007/1/20 end */
} else { /* actual value has been specified */
width = specified;
}
if (width > wchmm->n) width = wchmm->n;
return(width);
}
/* end of file */