/** 
 * <EN>
 * @brief  Load a language model.
 *
 * This function will create an LM process instance using the given LM
 * configuration, and load models specified in the configuration into
 * the instance.  Then the created instance will be installed to the
 * engine instance.  The lmconf should be registered to the 
 * recog->jconf before calling this function.
 *
 * To convert phoneme sequence to triphone at loading, you should
 * specify which AM to use with this LM by the argument am.
 *
 * </EN>
 *
 * <JA>
 * @brief 言語モデルを読み込む.
 *
 * この関数は,与えられた LM 設定に従って LM 処理インスタンスを生成し,
 * その中に言語モデルをロードします.その後,そのLM処理インスタンスは
 * 新たにエンジンインスタンスに登録されます.LM設定はこの関数を
 * 呼ぶ前にあらかじめ全体設定recog->jconfに登録されている必要があります.
 *
 * 辞書の読み込み時にトライフォンへの変換および音響モデルとのリンクが
 * 同時に行われます.このため,この言語モデルが使用する音響モデルの
 * インスタンスを引数 am として指定する必要があります.
 * 
 * </JA>
 * 
 * @param recog [i/o] engine instance
 * @param lmconf [in] LM configuration to load
 * 
 * @return TRUE on success, or FALSE on error.
 * 
 * @callgraph
 * @callergraph
 * @ingroup instance
 * 
 */
boolean
j_load_lm(Recog *recog, JCONF_LM *lmconf)
{
  JCONF_SEARCH *sh;
  PROCESS_LM *lm;
  PROCESS_AM *am, *atmp;

  jlog("STAT: *** loading LM%02d %s\n", lmconf->id, lmconf->name);

  /* find which am process instance to assign to each LM */
  am = NULL;
  for(sh=recog->jconf->search_root;sh;sh=sh->next) {
    if (sh->lmconf == lmconf) {
      for(atmp=recog->amlist;atmp;atmp=atmp->next) {
	if (sh->amconf == atmp->config) {
	  am = atmp;
	}
      }
    }
  }
  if (am == NULL) {
    jlog("ERROR: cannot find corresponding AM for LM%02d %s\n", lmconf->id, lmconf->name);
    jlog("ERROR: you should write all AM/LM combinations to be used for recognition with \"-SR\"\n");
    return FALSE;
  }

  /* create LM process instance */
  lm = j_process_lm_new(recog, lmconf);

  /* assign AM process instance to the LM instance */
  lm->am = am;

  /* load language model */
  if (lm->lmtype == LM_PROB) {
    /* LM (N-gram) */
    if ((lm->winfo = initialize_dict(lm->config, lm->am->hmminfo)) == NULL) {
      jlog("ERROR: m_fusion: failed to initialize dictionary\n");
      return FALSE;
    }
    if (lm->config->ngram_filename_lr_arpa || lm->config->ngram_filename_rl_arpa || lm->config->ngram_filename) {
      if ((lm->ngram = initialize_ngram(lm->config, lm->winfo)) == NULL) {
	jlog("ERROR: m_fusion: failed to initialize N-gram\n");
	return FALSE;
      }
    }
  }
  if (lm->lmtype == LM_DFA) {
    /* DFA */
    if (lm->config->dfa_filename != NULL && lm->config->dictfilename != NULL) {
      /* here add grammar specified by "-dfa" and "-v" to grammar list */
      multigram_add_gramlist(lm->config->dfa_filename, lm->config->dictfilename, lm->config, LM_DFA_GRAMMAR);
    }
    /* load all the specified grammars */
    if (multigram_load_all_gramlist(lm) == FALSE) {
      jlog("ERROR: m_fusion: some error occured in reading grammars\n");
      return FALSE;
    }
    /* setup for later wchmm building */
    multigram_update(lm);
    /* the whole lexicon will be forced to built in the boot sequence,
       so reset the global modification flag here */
    lm->global_modified = FALSE;
  }
  
  jlog("STAT: *** LM%02d %s loaded\n", lmconf->id, lmconf->name);

  return TRUE;
}
Beispiel #2
0
/** 
 * <JA>
 * @brief  第1パス平行認識処理の初期化.
 *
 * MFCC計算のワークエリア確保を行う. また必要な場合は,スペクトル減算用の
 * ワークエリア準備,ノイズスペクトルのロード,CMN用の初期ケプストラム
 * 平均データのロードなども行われる. 
 *
 * この関数は,システム起動後1回だけ呼ばれる.
 * </JA>
 * <EN>
 * @brief  Initializations for the on-the-fly 1st pass decoding.
 *
 * Work areas for all MFCC caculation instances are allocated.
 * Additionaly,
 * some initialization will be done such as allocating work area
 * for spectral subtraction, loading noise spectrum from file,
 * loading initial ceptral mean data for CMN from file, etc.
 *
 * This will be called only once, on system startup.
 * </EN>
 *
 * @param recog [i/o] engine instance
 *
 * @callgraph
 * @callergraph
 */
boolean
RealTimeInit(Recog *recog)
{
  Value *para;
  Jconf *jconf;
  RealBeam *r;
  MFCCCalc *mfcc;


  jconf = recog->jconf;
  r = &(recog->real);

  /* 最大フレーム長を最大入力時間数から計算 */
  /* set maximum allowed frame length */
  r->maxframelen = MAXSPEECHLEN / recog->jconf->input.frameshift;

  /* -ssload 指定時, SS用のノイズスペクトルをファイルから読み込む */
  /* if "-ssload", load noise spectrum for spectral subtraction from file */
  for(mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
    if (mfcc->frontend.ssload_filename && mfcc->frontend.ssbuf == NULL) {
      if ((mfcc->frontend.ssbuf = new_SS_load_from_file(mfcc->frontend.ssload_filename, &(mfcc->frontend.sslen))) == NULL) {
	jlog("ERROR: failed to read \"%s\"\n", mfcc->frontend.ssload_filename);
	return FALSE;
      }
      /* check ssbuf length */
      if (mfcc->frontend.sslen != mfcc->wrk->bflen) {
	jlog("ERROR: noise spectrum length not match\n");
	return FALSE;
      }
      mfcc->wrk->ssbuf = mfcc->frontend.ssbuf;
      mfcc->wrk->ssbuflen = mfcc->frontend.sslen;
      mfcc->wrk->ss_alpha = mfcc->frontend.ss_alpha;
      mfcc->wrk->ss_floor = mfcc->frontend.ss_floor;
    }
  }

  for(mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
  
    para = mfcc->para;

    /* 対数エネルギー正規化のための初期値 */
    /* set initial value for log energy normalization */
    if (para->energy && para->enormal) energy_max_init(&(mfcc->ewrk));
    /* デルタ計算のためのサイクルバッファを用意 */
    /* initialize cycle buffers for delta and accel coef. computation */
    if (para->delta) mfcc->db = WMP_deltabuf_new(para->baselen, para->delWin);
    if (para->acc) mfcc->ab = WMP_deltabuf_new(para->baselen * 2, para->accWin);
    /* デルタ計算のためのワークエリアを確保 */
    /* allocate work area for the delta computation */
    mfcc->tmpmfcc = (VECT *)mymalloc(sizeof(VECT) * para->vecbuflen);
    /* MAP-CMN 用の初期ケプストラム平均を読み込んで初期化する */
    /* Initialize the initial cepstral mean data from file for MAP-CMN */
    if (para->cmn || para->cvn) mfcc->cmn.wrk = CMN_realtime_new(para, mfcc->cmn.map_weight);
    /* -cmnload 指定時, CMN用のケプストラム平均の初期値をファイルから読み込む */
    /* if "-cmnload", load initial cepstral mean data from file for CMN */
    if (mfcc->cmn.load_filename) {
      if (para->cmn) {
	if ((mfcc->cmn.loaded = CMN_load_from_file(mfcc->cmn.wrk, mfcc->cmn.load_filename))== FALSE) {
	  jlog("WARNING: failed to read initial cepstral mean from \"%s\", do flat start\n", mfcc->cmn.load_filename);
	}
      } else {
	jlog("WARNING: CMN not required on AM, file \"%s\" ignored\n", mfcc->cmn.load_filename);
      }
    }

  }
  /* 窓長をセット */
  /* set window length */
  r->windowlen = recog->jconf->input.framesize + 1;
  /* 窓かけ用バッファを確保 */
  /* set window buffer */
  r->window = mymalloc(sizeof(SP16) * r->windowlen);

  return TRUE;
}
Beispiel #3
0
/** 
 * <JA>
 * @brief  第1パス平行音声認識処理のメイン
 *
 * この関数内では,漸次的な特徴量抽出および第1パスの認識が行われる. 
 * 入力データに対して窓掛け・シフトを行いMFCC計算を行いながら,
 * 音声認識を1フレームずつ並列実行する. 
 *
 * 認識処理(decode_proceed())において,音声区間終了が要求される
 * ことがある. この場合,未処理の音声を保存して第1パスを終了する
 * よう呼出元に要求する. 
 *
 * SPSEGMENT_NAIST あるいは GMM_VAD などのバックエンドVAD定義時は,デコーダベースの
 * VAD (音声区間開始検出)に伴うデコーディング制御が行われる. 
 * トリガ前は,認識処理が呼ばれるが,実際には各関数内で認識処理は
 * 行われていない. 開始を検出した時,この関数はそこまでに得られた
 * MFCC列を一定フレーム長分巻戻し,その巻戻し先から通常の認識処理を
 * 再開する. なお,複数処理インスタンス間がある場合,開始トリガは
 * どれかのインスタンスが検出した時点で全ての開始が同期される. 
 * 
 * この関数は,音声入力ルーチンのコールバックとして呼ばれる.
 * 音声データの数千サンプル録音ごとにこの関数が呼び出される. 
 * 
 * @param Speech [in] 音声データへのバッファへのポインタ
 * @param nowlen [in] 音声データの長さ
 * @param recog [i/o] engine instance
 * 
 * @return エラー時に -1 を,正常時に 0 を返す. また,第1パスを
 * 終了するよう呼出元に要求するときは 1 を返す. 
 * </JA>
 * <EN>
 * @brief  Main function of the on-the-fly 1st pass decoding
 *
 * This function performs sucessive MFCC calculation and 1st pass decoding.
 * The given input data are windowed to a certain length, then converted
 * to MFCC, and decoding for the input frame will be performed in one
 * process cycle.  The loop cycle will continue with window shift, until
 * the whole given input has been processed.
 *
 * In case of input segment request from decoding process (in
 * decode_proceed()), this function keeps the rest un-processed speech
 * to a buffer and tell the caller to stop input and end the 1st pass.
 *
 * When back-end VAD such as SPSEGMENT_NAIST or GMM_VAD is defined,  Decoder-based
 * VAD is enabled and its decoding control will be managed here.
 * In decoder-based VAD mode, the recognition will be processed but
 * no output will be done at the first un-triggering input area.
 * when speech input start is detected, this function will rewind the
 * already obtained MFCC sequence to a certain frames, and re-start
 * normal recognition at that point.  When multiple recognition process
 * instance is running, their segmentation will be synchronized.
 * 
 * This function will be called each time a new speech sample comes as
 * as callback from A/D-in routine.
 * 
 * @param Speech [in] pointer to the speech sample segments
 * @param nowlen [in] length of above
 * @param recog [i/o] engine instance
 * 
 * @return -1 on error (will close stream and terminate recognition),
 * 0 on success (allow caller to call me for the next segment).  It
 * returns 1 when telling the caller to segment now at the middle of
 * input , and 2 when input length overflow is detected.
 * </EN>
 *
 * @callgraph
 * @callergraph
 * 
 */
int
RealTimePipeLine(SP16 *Speech, int nowlen, Recog *recog) /* Speech[0...nowlen] = input */
{
  int i, now, ret;
  MFCCCalc *mfcc;
  RealBeam *r;

  r = &(recog->real);

#ifdef DEBUG_VTLN_ALPHA_TEST
  /* store speech */
  adin_cut_callback_store_buffer(Speech, nowlen, recog);
#endif

  /* window[0..windownum-1] は前回の呼び出しで残った音声データが格納されている */
  /* window[0..windownum-1] are speech data left from previous call */

  /* 処理用ポインタを初期化 */
  /* initialize pointer for local processing */
  now = 0;
  
  /* 認識処理がセグメント要求で終わったのかどうかのフラグをリセット */
  /* reset flag which indicates whether the input has ended with segmentation request */
  r->last_is_segmented = FALSE;

#ifdef RDEBUG
  printf("got %d samples\n", nowlen);
#endif

  while (now < nowlen) {	/* till whole input is processed */
    /* 入力長が maxframelen に達したらここで強制終了 */
    /* if input length reaches maximum buffer size, terminate 1st pass here */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      if (mfcc->f >= r->maxframelen) return(1);
    }
    /* 窓バッファを埋められるだけ埋める */
    /* fill window buffer as many as possible */
    for(i = min(r->windowlen - r->windownum, nowlen - now); i > 0 ; i--)
      r->window[r->windownum++] = (float) Speech[now++];
    /* もし窓バッファが埋まらなければ, このセグメントの処理はここで終わる. 
       処理されなかったサンプル (window[0..windownum-1]) は次回に持ち越し. */
    /* if window buffer was not filled, end processing here, keeping the
       rest samples (window[0..windownum-1]) in the window buffer. */
    if (r->windownum < r->windowlen) break;
#ifdef RDEBUG
    /*    printf("%d used, %d rest\n", now, nowlen - now);

	  printf("[f = %d]\n", f);*/
#endif

    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      mfcc->valid = FALSE;
      /* 窓内の音声波形から特徴量を計算して r->tmpmfcc に格納  */
      /* calculate a parameter vector from current waveform windows
	 and store to r->tmpmfcc */
      if ((*(recog->calc_vector))(mfcc, r->window, r->windowlen)) {
#ifdef ENABLE_PLUGIN
	/* call post-process plugin if exist */
	plugin_exec_vector_postprocess(mfcc->tmpmfcc, mfcc->param->veclen, mfcc->f);
#endif
	/* MFCC完成,登録 */
  	mfcc->valid = TRUE;
	/* now get the MFCC vector of current frame, now store it to param */
	if (param_alloc(mfcc->param, mfcc->f + 1, mfcc->param->veclen) == FALSE) {
	  jlog("ERROR: failed to allocate memory for incoming MFCC vectors\n");
	  return -1;
	}
	memcpy(mfcc->param->parvec[mfcc->f], mfcc->tmpmfcc, sizeof(VECT) * mfcc->param->veclen);
#ifdef RDEBUG
	printf("DeltaBuf: %02d: got frame %d\n", mfcc->id, mfcc->f);
#endif
      }
    }

    /* 処理を1フレーム進める */
    /* proceed one frame */
    ret = proceed_one_frame(recog);

    if (ret == 1 && recog->jconf->decodeopt.segment) {
      /* ショートポーズセグメンテーション: バッファに残っているデータを
	 別に保持して,次回の最初に処理する */
      /* short pause segmentation: there is some data left in buffer, so
	 we should keep them for next processing */
      r->rest_len = nowlen - now;
      if (r->rest_len > 0) {
	/* copy rest samples to rest_Speech */
	if (r->rest_Speech == NULL) {
	  r->rest_alloc_len = r->rest_len;
	  r->rest_Speech = (SP16 *)mymalloc(sizeof(SP16)*r->rest_alloc_len);
	} else if (r->rest_alloc_len < r->rest_len) {
	  r->rest_alloc_len = r->rest_len;
	  r->rest_Speech = (SP16 *)myrealloc(r->rest_Speech, sizeof(SP16)*r->rest_alloc_len);
	}
	memcpy(r->rest_Speech, &(Speech[now]), sizeof(SP16) * r->rest_len);
      }
    }
    if (ret != 0) return ret;

    /* 1フレーム処理が進んだのでポインタを進める */
    /* proceed frame pointer */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      if (!mfcc->valid) continue;
      mfcc->f++;
    }

    /* 窓バッファを処理が終わった分シフト */
    /* shift window */
    memmove(r->window, &(r->window[recog->jconf->input.frameshift]), sizeof(SP16) * (r->windowlen - recog->jconf->input.frameshift));
    r->windownum -= recog->jconf->input.frameshift;
  }

  /* 与えられた音声セグメントに対する認識処理が全て終了
     呼び出し元に, 入力を続けるよう伝える */
  /* input segment is fully processed
     tell the caller to continue input */
  return(0);			
}
Beispiel #4
0
static
int login_finish_login(struct clientinfo* clntinfo) {
	char* buffer;

	if (stage_action("loggedin") < 0) {
		say(clntinfo->clientsocket, "421 Error setting up (see logfile)\r\n");
		return CMD_ABORT;
	}

	clntinfo->login.authresp = readall(clntinfo->serversocket);
	if (!clntinfo->login.authresp.fullmsg) {
		if (timeout) {
			jlog(2, "Timeout in %s line %d\n", __FILE__,
					__LINE__);
			err_time_readline(clntinfo->clientsocket);
		}
		else {
			err_readline(clntinfo->clientsocket);
		}
		if (clntinfo->login.welcomemsg.fullmsg) {
			free(clntinfo->login.welcomemsg.fullmsg);
		}
		return CMD_ABORT;
	}

	if (clntinfo->login.welcomemsg.fullmsg) {
		/* we have not yet sent the welcome message to the client */
		buffer = merge_responses(clntinfo->login.welcomemsg.fullmsg,
					clntinfo->login.authresp.fullmsg);
		/* free the welcome message */
		free(clntinfo->login.welcomemsg.fullmsg);
		clntinfo->login.welcomemsg.fullmsg
			= clntinfo->login.welcomemsg.lastmsg = (char*) 0;
	} else {
		/* if the welcome message is sent, just copy the
		 * authentication response */
		buffer = strdup(clntinfo->login.authresp.fullmsg);
		enough_mem(buffer);
	}

	lcs.respcode = getcode(clntinfo->login.authresp.lastmsg);

	if (!checkdigits(clntinfo->login.authresp.lastmsg, 230)) {
		say(clntinfo->clientsocket,
				clntinfo->login.authresp.lastmsg);
		jlog(8, "Got \"%s\" after sending the password",
				clntinfo->login.authresp.fullmsg);
		free(clntinfo->login.authresp.fullmsg);
		free(buffer);
		clntinfo->login.authresp.fullmsg   = (char*) 0;
		clntinfo->login.authresp.lastmsg   = (char*) 0;
		return CMD_ERROR;
	}
	free(clntinfo->login.authresp.fullmsg);
	clntinfo->login.authresp.fullmsg   = (char*) 0;
	clntinfo->login.authresp.lastmsg   = (char*) 0;

	/* Now the client receives the welcome message as well as the
	 * response of the server from the authentication with the same code
	 * at the beginning */
	say(clntinfo->clientsocket, buffer);
	free(buffer);
	buffer =0;

	return CMD_HANDLED;
}
Beispiel #5
0
/** 
 * <JA>
 * @brief  第1パス平行認識処理の終了処理を行う.
 *
 * この関数は第1パス終了時に呼ばれ,入力長を確定したあと,
 * decode_end() (セグメントで終了したときは decode_end_segmented())を
 * 呼び出して第1パス終了処理を行う. 
 *
 * もし音声入力ストリームの終了によって認識が終わった場合(ファイル入力で
 * 終端に達した場合など)は,デルタバッファに未処理の入力が残っているので,
 * それをここで処理する. 
 *
 * @param recog [i/o] エンジンインスタンス
 * 
 * @return 処理成功時 TRUE, エラー時 FALSE を返す. 
 * </JA>
 * <EN>
 * @brief  Finalize the 1st pass on-the-fly decoding.
 *
 * This function will be called after the 1st pass processing ends.
 * It fix the input length of parameter vector sequence, call
 * decode_end() (or decode_end_segmented() when last input was ended
 * by segmentation) to finalize the 1st pass.
 *
 * If the last input was ended by end-of-stream (in case input reached
 * EOF in file input etc.), process the rest samples remaining in the
 * delta buffers.
 *
 * @param recog [i/o] engine instance
 * 
 * @return TRUE on success, or FALSE on error.
 * </EN>
 */
boolean
RealTimeParam(Recog *recog)
{
  boolean ret1, ret2;
  RealBeam *r;
  int ret;
  int maxf;
  boolean ok_p;
  MFCCCalc *mfcc;
  Value *para;
#ifdef RDEBUG
  int i;
#endif

  r = &(recog->real);

  if (r->last_is_segmented) {

    /* RealTimePipeLine で認識処理側の理由により認識が中断した場合,
       現状態のMFCC計算データをそのまま次回へ保持する必要があるので,
       MFCC計算終了処理を行わずに第1パスの結果のみ出力して終わる. */
    /* When input segmented by recognition process in RealTimePipeLine(),
       we have to keep the whole current status of MFCC computation to the
       next call.  So here we only output the 1st pass result. */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      mfcc->param->header.samplenum = mfcc->f + 1;/* len = lastid + 1 */
      mfcc->param->samplenum = mfcc->f + 1;
    }
    decode_end_segmented(recog);

    /* この区間の param データを第2パスのために返す */
    /* return obtained parameter for 2nd pass */
    return(TRUE);
  }

  if (recog->jconf->input.type == INPUT_VECTOR) {
    /* finalize real-time 1st pass */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      mfcc->param->header.samplenum = mfcc->f;
      mfcc->param->samplenum = mfcc->f;
    }
    /* 最終フレーム処理を行い,認識の結果出力と終了処理を行う */
    decode_end(recog);
    return TRUE;
  }

  /* MFCC計算の終了処理を行う: 最後の遅延フレーム分を処理 */
  /* finish MFCC computation for the last delayed frames */
  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
    if (mfcc->para->delta || mfcc->para->acc) {
      mfcc->valid = TRUE;
    } else {
      mfcc->valid = FALSE;
    }
  }

  /* loop until all data has been flushed */
  while (1) {

    /* check frame overflow */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      if (! mfcc->valid) continue;
      if (mfcc->f >= r->maxframelen) mfcc->valid = FALSE;
    }

    /* if all mfcc became invalid, exit loop here */
    ok_p = FALSE;
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      if (mfcc->valid) {
	ok_p = TRUE;
	break;
      }
    }
    if (!ok_p) break;

    /* try to get 1 frame for all mfcc instances */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      
      para = mfcc->para;
      
      if (! mfcc->valid) continue;
      
      /* check if there is data in cycle buffer of delta */
      ret1 = WMP_deltabuf_flush(mfcc->db);
#ifdef RDEBUG
      printf("DeltaBufLast: ret=%d, status=", ret1);
      for(i=0;i<mfcc->db->len;i++) {
	printf("%d", mfcc->db->is_on[i]);
      }
      printf(", nextstore=%d\n", mfcc->db->store);
#endif
      if (ret1) {
	/* uncomputed delta has flushed, compute it with tmpmfcc */
	if (para->energy && para->absesup) {
	  memcpy(mfcc->tmpmfcc, mfcc->db->vec, sizeof(VECT) * (para->baselen - 1));
	  memcpy(&(mfcc->tmpmfcc[para->baselen-1]), &(mfcc->db->vec[para->baselen]), sizeof(VECT) * para->baselen);
	} else {
	  memcpy(mfcc->tmpmfcc, mfcc->db->vec, sizeof(VECT) * para->baselen * 2);
	}
	if (para->acc) {
	  /* this new delta should be given to the accel cycle buffer */
	  ret2 = WMP_deltabuf_proceed(mfcc->ab, mfcc->tmpmfcc);
#ifdef RDEBUG
	  printf("AccelBuf: ret=%d, status=", ret2);
	  for(i=0;i<mfcc->ab->len;i++) {
	    printf("%d", mfcc->ab->is_on[i]);
	  }
	  printf(", nextstore=%d\n", mfcc->ab->store);
#endif
	  if (ret2) {
	    /* uncomputed accel was given, compute it with tmpmfcc */
	    memcpy(mfcc->tmpmfcc, mfcc->ab->vec, sizeof(VECT) * (para->veclen - para->baselen));
	    memcpy(&(mfcc->tmpmfcc[para->veclen - para->baselen]), &(mfcc->ab->vec[para->veclen - para->baselen]), sizeof(VECT) * para->baselen);
	  } else {
	    /* still no input is given: */
	    /* in case of very short input: go on to the next input */
	    continue;
	  }
	}
	
      } else {
      
	/* no data left in the delta buffer */
	if (para->acc) {
	  /* no new data, just flush the accel buffer */
	  ret2 = WMP_deltabuf_flush(mfcc->ab);
#ifdef RDEBUG
	  printf("AccelBuf: ret=%d, status=", ret2);
	  for(i=0;i<mfcc->ab->len;i++) {
	    printf("%d", mfcc->ab->is_on[i]);
	  }
	  printf(", nextstore=%d\n", mfcc->ab->store);
#endif
	  if (ret2) {
	    /* uncomputed data has flushed, compute it with tmpmfcc */
	    memcpy(mfcc->tmpmfcc, mfcc->ab->vec, sizeof(VECT) * (para->veclen - para->baselen));
	    memcpy(&(mfcc->tmpmfcc[para->veclen - para->baselen]), &(mfcc->ab->vec[para->veclen - para->baselen]), sizeof(VECT) * para->baselen);
	  } else {
	    /* actually no data exists in both delta and accel */
	    mfcc->valid = FALSE; /* disactivate this instance */
	    continue;		/* end this loop */
	  }
	} else {
	  /* only delta: input fully flushed */
	  mfcc->valid = FALSE; /* disactivate this instance */
	  continue;		/* end this loop */
	}
      }
      /* a new frame has been obtained from delta buffer to tmpmfcc */
      if(para->cmn || para->cvn) CMN_realtime(mfcc->cmn.wrk, mfcc->tmpmfcc);
      if (param_alloc(mfcc->param, mfcc->f + 1, mfcc->param->veclen) == FALSE) {
	jlog("ERROR: failed to allocate memory for incoming MFCC vectors\n");
	return FALSE;
      }
      /* store to mfcc->f */
      memcpy(mfcc->param->parvec[mfcc->f], mfcc->tmpmfcc, sizeof(VECT) * mfcc->param->veclen);
#ifdef ENABLE_PLUGIN
      /* call postprocess plugin if any */
      plugin_exec_vector_postprocess(mfcc->param->parvec[mfcc->f], mfcc->param->veclen, mfcc->f);
#endif
    }

    /* call recognition start callback */
    ok_p = FALSE;
    maxf = 0;
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      if (!mfcc->valid) continue;
      if (maxf < mfcc->f) maxf = mfcc->f;
      if (mfcc->f == 0) {
	ok_p = TRUE;
      }
    }

    if (ok_p && maxf == 0) {
      /* call callback when at least one of MFCC has initial frame */
      if (recog->jconf->decodeopt.segment) {
#ifdef BACKEND_VAD
	  /* not exec pass1 begin callback here */
#else
	if (!recog->process_segment) {
	  callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
	}
	callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
	callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
	recog->triggered = TRUE;
#endif
      } else {
	callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
	callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
	recog->triggered = TRUE;
      }
    }

    /* proceed for the curent frame */
    ret = decode_proceed(recog);
    if (ret == -1) {		/* error */
      return -1;
    } else if (ret == 1) {	/* segmented */
      /* loop out */
      break;
    } /* else no event occured */

#ifdef BACKEND_VAD
    /* check up trigger in case of VAD segmentation */
    if (recog->jconf->decodeopt.segment) {
      if (recog->triggered == FALSE) {
	if (spsegment_trigger_sync(recog)) {
	  if (!recog->process_segment) {
	    callback_exec(CALLBACK_EVENT_RECOGNITION_BEGIN, recog);
	  }
	  callback_exec(CALLBACK_EVENT_SEGMENT_BEGIN, recog);
	  callback_exec(CALLBACK_EVENT_PASS1_BEGIN, recog);
	  recog->triggered = TRUE;
	}
      }
    }
#endif

    /* call frame-wise callback */
    callback_exec(CALLBACK_EVENT_PASS1_FRAME, recog);

    /* move to next */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      if (! mfcc->valid) continue;
      mfcc->f++;
    }
  }

  /* finalize real-time 1st pass */
  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
    mfcc->param->header.samplenum = mfcc->f;
    mfcc->param->samplenum = mfcc->f;
  }
  /* 最終フレーム処理を行い,認識の結果出力と終了処理を行う */
  decode_end(recog);

  return(TRUE);
}
Beispiel #6
0
static
int login_mayconnect(struct clientinfo* clntinfo) {
	int allowed = 0;
	unsigned long int target;
	unsigned long int host_ip;
	unsigned long int client_ip, server_ip;
	int tags;

	allowed = 0;

	/* we don't know yet if clntinfo->destination is a hostname like
	 * "somehost.foo.com" or if it is an IP in a char* like
	 * "212.117.232.20"
	 *
	 * So call inet_addr(), it should make the decision  :-)
	 *
	 * */
	target = inet_addr(clntinfo->destination);

	/* get the client_ip by asking information about the socket the
	 * client is connected */
	client_ip = get_uint_ip(GET_IP_CLIENT, clntinfo);
	server_ip = (unsigned long int) UINT_MAX;

	if (target == (unsigned long int) UINT_MAX) {
		/* clntinfo->destination may be a hostname, but it needn't.
		 * It may also be an invalid IP: "393.39.239.500" or
		 * anything else. Look it up.
		 * */
		host_ip = hostent_get_ip(&hostcache, clntinfo->destination);
		if (host_ip != (unsigned long int) UINT_MAX) {
			/* successful lookup */
			server_ip = host_ip;
		} else {
			/* it's not a valid IP and we could not look it up,
			 * so we could not get valid information about the
			 * destination host */
			jlog(7, "Nonsense destination (no IP and could not look up hostname): %s",
					clntinfo->destination);
			jlog(8, "Please check your nameserver configuration. This may also happen if your chroot-environment does not contain the necessary files which the libc needs for a lookup");
			allowed = 0;
		}
	} else {
		/* okay, it's an IP */
		server_ip = inet_addr(clntinfo->destination);
	}

	if (server_ip != (unsigned long) UINT_MAX) {
		/* we could get a valid IP, now we can evaluate if client
		 * is allowed to connect to the destination host */
		jlog(9, "Checking all tags");
		tags = TAG_ALL_NOT_FORWARDED;
		if (clntinfo->before_forward.user) {
			/* if we are treating a forward, add this value, it
			 * won't come up in the option list otherwise */
			tags |= TAG_FORWARDED;
		}
		/* checking of the configuration works such:
		 *
		 * no forward:   do not evaluate <forwarded>
		 *               always check the normal values
		 *
		 * forward:      evaluate <forwarded>
		 *               if (!in_forwarded_tag) {
		 *     (1)             check before_forward.* values
		 *               } else {
		 *     (2)             check normal values
		 *               }
		 */
		if (clntinfo->before_forward.user) {
			/* Yes, there was a forward applied */
			config_shrink_config(client_ip,
				/* this are the original values */
				/* see above (1) */
				clntinfo->before_forward.dest_ip,
				clntinfo->before_forward.destination,
				clntinfo->before_forward.destinationport,
				clntinfo->before_forward.user,
				/* these are the values set by the forward */
				/* pass them as well, if we are in the
				 * forwarded_tag, config_match_section()
				 * will overwrite the previous with the
				 * following values */
				server_ip,
				clntinfo->destination,
				clntinfo->destinationport,
				clntinfo->user,
				0,		/* set no specific time */
				clntinfo->proxy_ip,
				clntinfo->proxy_port,
				srvinfo.servertype,
				&hostcache,
				tags);
		} else {
			/* not a forward */
			config_shrink_config(client_ip,
				server_ip,
				clntinfo->destination,
				clntinfo->destinationport,
				clntinfo->user,
				clntinfo->before_forward.dest_ip,
				clntinfo->before_forward.destination,
				clntinfo->before_forward.destinationport,
				clntinfo->before_forward.user,
				0,		/* set no specific time */
				clntinfo->proxy_ip,
				clntinfo->proxy_port,
				srvinfo.servertype,
				&hostcache,
				tags);
		}

		allowed = strcmp(config_get_option("access"), "allow") == 0;
	}

	if (!allowed) {
		say(clntinfo->clientsocket, "531 You are not allowed to connect to that host.\r\n");
		jlog(8, "Not allowed to connect to %s", clntinfo->destination);
		lcs.respcode = 531;
		return CMD_ERROR;
	}
	/* if the client was allowed, save the clients original IP */
	if (!clntinfo->before_forward.user) {
		clntinfo->before_forward.dest_ip = server_ip;
	}
	return allowed;  /* a positive int */
}
Beispiel #7
0
int handle_login(struct clientinfo* clntinfo) {
	struct cmdhandlerstruct *cmdhandler;
	char *buffer = 0;
	int ss, cs;
	int i, expected;
	int protoviolations = 0;

	conn_info.lcs = &lcs;
	conn_info.clntinfo = clntinfo;
	ss = clntinfo->serversocket;
	cs = clntinfo->clientsocket;

	if (clntinfo->transparent == TRANSPARENT_YES
		/* we are connected */
		&&
	    config_compare_option("logintime", "connect")) {

		if (config_get_ioption("loginstyle", 0) != 0) {
			jlog(5, "A login at the connection time only works with loginstyle == 0, setting loginstyle = 0");

			config_option_list_delete("loginstyle");
			config_option_list_add("loginstyle", "0");
		}
	}

	cmdhandler = &login_auth_funcs
				[ config_get_ioption("loginstyle", 0) ][0];

	expected = QUITFUNC + 1;    /* skip reset and quit function */
	while (1) {
		if (timeout) {
			jlog(2, "Timeout in %s line %d\n", __FILE__ ,__LINE__);
			return -1;
		}
		if (buffer) {
			free(buffer);
			buffer = 0;
		}

		buffer = readline(cs);
		lcs.cmd = (char*) 0;

		if (buffer) {
			lcs.cmd = buffer;
			free(lcs.method);
			i = 0;
			lcs.method = quotstrtok(lcs.cmd, WHITESPACES, &i);

			if (buffer[0] == '\0') {
				/* empty line. Prevent logging of the
				 * command */
				free(buffer);
				buffer = 0;
				continue;
			}
			/* log the command */
			log_cmd(&lcs);
			free(lcs.method); lcs.method = (char*) 0;
			lcs.respcode = 0;
			lcs.transferred = 0;
		}

		if (!buffer) {
			if (timeout) {
				jlog(2, "Timeout in %s line %d\n", __FILE__
						,__LINE__);
				err_time_readline(cs);
			} else {
				err_readline(cs);
			}
			return -1;
		}

		jlog(8, "Expecting %s", cmdhandler[expected].cmd);
		if (my_strcasestr(buffer, "PASS") == (char*) 0) {
			jlog(8, "Got: %s", buffer);
		} else {
			jlog(8, "Got the password");
		}

		/* check for QUIT */
		if (checkbegin(buffer, "QUIT")) {
			int ret = (cmdhandler[QUITFUNC].func)
						(buffer, &conn_info);
			ret = (cmdhandler[RESETFUNC].func)
						(buffer, &conn_info);
			free(buffer);
			/* return 1 to prevent the proxy from entering
			 * handle_cmds */
			return 1;
		}
		if (cmdhandler[expected].cmd 
			&& checkbegin(buffer, cmdhandler[expected].cmd)) {

			int ret = (cmdhandler[expected].func)
						(buffer, &conn_info);
			memset(buffer, 0, strlen(buffer));
			protoviolations = 0;
			switch (ret) {
				case CMD_DONE:
					/* we're done - logged in */
					/* CMD_DONE is returned if the USER
					 * command got a 230 response back
					 * */
					break;
				case CMD_HANDLED:
					/* expecting the next */
					expected++;
					break;
				case CMD_ERROR:
					/* reset counter, skip reset and
					 * quit function */
					ret = (cmdhandler[RESETFUNC].func)
							(buffer, &conn_info);
					expected = QUITFUNC + 1;
					/* errors are handled by the
					 * command handler functions
					 * */
					break;
				case CMD_ABORT:
					return -1;
					break;
			}
			/* found and called proper function */
		} else {
			protoviolations++;
			if (protoviolations >=
			    config_get_ioption("loginprotocolviolations", 10)){
				/* like ABORT */
				sayf(clntinfo->clientsocket,
					"500 Too many consequent protocol "
					"violations - Closing connection\r\n");
				return -1;
			}
			sayf(clntinfo->clientsocket,
				"530 Login incorrect. Expected %scommand\r\n",
				cmdhandler[expected].cmd);
			/* reset counter, skip reset and quit function */
			(cmdhandler[RESETFUNC].func)
						(buffer, &conn_info);
			expected = QUITFUNC + 1;
		}
		if (clntinfo->login.stage == LOGIN_ST_FULL) {
			/* we are done */
			free(buffer); buffer = (char*) 0;
			return 0;
		}
	}
	/* lcs.host and lcs.user  are freed at the termination of the
	 * programm */
}
/** 
 * Write a whole N-gram data in binary format.
 * 
 * @param fp [in] file pointer
 * @param ndata [in] N-gram data to write
 * @param headerstr [in] user header string
 * 
 * @return TRUE on success, FALSE on failure
 */
boolean
ngram_write_bin(FILE *fp, NGRAM_INFO *ndata, char *headerstr)
{
  int i,n;
  unsigned int len;
  int wlen;
  NGRAM_TUPLE_INFO *t;

  reset_wrt_counter();

  /* write initial header */
  if (write_header(fp, headerstr) == FALSE) return FALSE;

  /* swap not needed any more */
  need_swap = FALSE;

  /* write some header info */
  wrt(fp, &(ndata->n), sizeof(int), 1);
  wrt(fp, &(ndata->dir), sizeof(int), 1);
  wrt(fp, &(ndata->bigram_index_reversed), sizeof(boolean), 1);

  /* write total info */
  for(n=0;n<ndata->n;n++) {
    wrt(fp, &(ndata->d[n].totalnum), sizeof(NNID), 1);
    /*jlog("ngram %d=%d\n",n+1,ndata->ngram_num[n]);*/
  }

  /* unk_*, isopen, max_word_num are set after read, so need not save */

  /* write wname */
  wlen = 0;
  for(i=0;i<ndata->max_word_num;i++) {
    wlen += strlen(ndata->wname[i]) + 1;
  }
  wrt(fp, &wlen, sizeof(int), 1);
  for(i=0;i<ndata->max_word_num;i++) {
    wrt(fp, ndata->wname[i], 1, strlen(ndata->wname[i]) + 1); /* include \0 */
  }

  /* write N-gram */
  for(n=0;n<ndata->n;n++) {
    t = &(ndata->d[n]);

    wrt(fp, &(t->is24bit), sizeof(boolean), 1);
    wrt(fp, &(t->ct_compaction), sizeof(boolean), 1);
    wrt(fp, &(t->bgnlistlen), sizeof(NNID), 1);
    wrt(fp, &(t->context_num), sizeof(NNID), 1);
    if (n > 0) {
      if (t->is24bit) {
	wrt(fp, t->bgn_upper, sizeof(NNID_UPPER), t->bgnlistlen);
	wrt(fp, t->bgn_lower, sizeof(NNID_LOWER), t->bgnlistlen);
      } else {
	wrt(fp, t->bgn, sizeof(NNID), t->bgnlistlen);
      }
      wrt(fp, t->num, sizeof(WORD_ID), t->bgnlistlen);
      wrt(fp, t->nnid2wid, sizeof(WORD_ID), t->totalnum);
    }
    wrt(fp, t->prob, sizeof(LOGPROB), t->totalnum);
    if (t->bo_wt) {
      i = 1;
      wrt(fp, &i, sizeof(int), 1);
      wrt(fp, t->bo_wt, sizeof(LOGPROB), t->context_num);
    } else {
      i = 0;
      wrt(fp, &i, sizeof(int), 1);
    }
    if (t->nnid2ctid_upper) {
      i = 1;
      wrt(fp, &i, sizeof(int), 1);
      wrt(fp, t->nnid2ctid_upper, sizeof(NNID_UPPER), t->totalnum);
      wrt(fp, t->nnid2ctid_lower, sizeof(NNID_LOWER), t->totalnum);
    } else {
      i = 0;
      wrt(fp, &i, sizeof(int), 1);
    }

  }

  /* write additional LR 2-gram */
  if (ndata->bo_wt_1) {
    i = 1;
    wrt(fp, &i, sizeof(int), 1);
    wrt(fp, ndata->bo_wt_1, sizeof(LOGPROB), ndata->d[0].context_num);
  } else {
    i = 0;
    wrt(fp, &i, sizeof(int), 1);
  }
  if (ndata->p_2) {
    i = 1;
    wrt(fp, &i, sizeof(int), 1);
    wrt(fp, ndata->p_2, sizeof(LOGPROB), ndata->d[1].totalnum);
  } else {
    i = 0;
    wrt(fp, &i, sizeof(int), 1);
  }

  len = get_wrt_counter();
  jlog("Stat: ngram_write_bin: wrote %lu bytes (%.1f MB)\n", len, len / 1048576.0);
  return TRUE;
}
/** 
 * <JA>
 * 最後の1単語の前向きトレリスを計算して,文仮説の前向き尤度を更新する. 
 * 
 * @param now [i/o] 文仮説
 * @param param [in] 入力パラメータ列
 * @param r [in] 認識処理インスタンス
 * 
 * </JA>
 * <EN>
 * Compute the forward viterbi for the last word to update forward scores
 * and ready for word connection.
 * 
 * @param now [i/o] hypothesis
 * @param param [in] input parameter vectors
 * @param r [in] recognition process instance
 * 
 * </EN>
 * @callgraph
 * @callergraph
 */
void
scan_word(NODE *now, HTK_Param *param, RecogProcess *r)
{
  int   i,t, j;
  HMM *whmm;
  A_CELL *ac;
  WORD_ID word;
  LOGPROB tmpmax, tmptmp, score1;
  int startt = 0, endt;
  int wordhmmnum;
  LOGPROB tmpmax_store, store_point_maxarc; /* multipath */
  LOGPROB tmpmax2 = LOG_ZERO;
  int phmmlen;
  HMM_Logical *ret, *wend;
  int store_point;
  int crossword_point = 0;
  boolean back_rescan = FALSE;
  boolean node_exist_p;
  int tn;		       ///< Temporal pointer to current buffer
  int tl;		       ///< Temporal pointer to previous buffer

  /* store global values to local for rapid access */
  WORD_INFO *winfo;
  HTK_HMM_INFO *hmminfo;
  LOGPROB *framemaxscore;
  int peseqlen;
  boolean ccd_flag;
  boolean enable_iwsp;
#ifdef SCAN_BEAM
  LOGPROB scan_beam_thres;
#endif
  StackDecode *dwrk;

  winfo = r->lm->winfo;
  hmminfo = r->am->hmminfo;
  dwrk = &(r->pass2);
  peseqlen = r->peseqlen;
  framemaxscore = r->pass2.framemaxscore;
  ccd_flag = r->ccd_flag;
  enable_iwsp = r->lm->config->enable_iwsp; /* multipath */
#ifdef SCAN_BEAM
  scan_beam_thres = r->config->pass2.scan_beam_thres;
#endif

  if (hmminfo->multipath) {
    store_point = -1;
  } else {
    store_point = 0;
  }
  
  /* ----------------------- prepare HMM ----------------------- */

  if (ccd_flag) {
    /* 直前の音素があれば,そこまでさかのぼって scan する */
    /* if there are any last phone, enable backscan */
    if (now->last_ph == NULL) {
      /* initial score: now->g[] */
      /* scan range: phones in now->seq[now->seqnum-1] */
      back_rescan = FALSE;
    } else {
      /* initial score: now->g_prev[] (1-phone before)*/
      /* scan range: phones in now->seq[now->seqnum-1] + now->last_ph */
      back_rescan = TRUE;
    }
  }
#ifdef TCD
  if (now->last_ph != NULL) {
    jlog("DEBUG: inherited last_ph: %s\n", (now->last_ph)->name);
    if (now->last_ph_sp_attached) jlog("DEBUG: (sp attached)\n"); /* multipath */
  } else {
    jlog("DEBUG: no last_ph inherited\n");
  }
#endif

  /* scan 範囲分のHMMを準備 */
  /* prepare HMM of the scan range */
  word = now->seq[now->seqnum-1];

  if (ccd_flag) {

    if (back_rescan) {
      
      /* scan range: phones in now->seq[now->seqnum-1] + now->last_ph */
      
      phmmlen = winfo->wlen[word] + 1;
      if (phmmlen > dwrk->phmmlen_max) {
	j_internal_error("scan_word: num of phonemes in a word exceed phmmlenmax (%d) ?\n", dwrk->phmmlen_max);
      }
      for (i=0;i<phmmlen - 2;i++) dwrk->phmmseq[i] = winfo->wseq[word][i];
      if (enable_iwsp && hmminfo->multipath) {
	for (i=0;i<phmmlen - 2;i++) dwrk->has_sp[i] = FALSE;
      }

      /* 最終単語と last_ph 間の単語間triphoneを考慮 */
      /* consider cross-word context dependency between the last word and now->last_ph */
      wend = winfo->wseq[word][winfo->wlen[word]-1];
      ret = get_right_context_HMM(wend, now->last_ph->name, hmminfo);
      if (ret == NULL) {	/* triphone not found */
	/* fallback to the original bi/mono-phone */
	/* error if the original is pseudo phone (not explicitly defined
	   in hmmdefs/hmmlist) */
	/* exception: word with 1 phone (triphone may exist in the next expansion */
	if (winfo->wlen[word] > 1 && wend->is_pseudo) {
	  error_missing_right_triphone(wend, now->last_ph->name);
	}
	dwrk->phmmseq[phmmlen-2] = wend;
      } else {
	dwrk->phmmseq[phmmlen-2] = ret;
      }
      ret = get_left_context_HMM(now->last_ph, wend->name, hmminfo);
      if (ret == NULL) {
	/* fallback to the original bi/mono-phone */
	/* error if the original is pseudo phone (not explicitly defined
	   in hmmdefs/hmmlist) */
	if (now->last_ph->is_pseudo) {
	  error_missing_left_triphone(now->last_ph, wend->name);
	}
	dwrk->phmmseq[phmmlen-1] = now->last_ph;
      } else {
	dwrk->phmmseq[phmmlen-1] = ret;
      }

      if (enable_iwsp && hmminfo->multipath) {
	dwrk->has_sp[phmmlen-2] = TRUE;
	dwrk->has_sp[phmmlen-1] = now->last_ph_sp_attached;
      }
 
#ifdef TCD
      jlog("DEBUG: w=");
      for(i=0;i<winfo->wlen[word];i++) {
	jlog(" %s",(winfo->wseq[word][i])->name);
	if (enable_iwsp && hmminfo->multipath && dwrk->has_sp[i]) jlog("(sp)");
      }
      jlog(" | %s\n", (now->last_ph)->name);
      if (hmminfo->multipath && now->last_ph_sp_attached) jlog("DEBUG:   (sp)\n");
      jlog("DEBUG: scan for:");
      
      for (i=0;i<phmmlen;i++) {
	jlog(" %s", dwrk->phmmseq[i]->name);
 	if (enable_iwsp && hmminfo->multipath && dwrk->has_sp[i]) jlog("(sp)");
      }
      jlog("\n");
#endif

      /* 単語HMMを作る */
      /* make word HMM */
      whmm = new_make_word_hmm(hmminfo, dwrk->phmmseq, phmmlen, (enable_iwsp && hmminfo->multipath) ? dwrk->has_sp : NULL);
      if (whmm == NULL) {
	j_internal_error("Error: failed to make word hmm for word #%d \"%s [%s]\"\n", word, winfo->wname[word], winfo->woutput[word]);
      }
      
      /* backscan なので,計算前の g[] 初期値は now->g_prev[] を使用 */
      /* As backscan enabled, the initial forward score g[] is set by
	 now->g_prev[] */
      for (t=0;t<peseqlen;t++) {
	dwrk->g[t]=now->g_prev[t];

      }
      
      /* 次段用のg_prevを格納するノード位置を設定 */
      /* set where to store scores as new g_prev[] for the next backscan
	 in the HMM */
      if (hmminfo->multipath) {
	store_point = hmm_logical_state_num(dwrk->phmmseq[0]) - 2;
	store_point_maxarc = max_out_arc(dwrk->phmmseq[0]);
	if (enable_iwsp && dwrk->has_sp[0]) {
	  store_point += hmm_logical_state_num(hmminfo->sp) - 2;
	  if (store_point_maxarc < max_out_arc(hmminfo->sp)) {
	    store_point_maxarc = max_out_arc(hmminfo->sp);
	  }
	}
      } else {
	store_point = hmm_logical_state_num(dwrk->phmmseq[0]) - 2 - 1;
      }
      /* scan中に直前単語とこの単語をまたぐ場所を設定 */
      /* set where is the connection point of the last word in the HMM */
      if (hmminfo->multipath) {
	crossword_point = whmm->len - hmm_logical_state_num(dwrk->phmmseq[phmmlen-1]);
	if (enable_iwsp && dwrk->has_sp[phmmlen-1]) {
	  crossword_point -= hmm_logical_state_num(hmminfo->sp) - 2;
	}
      } else {
	crossword_point = whmm->len - (hmm_logical_state_num(dwrk->phmmseq[phmmlen-1]) - 2) - 1;
      }
      
    } else {			/* not backscan mode */
      
      /* scan range: phones in now->seq[now->seqnum-1] */
      
#ifdef TCD
      jlog("DEBUG: scan(org):");
      for (i=0;i<winfo->wlen[word];i++) {
	jlog(" %s", (winfo->wseq[word][i])->name);
      }
      jlog("\n");
#endif

      if (enable_iwsp && hmminfo->multipath) {
	/* 必要ならばショートポーズを挟み込む位置を指定する */
	for(i=0;i<winfo->wlen[word];i++) {
	  dwrk->has_sp[i] = FALSE;
	}
	dwrk->has_sp[winfo->wlen[word]-1] = TRUE;
      }
      
      /* 単語HMMを作る */
      /* make word HMM */
      whmm = new_make_word_hmm(hmminfo, winfo->wseq[word], winfo->wlen[word], (enable_iwsp && hmminfo->multipath) ? dwrk->has_sp : NULL);
      if (whmm == NULL) {
	j_internal_error("Error: failed to make word hmm for word #%d \"%s [%s]\"\n", word, winfo->wname[word], winfo->woutput[word]);
      }
      
      /* 計算前の g[] 初期値は now->g[] を使用 */
      /* the initial forward score g[] is set by now->g[] */
      for (t=0;t<peseqlen;t++) {
	dwrk->g[t]=now->g[t];
      }
      
      /* 次段用のg_prevを格納するノード位置を設定 */
      /* set where to store scores as new g_prev[] for the next backscan
	 in the HMM */
      if (hmminfo->multipath) {
	store_point = hmm_logical_state_num(winfo->wseq[word][0]) - 2;
	store_point_maxarc = max_out_arc(winfo->wseq[word][0]);
	if (enable_iwsp && dwrk->has_sp[0]) {
	  store_point += hmm_logical_state_num(hmminfo->sp) - 2;
	  if (store_point_maxarc < max_out_arc(hmminfo->sp)) {
	    store_point_maxarc = max_out_arc(hmminfo->sp);
	  }
	}
      } else {
	store_point = hmm_logical_state_num(winfo->wseq[word][0]) - 2 - 1;
      }

      /* scan中に直前単語とこの単語をまたぐ場所は,なし */
      /* the connection point of the last word is not exist in the HMM */
      crossword_point = -1;
    }
    
  } else {			/* ccd_flag == FALSE */

    if (enable_iwsp && hmminfo->multipath) {
      /* 必要ならばショートポーズを挟み込む位置を指定する */
      for(i=0;i<winfo->wlen[word];i++) {
	dwrk->has_sp[i] = FALSE;
      }
      dwrk->has_sp[winfo->wlen[word]-1] = TRUE;
    }

    /* 音素環境非依存の場合は単純に最終単語分の HMM を作成 */
    /* for monophone: simple make HMM for the last word */
    whmm = new_make_word_hmm(hmminfo, winfo->wseq[word], winfo->wlen[word], (enable_iwsp && hmminfo->multipath) ? dwrk->has_sp : NULL);
    if (whmm == NULL) {
      j_internal_error("Error: failed to make word hmm for word #%d \"%s [%s]\"\n", word, winfo->wname[word], winfo->woutput[word]);
    }

    /* 計算前の g[] 初期値は now->g[] を使用 */
    /* the initial forward score g[] is set by now->g[] */
    for (t=0;t<peseqlen;t++) {
      dwrk->g[t]=now->g[t];
    }
    
  }

#ifdef TCD
  jlog("DEBUG: whmm len	  = %d\n",whmm->len);
  jlog("DEBUG: crossword_point = %d\n", crossword_point);
  jlog("DEBUG: g[] store point = %d\n", store_point);
#endif

  wordhmmnum = whmm->len;
  if (wordhmmnum >= winfo->maxwn + 10) {
    j_internal_error("scan_word: word too long (>%d)\n", winfo->maxwn + 10);
  }

#ifndef GRAPHOUT_PRECISE_BOUNDARY
  if (r->graphout) {
    if (ccd_flag) {
      now->tail_g_score = now->g[now->bestt];
    }
  }
#endif

  /* ----------------------- do scan ----------------------- */
  
  /* scan開始点を検索 -> starttへ*/
  /* search for the start frame -> set to startt */
  for(t = peseqlen-1; t >=0 ; t--) {
    if (
#ifdef SCAN_BEAM
	dwrk->g[t] > framemaxscore[t] - scan_beam_thres &&
#endif
	dwrk->g[t] > LOG_ZERO) {
      break;
    }
  }
  if (t < 0) {			/* no node has score > LOG_ZERO */
    for(t=0;t<peseqlen;t++) {
      if (ccd_flag) now->g_prev[t] = LOG_ZERO;
      now->g[t] = LOG_ZERO;
    }
#ifdef GRAPHOUT_PRECISE_BOUNDARY
    if (r->graphout) {
      for(t=0;t<peseqlen;t++) {
	now->wordend_frame[t] = -1;
	now->wordend_gscore[t] = LOG_ZERO;
      }
    }
#endif
    goto end_of_scan;
  }
  startt = t;
  
  /* clear [startt+1..peseqlen-1] */
  for(t=peseqlen-1;t>startt;t--) {
    if (ccd_flag) now->g_prev[t] = LOG_ZERO;
    now->g[t] = LOG_ZERO;
#ifdef GRAPHOUT_PRECISE_BOUNDARY
    if (r->graphout) {
      now->wordend_frame[t] = -1;
      now->wordend_gscore[t] = LOG_ZERO;
    }
#endif
  }

  /* バッファポインタ初期化 */
  tn = 0; tl = 1;

#ifdef GRAPHOUT_PRECISE_BOUNDARY
  if (r->graphout) {
    for(i=0;i<wordhmmnum;i++) {
      dwrk->wend_token_frame[tn][i] = -1;
      dwrk->wend_token_gscore[tn][i] = LOG_ZERO;
    }
  }
#endif
  
  if (! hmminfo->multipath) {
    /* Below initialization is not needed on multipath version, since
       the actual viterbi will begin at frame 0 in multipath mode in main loop */
    
    /* 時間 [startt] 上の値を初期化 */
    /* initialize scores on frame [startt] */
    for(i=0;i<wordhmmnum-1;i++) dwrk->wordtrellis[tn][i] = LOG_ZERO;
    dwrk->wordtrellis[tn][wordhmmnum-1] = dwrk->g[startt] + outprob(&(r->am->hmmwrk), startt, &(whmm->state[wordhmmnum-1]), param);
    if (ccd_flag) {
      now->g_prev[startt] = dwrk->wordtrellis[tn][store_point];
    }
    now->g[startt] = dwrk->wordtrellis[tn][0];
    
#ifdef GRAPHOUT_PRECISE_BOUNDARY
    if (r->graphout) {
      if (ccd_flag) {
	if (back_rescan) {
	  if (wordhmmnum-1 == crossword_point) {
	    dwrk->wend_token_frame[tn][wordhmmnum-1] = startt;
	    dwrk->wend_token_gscore[tn][wordhmmnum-1] = dwrk->g[startt];
	  } else {
	    dwrk->wend_token_frame[tn][wordhmmnum-1] = -1;
	    dwrk->wend_token_gscore[tn][wordhmmnum-1] = LOG_ZERO;
	  }
	} else {
	  dwrk->wend_token_frame[tn][wordhmmnum-1] = startt;
	  dwrk->wend_token_gscore[tn][wordhmmnum-1] = dwrk->g[startt];
	}
      } else {
	dwrk->wend_token_frame[tn][wordhmmnum-1] = startt;
	dwrk->wend_token_gscore[tn][wordhmmnum-1] = dwrk->g[startt];
      }
      now->wordend_frame[startt] = dwrk->wend_token_frame[tn][0];
      now->wordend_gscore[startt] = dwrk->wend_token_gscore[tn][0];
    }
#endif
  } /* end of hmminfo->multipath */
  
  endt = startt;

  /* メインループ: startt から始まり 0 に向かって Viterbi 計算 */
  /* main loop: start from [startt], and compute Viterbi toward [0] */
  for(t = hmminfo->multipath ? startt : startt - 1; t >= 0; t--) {
    
    /* wordtrellisのワークエリアをスワップ */
    i = tn; tn = tl; tl = i;
    
    node_exist_p = FALSE;	/* TRUE if there is at least 1 survived node in this frame */

    if (hmminfo->multipath) {

      /* 端のノード [t][wordhmmnum-1]は g[] を参照する */
      /* the edge node [t][wordhmmnum-1] is equal to g[] */

      /* ノード [t][wordhmmnum-2..0] についてトレリスを計算 */
      /* expand trellis for node [t][wordhmmnum-2..0] */
      tmpmax_store = LOG_ZERO;

    } else {
    
      /* 端のノード [t][wordhmmnum-1]は,内部遷移 か g[]の高い方になる */
      /* the edge node [t][wordhmmnum-1] is either internal transitin or g[] */
      tmptmp = LOG_ZERO;
      for (ac=whmm->state[wordhmmnum-1].ac;ac;ac=ac->next) {
	score1 = dwrk->wordtrellis[tl][ac->arc] + ac->a;
	if (tmptmp < score1) {
	  j = ac->arc;
	  tmptmp = score1;
	}
      }
      if (dwrk->g[t] > tmptmp) {
	tmpmax = dwrk->g[t];
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	if (r->graphout) {
	  if (!back_rescan || wordhmmnum-1 == crossword_point) {
	    dwrk->wend_token_frame[tn][wordhmmnum-1] = t;
	    dwrk->wend_token_gscore[tn][wordhmmnum-1] = dwrk->g[t];
	  } else {
	    dwrk->wend_token_frame[tn][wordhmmnum-1] = dwrk->wend_token_frame[tl][j];
	    dwrk->wend_token_gscore[tn][wordhmmnum-1] = dwrk->wend_token_gscore[tl][j];
	  }
	}
#endif
      } else {
	tmpmax = tmptmp;
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	if (r->graphout) {
	  dwrk->wend_token_frame[tn][wordhmmnum-1] = dwrk->wend_token_frame[tl][j];
	  dwrk->wend_token_gscore[tn][wordhmmnum-1] = dwrk->wend_token_gscore[tl][j];
	}
#endif
      }

      /* 端のノードのスコアエンベロープチェック: 一定幅外なら落とす */
      /* check if the edge node is within score envelope */
      if (
#ifdef SCAN_BEAM
	  tmpmax <= framemaxscore[t] - scan_beam_thres ||
#endif
	  tmpmax <= LOG_ZERO
	  ) {
	dwrk->wordtrellis[tn][wordhmmnum-1] = LOG_ZERO;
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	if (r->graphout) {
	  dwrk->wend_token_frame[tn][wordhmmnum-1] = -1;
	  dwrk->wend_token_gscore[tn][wordhmmnum-1] = LOG_ZERO;
	}
#endif
      } else {
	node_exist_p = TRUE;
	dwrk->wordtrellis[tn][wordhmmnum-1] = tmpmax + outprob(&(r->am->hmmwrk), t, &(whmm->state[wordhmmnum-1]), param);
      }

    } /* end of ~multipath */

    /* ノード [t][wordhmmnum-2..0] についてトレリスを計算 */
    /* expand trellis for node [t][wordhmmnum-2..0] */
    for(i=wordhmmnum-2;i>=0;i--) {

      if (ccd_flag) {

	/* 最尤パスと最尤スコア tmpmax を見つける */
	/* tmpmax2 は次回用 g_prev[] のための最大値(自己遷移を除いた最大値) */
	/* find most likely path and the max score 'tmpmax' */
	/* 'tmpmax2' is max score excluding self transition, for next g_prev[] */
	if (! hmminfo->multipath) {
	  if (i == store_point) {
	    tmpmax2 = LOG_ZERO;
	  }
	}
	tmpmax = LOG_ZERO;
	for (ac=whmm->state[i].ac;ac;ac=ac->next) {
	  if (hmminfo->multipath) {
	    if (ac->arc == wordhmmnum-1) score1 = dwrk->g[t];
	    else if (t + 1 > startt) score1 = LOG_ZERO;
	    else score1 = dwrk->wordtrellis[tl][ac->arc];
	    score1 += ac->a;
	  } else {
	    score1 = dwrk->wordtrellis[tl][ac->arc] + ac->a;
	  }
	  if (i <= crossword_point && ac->arc > crossword_point) {
	    /* これは単語を越える遷移 (backscan 実行時) */
	    /* this is a transition across word (when backscan is enabled) */
	    score1 += now->lscore; /* add LM score */
	  }

	  if (hmminfo->multipath) {
	    if (i <= store_point && ac->arc > store_point) {
	      if (tmpmax_store < score1) tmpmax_store = score1;
	    }
	  } else {
	    if (i == store_point && i != ac->arc) {
	      if (tmpmax2 < score1) tmpmax2 = score1;
	    }
	  }

	  if (tmpmax < score1) {
	    tmpmax = score1;
	    j = ac->arc;
	  }
	}

	/* スコアエンベロープチェック: 一定幅外なら落とす */
	/* check if score of this node is within the score envelope */
	if (
#ifdef SCAN_BEAM
	    tmpmax <= framemaxscore[t] - scan_beam_thres ||
#endif
	    tmpmax <= LOG_ZERO
	    ) {  /* invalid node */
	  dwrk->wordtrellis[tn][i] = LOG_ZERO;
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	  if (r->graphout) {
	    dwrk->wend_token_frame[tn][i] = -1;
	    dwrk->wend_token_gscore[tn][i] = LOG_ZERO;
	  }
#endif
	  if (! hmminfo->multipath) {
	    if (i == store_point) now->g_prev[t] = LOG_ZERO;
	  }
	} else { /* survived node */
	  if (! hmminfo->multipath) {
	    if (i == store_point) now->g_prev[t] = tmpmax2;
	  }
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	  if (r->graphout) {

	    if (hmminfo->multipath) {
	      if ((back_rescan && i <= crossword_point && j > crossword_point)
		  || j == wordhmmnum-1) {
		dwrk->wend_token_frame[tn][i] = t;
		dwrk->wend_token_gscore[tn][i] = tmpmax;
	      } else {
		dwrk->wend_token_frame[tn][i] = dwrk->wend_token_frame[tl][j];
		dwrk->wend_token_gscore[tn][i] = dwrk->wend_token_gscore[tl][j];
	      }
	    } else {
	      if (i <= crossword_point && j > crossword_point) {
		dwrk->wend_token_frame[tn][i] = t;
		dwrk->wend_token_gscore[tn][i] = tmpmax;
	      } else {
		dwrk->wend_token_frame[tn][i] = dwrk->wend_token_frame[tl][j];
		dwrk->wend_token_gscore[tn][i] = dwrk->wend_token_gscore[tl][j];
	      }
	    }
	  }
#endif
	  node_exist_p = TRUE;	/* at least one node survive in this frame */

	  dwrk->wordtrellis[tn][i] = tmpmax;
	  if (! hmminfo->multipath || i > 0) {
	    /* compute output probability */
	    dwrk->wordtrellis[tn][i] += outprob(&(r->am->hmmwrk), t, &(whmm->state[i]), param);
	  }
	}
	
      } else {			/* not triphone */

	/* backscan 無し: store_point, crossword_point は無関係 */
	/* no backscan: store_point, crossword_point ignored */
	tmpmax = LOG_ZERO;
	if (hmminfo->multipath) {
	  for (ac=whmm->state[i].ac;ac;ac=ac->next) {
	    if (ac->arc == wordhmmnum-1) score1 = dwrk->g[t];
	    else if (t + 1 > startt) score1 = LOG_ZERO;
	    else score1 = dwrk->wordtrellis[tl][ac->arc];
	    score1 += ac->a;
	    if (tmpmax < score1) {
	      tmpmax = score1;
	      j = ac->arc;
	    }
	  }
	} else {
	  for (ac=whmm->state[i].ac;ac;ac=ac->next) {
	    score1 = dwrk->wordtrellis[tl][ac->arc] + ac->a;
	    if (tmpmax < score1) {
	      tmpmax = score1;
	      j = ac->arc;
	    }
	  }
	}

	/* スコアエンベロープチェック: 一定幅外なら落とす */
	/* check if score of this node is within the score envelope */
	if (
#ifdef SCAN_BEAM
	    tmpmax <= framemaxscore[t] - scan_beam_thres ||
#endif
	    tmpmax <= LOG_ZERO
	    ) {
	  /* invalid node */
	  dwrk->wordtrellis[tn][i] = LOG_ZERO;
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	  if (r->graphout) {
	    dwrk->wend_token_frame[tn][i] = -1;
	    dwrk->wend_token_gscore[tn][i] = LOG_ZERO;
	  }
#endif
	} else {
	  /* survived node */
	  node_exist_p = TRUE;
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	  if (r->graphout) {
	    if (hmminfo->multipath) {
	      if (j == wordhmmnum-1) {
		dwrk->wend_token_frame[tn][i] = t;
		dwrk->wend_token_gscore[tn][i] = tmpmax;
	      } else {
		dwrk->wend_token_frame[tn][i] = dwrk->wend_token_frame[tl][j];
		dwrk->wend_token_gscore[tn][i] = dwrk->wend_token_gscore[tl][j];
	      }
	    } else {
	      dwrk->wend_token_frame[tn][i] = dwrk->wend_token_frame[tl][j];
	      dwrk->wend_token_gscore[tn][i] = dwrk->wend_token_gscore[tl][j];
	    }
	  }
#endif
	  /* score of node [t][i] has been determined here */
	  dwrk->wordtrellis[tn][i] = tmpmax;
	  if (! hmminfo->multipath || i > 0) {
	    dwrk->wordtrellis[tn][i] += outprob(&(r->am->hmmwrk), t, &(whmm->state[i]), param);
	  }
	}
	
      }
    } /* end of node loop */

    /* 時間 t のViterbi計算終了. 前向きスコアはscanした単語の始端 */
    /* Viterbi end for frame [t].  the forward score is the score of word
       beginning scanned */
    now->g[t] = dwrk->wordtrellis[tn][0];
#ifdef GRAPHOUT_PRECISE_BOUNDARY
    if (r->graphout) {
      now->wordend_frame[t] = dwrk->wend_token_frame[tn][0];
      now->wordend_gscore[t] = dwrk->wend_token_gscore[tn][0];
    }
#endif

    if (hmminfo->multipath) {
      /* triphone 時, 次段のために store_point のデータをg_prevに保存 */
      /* store the scores crossing the store_point to g_prev, for next scan */
      if (ccd_flag) {
	/* the max arc crossing the store_point always selected as tmpmax_score */ 
	tmpmax_store -= store_point_maxarc;
	if (tmpmax_store < LOG_ZERO) tmpmax_store = LOG_ZERO;
	now->g_prev[t] = tmpmax_store;
      }
    }

    /* store the number of last computed frame */
    if (node_exist_p) endt = t;
    
    /* scanした単語の第1パスでの始端時刻より先まで t が進んでおり,かつ
       この t においてスコアエンベロープによって生き残ったノードが一つも
       無かったならば,このフレームで計算を打ち切りそれ以上先([0..t-1])は
       計算しない */
    /* if frame 't' already reached the beginning frame of scanned word
       in 1st pass and no node was survived in this frame (all nodes pruned
       by score envelope), terminate computation at this frame and
       do not computer further frame ([0..t-1]). */
    if (t < now->estimated_next_t && (!node_exist_p)) {
      /* clear the rest scores */
      for (i=t-1;i>=0;i--) {
	now->g[i] = LOG_ZERO;
#ifdef GRAPHOUT_PRECISE_BOUNDARY
	if (r->graphout) {
	  now->wordend_frame[i] = -1;
	  now->wordend_gscore[i] = LOG_ZERO;
	}
#endif
	if (ccd_flag) now->g_prev[i] = LOG_ZERO;
      }
      /* terminate loop */
      break;
    }
    
  } /* end of time loop */
  
  if (debug2_flag) jlog("DEBUG: scanned: [%3d-%3d]\n", endt, startt);

 end_of_scan:

  if (hmminfo->multipath) {
    /* 前向きスコアの最終値を計算 (状態 0 から時間 0 への遷移) */
    /* compute the total forward score (transition from state 0 to frame 0 */
    if (endt == 0) {
      tmpmax = LOG_ZERO;
      for(ac=whmm->state[0].ac;ac;ac=ac->next) {
	score1 = dwrk->wordtrellis[tn][ac->arc] + ac->a;
	if (tmpmax < score1) tmpmax = score1;
      }
      now->final_g = score1;
    } else {
      now->final_g = LOG_ZERO;
    }
  }
  
  /* 次回 backscan のための情報格納 */
  /* store data for next backscan */
  if (ccd_flag) {
    if (store_point == (hmminfo->multipath ? wordhmmnum - 2 : wordhmmnum - 1)) {
      /* last_ph無し,かつ単語の音素長=1の場合、次回の scan_word() で
	 単語全体がもう一度再計算される. この場合,
	 g_prev は,このscan_wordを開始する前のスコアを入れておく必要がある */
      /* if there was no 'last_ph' and the scanned word consists of only
	 1 phone, the whole word should be re-computed in the future scan_word().
	 So the next 'g_prev[]' should be the initial forward scores
	 before we begin Viterbi (= g[t]). */
      for (t = startt; t>=0; t--) {
	now->g_prev[t] = dwrk->g[t];
      }
    }
#ifndef GRAPHOUT_PRECISE_BOUNDARY
    if (r->graphout) {
      if (now->tail_g_score != LOG_ZERO) {
	if (now->prevgraph != NULL) {
	  (now->prevgraph)->leftscore = now->tail_g_score;
	}
      }
    }
#endif
    /* 次回のために now->last_ph を更新 */
    /* update 'now->last_ph' for future scan_word() */
    if (back_rescan) {
      now->last_ph = dwrk->phmmseq[0];
    } else {
      now->last_ph = winfo->wseq[word][0];
    }
    if (enable_iwsp && hmminfo->multipath) {
      now->last_ph_sp_attached = dwrk->has_sp[0];
    }
  }

#ifdef GRAPHOUT_PRECISE_BOUNDARY
  if (! hmminfo->multipath) {
    if (r->graphout) {
      /* 次回の next_word 用に境界情報を調整 */
      /* proceed word boundary for one step for next_word */
      now->wordend_frame[peseqlen-1] = now->wordend_frame[0];
      now->wordend_gscore[peseqlen-1] = now->wordend_gscore[0];
      for (t=0;t<peseqlen-1;t++) {
	now->wordend_frame[t] = now->wordend_frame[t+1];
	now->wordend_gscore[t] = now->wordend_gscore[t+1];
      }
    }
  }
#endif

  /* free work area */
  free_hmm(whmm);
#ifdef TCD
  if (hmminfo->multipath) {
    if (ccd_flag) {
      jlog("DEBUG: last_ph = %s", (now->last_ph)->name);
      if (now->last_ph_sp_attached) jlog(" (sp attached)");
      jlog("\n");
    }
  } else {
    jlog("DEBUG: last_ph = %s\n", (now->last_ph)->name);
  }
#endif
}
/** 
 * <EN>
 * @brief  Launch a recognition process instance.
 *
 * This function will create an recognition process instance
 * using the given SEARCH configuration, and launch recognizer for
 * the search.  Then the created instance will be installed to the
 * engine instance.  The sconf should be registered to the global
 * jconf before calling this function.
 *
 * </EN>
 *
 * <JA>
 * @brief 認識処理インスタンスを立ち上げる.
 *
 * この関数は,与えられた SEARCH 設定に従って 認識処理インスタンスを生成し,
 * 対応する音声認識器を構築します.その後,その生成された認識処理インスタンスは
 * 新たにエンジンインスタンスに登録されます.SEARCH設定はこの関数を
 * 呼ぶ前にあらかじめ全体設定jconfに登録されている必要があります.
 * 
 * </JA>
 * 
 * @param recog [i/o] engine instance
 * @param sconf [in] SEARCH configuration to launch
 * 
 * @return TRUE on success, or FALSE on error.
 *
 * @callgraph
 * @callergraph
 * @ingroup instance
 * 
 */
boolean
j_launch_recognition_instance(Recog *recog, JCONF_SEARCH *sconf)
{
  RecogProcess *p;
  PROCESS_AM *am;
  PROCESS_LM *lm;

  jlog("STAT: composing recognizer instance SR%02d %s (AM%02d %s, LM%02d %s)\n", sconf->id, sconf->name, sconf->amconf->id, sconf->amconf->name, sconf->lmconf->id, sconf->lmconf->name);

  /* allocate recognition instance */
  p = j_recogprocess_new(recog, sconf);

  /* assign corresponding AM instance and LM instance to use */
  for(lm=recog->lmlist;lm;lm=lm->next) {
    if (sconf->lmconf == lm->config) {
      for(am=recog->amlist;am;am=am->next) {
	if (sconf->amconf == am->config) {
	  p->am = am;
	  p->lm = lm;
	}
      }
    }
  }

  if (p->config->sw.triphone_check_flag && p->am->hmminfo->is_triphone) {
    /* go into interactive triphone HMM check mode */
    hmm_check(p);
  }
  
  /******************************************/
  /******** set work area and flags *********/
  /******************************************/

  /* copy values of sub instances for handly access during recognition */
  /* set lm type */
  p->lmtype = p->lm->lmtype;
  p->lmvar  = p->lm->lmvar;
  p->graphout = p->config->graph.enabled;
  
  /* set flag for context dependent handling */
  if (p->config->force_ccd_handling) {
    p->ccd_flag = p->config->ccd_handling;
  } else {
    if (p->am->hmminfo->is_triphone) {
      p->ccd_flag = TRUE;
    } else {
      p->ccd_flag = FALSE;
    }
  }

  /* iwsp prepare */
  if (p->lm->config->enable_iwsp) {
    if (p->am->hmminfo->multipath) {
      /* find short-pause model */
      if (p->am->hmminfo->sp == NULL) {
	jlog("ERROR: iwsp enabled but no short pause model \"%s\" in hmmdefs\n", p->am->config->spmodel_name);
	return FALSE;
      }
      p->am->hmminfo->iwsp_penalty = p->am->config->iwsp_penalty;
    } else {
      jlog("ERROR: \"-iwsp\" needs multi-path mode\n");
      jlog("ERROR: you should use multi-path AM, or specify \"-multipath\" with \"-iwsp\"\n");
      return FALSE;
    }
  }

  /* for short-pause segmentation  */
  if (p->config->successive.enabled) {
    if (p->config->successive.pausemodelname) {
      /* pause model name string specified, divide it and store to p */
      char *s;
      int n;
      p->pass1.pausemodelnames = (char*)mymalloc(strlen(p->config->successive.pausemodelname)+1);
      strcpy(p->pass1.pausemodelnames, p->config->successive.pausemodelname);
      n = 0;
      for (s = strtok(p->pass1.pausemodelnames, " ,"); s; s = strtok(NULL, " ,")) {
	n++;
      }
      p->pass1.pausemodelnum = n;
      p->pass1.pausemodel = (char **)mymalloc(sizeof(char *) * n);
      strcpy(p->pass1.pausemodelnames, p->config->successive.pausemodelname);
      n = 0;
      for (s = strtok(p->pass1.pausemodelnames, " ,"); s; s = strtok(NULL, " ,")) {
	p->pass1.pausemodel[n++] = s;
      }
    } else {
      p->pass1.pausemodel = NULL;
    }
    /* check if pause word exists on dictionary */
    {
      WORD_ID w;
      boolean ok_p;
      ok_p = FALSE;
      for(w=0;w<p->lm->winfo->num;w++) {
	if (is_sil(w, p)) {
	  ok_p = TRUE;
	  break;
	}
      }
      if (!ok_p) {
#ifdef SPSEGMENT_NAIST
	jlog("Error: no pause word in dictionary needed for decoder-based VAD\n");
#else
	jlog("Error: no pause word in dictionary needed for short-pause segmentation\n");
#endif
	jlog("Error: you should have at least one pause word in dictionary\n");
	jlog("Error: you can specify pause model names by \"-pausemodels\"\n");
	return FALSE;
      }
    }
  }

  /**********************************************/
  /******** set model-specific defaults *********/
  /**********************************************/
  if (p->lmtype == LM_PROB) {
    /* set default lm parameter if not specified */
    if (!p->config->lmp.lmp_specified) {
      if (p->am->hmminfo->is_triphone) {
	p->config->lmp.lm_weight = DEFAULT_LM_WEIGHT_TRI_PASS1;
	p->config->lmp.lm_penalty = DEFAULT_LM_PENALTY_TRI_PASS1;
      } else {
	p->config->lmp.lm_weight = DEFAULT_LM_WEIGHT_MONO_PASS1;
	p->config->lmp.lm_penalty = DEFAULT_LM_PENALTY_MONO_PASS1;
      }
    }
    if (!p->config->lmp.lmp2_specified) {
      if (p->am->hmminfo->is_triphone) {
	p->config->lmp.lm_weight2 = DEFAULT_LM_WEIGHT_TRI_PASS2;
	p->config->lmp.lm_penalty2 = DEFAULT_LM_PENALTY_TRI_PASS2;
      } else {
	p->config->lmp.lm_weight2 = DEFAULT_LM_WEIGHT_MONO_PASS2;
	p->config->lmp.lm_penalty2 = DEFAULT_LM_PENALTY_MONO_PASS2;
      }
    }
    if (p->config->lmp.lmp_specified != p->config->lmp.lmp2_specified) {
      jlog("WARNING: m_fusion: only -lmp or -lmp2 specified, LM weights may be unbalanced\n");
    }
  }

  /****************************/
  /******* build wchmm ********/
  /****************************/
  if (p->lmtype == LM_DFA) {
    /* execute generation of global grammar and build of wchmm */
    multigram_build(p); /* some modification occured if return TRUE */
  }

  if (p->lmtype == LM_PROB) {
    /* build wchmm with N-gram */
    p->wchmm = wchmm_new();
    p->wchmm->lmtype = p->lmtype;
    p->wchmm->lmvar  = p->lmvar;
    p->wchmm->ccd_flag = p->ccd_flag;
    p->wchmm->category_tree = FALSE;
    p->wchmm->hmmwrk = &(p->am->hmmwrk);
    /* assign models */
    p->wchmm->ngram = p->lm->ngram;
    if (p->lmvar == LM_NGRAM_USER) {
      /* register LM functions for 1st pass here */
      p->wchmm->uni_prob_user = p->lm->lmfunc.uniprob;
      p->wchmm->bi_prob_user = p->lm->lmfunc.biprob;
    }
    p->wchmm->winfo = p->lm->winfo;
    p->wchmm->hmminfo = p->am->hmminfo;
    if (p->wchmm->category_tree) {
      if (p->config->pass1.old_tree_function_flag) {
	if (build_wchmm(p->wchmm, p->lm->config) == FALSE) {
	  jlog("ERROR: m_fusion: error in bulding wchmm\n");
	  return FALSE;
	}
      } else {
	if (build_wchmm2(p->wchmm, p->lm->config) == FALSE) {
	  jlog("ERROR: m_fusion: error in bulding wchmm\n");
	  return FALSE;
	}
      }
    } else {
      if (build_wchmm2(p->wchmm, p->lm->config) == FALSE) {
	jlog("ERROR: m_fusion: error in bulding wchmm\n");
	return FALSE;
      }
    }

    /* 起動時 -check でチェックモードへ */
    if (p->config->sw.wchmm_check_flag) {
      wchmm_check_interactive(p->wchmm);
    }

    /* set beam width */
    /* guess beam width from models, when not specified */
    p->trellis_beam_width = set_beam_width(p->wchmm, p->config->pass1.specified_trellis_beam_width);

    /* initialize cache for factoring */
    max_successor_cache_init(p->wchmm);
  }

  /* backtrellis initialization */
  p->backtrellis = (BACKTRELLIS *)mymalloc(sizeof(BACKTRELLIS));
  bt_init(p->backtrellis);

  /* prepare work area for 2nd pass */
  wchmm_fbs_prepare(p);

  jlog("STAT: SR%02d %s composed\n", sconf->id, sconf->name);

  if (sconf->sw.start_inactive) {
    /* start inactive */
    p->active = -1;
  } else {
    /* book activation for the recognition */
    p->active = 1;
  }
  if (p->lmtype == LM_DFA) {
    if (p->lm->winfo == NULL ||
	(p->lmvar == LM_DFA_GRAMMAR && p->lm->dfa == NULL)) {
      /* make this instance inactive */
      p->active = -1;
    }
  }

  return TRUE;
}
Beispiel #11
0
void inet_print_iphdr(void *data)
{
	struct ip *iph;
	iph = data + sizeof(struct ether_header);
	jlog(L_DEBUG, "iphdr len: %i", iph->ip_len);
}
/** 
 * <EN>
 * 
 * @brief  Create MFCC calculation instance for AM processing instances and GMM
 *
 * If more than one AM processing instance (or GMM) has the same configuration,
 * the same MFCC calculation instance will be shared among them.
 * 
 * </EN>
 * <JA>
 *
 * @brief  全てのAM処理インスタンスおよびGMM用に,MFCC計算インスタンスを生成する. 
 *
 * 2つ以上のAM処理インスタンス(およびGMM)が同一の特徴量計算条件を持
 * つ場合,それらのインスタンスはひとつの MFCC 計算インスタンスを共有する. 
 * 
 * </JA>
 * 
 * @param recog [i/o] engine instance
 *
 * @callgraph
 * @callergraph
 *
 */
void
create_mfcc_calc_instances(Recog *recog)
{
  PROCESS_AM *am;
  MFCCCalc *mfcc;
  int count;
  
  jlog("STAT: *** create MFCC calculation modules from AM\n");
  count = 0;
  for(am=recog->amlist;am;am=am->next) {
    for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
      if (mfcc_config_is_same(am->config, mfcc)) {
	/* the same */
	jlog("STAT: AM%02d %s: share MFCC%02d\n", am->config->id, am->config->name, mfcc->id);
	am->mfcc = mfcc;
	break;
      }
    }
    if (!mfcc) {		/* the same not found */
      /* initialize MFCC calculation work area */
      count++;
      /* create new mfcc instance */
      mfcc = j_mfcccalc_new(am->config);
      mfcc->id = count;
      /* assign to the am */
      am->mfcc = mfcc;
      /* add to the list of all MFCCCalc */
      mfcc->next = recog->mfcclist;
      recog->mfcclist = mfcc;
      jlog("STAT: AM%2d %s: create a new module MFCC%02d\n", am->config->id, am->config->name, mfcc->id);
    }
  }

  /* for GMM */
  if (recog->gmm) {
    /* if GMM calculation config found, make MFCC instance for that. */
    for(mfcc=recog->mfcclist;mfcc;mfcc=mfcc->next) {
      if (mfcc_config_is_same(recog->jconf->gmm, mfcc)) {
	/* the same */
	jlog("STAT: GMM: share MFCC%02d\n", mfcc->id);
	recog->gmmmfcc = mfcc;
	break;
	}
    }
    if (!mfcc) {		/* the same not found */
      /* initialize MFCC calculation work area */
      count++;
      /* create new mfcc instance */
      mfcc = j_mfcccalc_new(recog->jconf->gmm);
      mfcc->id = count;
      /* assign to gmm */
      recog->gmmmfcc = mfcc;
      /* add to the list of all MFCCCalc */
      mfcc->next = recog->mfcclist;
      recog->mfcclist = mfcc;
      jlog("STAT: GMM: create a new module MFCC%02d\n", mfcc->id);
    }
  }
  
  jlog("STAT: %d MFCC modules created\n", count);
}
/** 
 * <JA>
 * @brief  全てのモデルを読み込み,認識の準備を行なう. 
 *
 * この関数では,jconf 内にある(複数の) AM 設定パラメータ構造体やLM 
 * 設定パラメータ構造体のそれぞれに対して,AM/LM処理インスタンスを生成
 * する. そしてそれぞれのインスタンスについてその中にモデルを読み込み,
 * 認識用にセットアップする. GMMもここで読み込まれる. 
 * 
 * </JA>
 * <EN>
 * @brief  Read in all models for recognition.
 *
 * This function create AM/LM processing instance for each AM/LM
 * configurations in jconf.  Then the model for each instance will be loaded
 * into memory and set up for recognition.  GMM will also be read here.
 * 
 * </EN>
 *
 * @param recog [i/o] engine instance
 * @param jconf [in] global configuration variables
 *
 * @return TRUE on success, FALSE on failure.
 *
 * @callgraph
 * @callergraph
 * @ingroup instance
 */
boolean
j_load_all(Recog *recog, Jconf *jconf)
{
  JCONF_AM *amconf;
  JCONF_LM *lmconf;

  /* set global jconf */
  recog->jconf = jconf;

  /* load acoustic models */
  for(amconf=jconf->am_root;amconf;amconf=amconf->next) {
    if (j_load_am(recog, amconf) == FALSE) return FALSE;
  }

  /* load language models */
  for(lmconf=jconf->lm_root;lmconf;lmconf=lmconf->next) {
    if (j_load_lm(recog, lmconf) == FALSE) return FALSE;
  }

  /* GMM */
  if (jconf->reject.gmm_filename != NULL) {
    jlog("STAT: loading GMM\n");
    if ((recog->gmm = initialize_GMM(jconf)) == NULL) {
      jlog("ERROR: m_fusion: failed to initialize GMM\n");
      return FALSE;
    }
  }

  /* check sampling rate requirement on AMs and set it to global jconf */
  {
    boolean ok_p;

    /* set input sampling rate from an AM */
    jconf->input.sfreq = jconf->am_root->analysis.para.smp_freq;
    jconf->input.period = jconf->am_root->analysis.para.smp_period;
    jconf->input.frameshift = jconf->am_root->analysis.para.frameshift;
    jconf->input.framesize = jconf->am_root->analysis.para.framesize;
    /* check if the value is equal at all AMs */
    ok_p = TRUE;
    for(amconf = jconf->am_root; amconf; amconf = amconf->next) {
      if (jconf->input.sfreq != amconf->analysis.para.smp_freq) ok_p = FALSE;
    }
    if (!ok_p) {
      jlog("ERROR: required sampling rate differs in AMs!\n");
      for(amconf = jconf->am_root; amconf; amconf = amconf->next) {
	jlog("ERROR: AM%02d %s: %dHz\n", amconf->analysis.para.smp_freq);
      }
      return FALSE;
    }
    /* also check equality for GMM */
    if (recog->gmm) {
      if (jconf->input.sfreq != jconf->gmm->analysis.para.smp_freq) {
	jlog("ERROR: required sampling rate differs between AM and GMM!\n");
	jlog("ERROR: AM : %dHz\n", jconf->input.sfreq);
	jlog("ERROR: GMM: %dHz\n", jconf->gmm->analysis.para.smp_freq);
	return FALSE;
      }
    }
    for(amconf = jconf->am_root; amconf; amconf = amconf->next) {
      if (jconf->input.frameshift != amconf->analysis.para.frameshift) ok_p = FALSE;
    }
    if (!ok_p) {
      jlog("ERROR: requested frame shift differs in AMs!\n");
      for(amconf = jconf->am_root; amconf; amconf = amconf->next) {
	jlog("ERROR: AM%02d %s: %d samples\n", amconf->analysis.para.frameshift);
      }
      return FALSE;
    }
    /* also check equality for GMM */
    if (recog->gmm) {
      if (jconf->input.frameshift != jconf->gmm->analysis.para.frameshift) {
	jlog("ERROR: required frameshift differs between AM and GMM!\n");
	jlog("ERROR: AM : %d samples\n", jconf->input.frameshift);
	jlog("ERROR: GMM: %d samples\n", jconf->gmm->analysis.para.frameshift);
	return FALSE;
      }
    }
    for(amconf = jconf->am_root; amconf; amconf = amconf->next) {
      if (jconf->input.framesize != amconf->analysis.para.framesize) ok_p = FALSE;
    }
    if (!ok_p) {
      jlog("ERROR: requested frame size (window length) differs in AMs!\n");
      for(amconf = jconf->am_root; amconf; amconf = amconf->next) {
	jlog("ERROR: AM%02d %s: %d samples\n", amconf->analysis.para.framesize);
      }
      return FALSE;
    }
    /* also check equality for GMM */
    if (recog->gmm) {
      if (jconf->input.framesize != jconf->gmm->analysis.para.framesize) {
	jlog("ERROR: requested frame size differs between AM and GMM!\n");
	jlog("ERROR: AM : %d samples\n", jconf->input.framesize);
	jlog("ERROR: GMM: %d samples\n", jconf->gmm->analysis.para.framesize);
	return FALSE;
      }
    }
  }

  return TRUE;
}
/** 
 * <JA>
 * @brief  音響HMMをファイルから読み込み,認識用にセットアップする. 
 *
 * ファイルからのHMM定義の読み込み,HMMList ファイルの読み込み,
 * パラメータ型のチェック,マルチパス扱いの on/off, ポーズモデルの設定など
 * が行われ,認識のための準備が行われる. 
 *
 * この音響モデルの入力となる音響パラメータの種類やパラメータもここで
 * 最終決定される. 決定には,音響HMMのヘッダ,(バイナリHMMの場合,存
 * 在すれば)バイナリHMMに埋め込まれた特徴量情報,jconf の設定(ばらば
 * らに,あるいは -htkconf 使用時)などの情報が用いられる. 
 * </JA>
 * <EN>
 * @brief  Read in an acoustic HMM from file and setup for recognition.
 *
 * This functions reads HMM definitions from file, reads also a
 * HMMList file, makes logical-to-physical model mapping, determine
 * required parameter type, determine whether multi-path handling is needed,
 * and find pause model in the definitions.
 *
 * The feature vector extraction parameters are also finally
 * determined in this function.  Informations used for the
 * determination is (1) the header values in hmmdefs, (2) embedded
 * parameters in binary HMM if you are reading a binary HMM made with
 * recent mkbinhmm, (3) user-specified parameters in jconf
 * configurations (either by separatedly specified or by -htkconf
 * options).
 *
 * </EN>
 * 
 * @param amconf [in] AM configuration variables
 * @param jconf [i/o] global configuration variables
 * 
 * @return the newly created HMM information structure, or NULL on failure.
 * 
 */
static HTK_HMM_INFO *
initialize_HMM(JCONF_AM *amconf, Jconf *jconf)
{
  HTK_HMM_INFO *hmminfo;

  /* at here, global variable "para" holds values specified by user or
     by user-specified HTK config file */
  if (amconf->analysis.para_hmm.loaded == 1) {
    jlog("Warning: you seems to read more than one acoustic model for recognition, but\n");
    jlog("Warning: previous one already has header-embedded acoustic parameters\n");
    jlog("Warning: if you have different parameters, result may be wrong!\n");
  }
  
  /* allocate new hmminfo */
  hmminfo = hmminfo_new();
  /* load hmmdefs */
  if (init_hmminfo(hmminfo, amconf->hmmfilename, amconf->mapfilename, &(amconf->analysis.para_hmm)) == FALSE) {
    hmminfo_free(hmminfo);
    return NULL;
  }
  if (debug2_flag) {
    HTK_HMM_Data *dtmp;
    int i;
    for (dtmp = hmminfo->start; dtmp; dtmp = dtmp->next) {
      printf("***\nname: %s\n", dtmp->name);
      for (i=0;i<dtmp->state_num;i++) {
	if (dtmp->s[i] == NULL) continue;
	printf("state %d: id=%d   %s\n", i + 1, dtmp->s[i]->id, (dtmp->s[i]->name) ? dtmp->s[i]->name : "");
      }
    }
  }

  /* set multipath mode flag */
  if (amconf->force_multipath) {
    jlog("STAT: m_fusion: force multipath HMM handling by user request\n");
    hmminfo->multipath = TRUE;
  } else {
    hmminfo->multipath = hmminfo->need_multipath;
  }

  /* only MFCC is supported for audio input */
  /* MFCC_{0|E}[_D][_A][_Z][_N] is supported */
  /* check parameter type of this acoustic HMM */
  if (jconf->input.type == INPUT_WAVEFORM) {
    /* Decode parameter extraction type according to the training
       parameter type in the header of the given acoustic HMM */
    switch(hmminfo->opt.param_type & F_BASEMASK) {
    case F_MFCC:
    case F_FBANK:
    case F_MELSPEC:
      break;
    default:
      jlog("ERROR: m_fusion: for direct speech input, only HMM trained by MFCC ior filterbank is supported\n");
      hmminfo_free(hmminfo);
      return NULL;
    }
    /* set acoustic analysis parameters from HMM header */
    calc_para_from_header(&(amconf->analysis.para), hmminfo->opt.param_type, hmminfo->opt.vec_size);
  }
  /* check if tied_mixture */
  if (hmminfo->is_tied_mixture && hmminfo->codebooknum <= 0) {
    jlog("ERROR: m_fusion: this tied-mixture model has no codebook!?\n");
    hmminfo_free(hmminfo);
    return NULL;
  }

#ifdef PASS1_IWCD
  /* make state clusters of same context for inter-word triphone approx. */
  if (hmminfo->is_triphone) {
    if (hmminfo->cdset_root == NULL) {
      jlog("STAT: making pseudo bi/mono-phone for IW-triphone\n");
      if (make_cdset(hmminfo) == FALSE) {
	jlog("ERROR: m_fusion: failed to make context-dependent state set\n");
	hmminfo_free(hmminfo);
	return NULL;
      }
    } else {
      jlog("STAT: pseudo phones are loaded from binary hmmlist file\n");
    }

    /* add those `pseudo' biphone and monophone to the logical HMM names */
    /* they points not to the defined HMM, but to the CD_Set structure */
    hmm_add_pseudo_phones(hmminfo);
  }
#endif

  /* find short pause model and set to hmminfo->sp */
  htk_hmm_set_pause_model(hmminfo, amconf->spmodel_name);


  hmminfo->cdset_method = amconf->iwcdmethod;
  hmminfo->cdmax_num = amconf->iwcdmaxn;

  if (amconf->analysis.para_htk.loaded == 1) apply_para(&(amconf->analysis.para), &(amconf->analysis.para_htk));
  if (amconf->analysis.para_hmm.loaded == 1) apply_para(&(amconf->analysis.para), &(amconf->analysis.para_hmm));
  apply_para(&(amconf->analysis.para), &(amconf->analysis.para_default));

  return(hmminfo);
  
}
Beispiel #15
0
/** 
 * <JA>
 * GMMの計算のための初期化. 起動時に一度だけ呼ばれる. 
 * 
 * @param recog [i/o] エンジンインスタンス
 * </JA>
 * <EN>
 * Initialization for computing GMM likelihoods.  This will be called
 * once on startup.
 * 
 * @param recog [i/o] engine instance
 * </EN>
 *
 * @callgraph
 * @callergraph
 * 
 */
boolean
gmm_init(Recog *recog)
{
  HTK_HMM_INFO *gmm;
  HTK_HMM_Data *d;
  GMMCalc *gc;
  int i;

  gmm = recog->gmm;

  /* check GMM format */
  /* tied-mixture GMM is not supported */
  if (gmm->is_tied_mixture) {
    jlog("ERROR: gmm_init: tied-mixture GMM is not supported\n");
    return FALSE;
  }
  /* assume 3 state GMM (only one output state) */
  for(d=gmm->start;d;d=d->next) {
    if (d->state_num > 3) {
      jlog("ERROR: gmm_init: more than three states (one output state) defined in GMM [%s]\n", d->name);
      return FALSE;
    }
  }

  /* check if CMN needed */

  /* allocate work area */
  if (recog->gc == NULL) {
    gc = (GMMCalc *)mymalloc(sizeof(GMMCalc));
    recog->gc = gc;
  } else {
    gc = recog->gc;
  }
  
  /* allocate buffers */
  gc->gmm_score = (LOGPROB *)mymalloc(sizeof(LOGPROB) * gmm->totalhmmnum);

#ifdef GMM_VAD
  gc->nframe = recog->jconf->detect.gmm_margin;
  gc->rates = (LOGPROB *)mymalloc(sizeof(LOGPROB) * gc->nframe);
#endif

  gc->is_voice = (boolean *)mymalloc(sizeof(boolean) * gmm->totalhmmnum);
  i = 0;
  if (recog->jconf->reject.gmm_reject_cmn_string) {
    for(d=recog->gmm->start;d;d=d->next) {
      if (strstr(recog->jconf->reject.gmm_reject_cmn_string, d->name)) {
	gc->is_voice[i] = FALSE;
      } else {
	gc->is_voice[i] = TRUE;
      }
      i++;
    }
  } else {
    for(d=recog->gmm->start;d;d=d->next) {
      gc->is_voice[i] = TRUE;
      i++;
    }
  }

  /* initialize work area */
  gc->OP_nstream = gmm->opt.stream_info.num;
  for(i=0;i<gc->OP_nstream;i++) {
    gc->OP_veclen_stream[i] = gmm->opt.stream_info.vsize[i];
  }
  gmm_gprune_safe_init(gc, gmm, recog->jconf->reject.gmm_gprune_num);

  /* check if variances are inversed */
  if (!gmm->variance_inversed) {
    /* here, inverse all variance values for faster computation */
    htk_hmm_inverse_variances(gmm);
    gmm->variance_inversed = TRUE;
  }

  return TRUE;
}
/** 
 *
 * Compaction of back-off elements in N-gram data.
 * 
 * @param ndata [i/o] N-gram information
 * @param n [i] N of N-gram
 * 
 * @return TRUE on success, or FALSE on failure.
 * 
 */
boolean
ngram_compact_context(NGRAM_INFO *ndata, int n)
{
  NNID i;
  NNID c;
  NNID dst;
  NNID ntmp;
  NGRAM_TUPLE_INFO *this, *up;

  this = &(ndata->d[n-1]);
  up   = &(ndata->d[n]);

  /* count number of valid context */
  c = 0;
  for(i=0;i<up->bgnlistlen;i++) {
    if ((up->is24bit == TRUE && up->bgn_upper[i] != NNID_INVALID_UPPER)
	|| (up->is24bit == FALSE && up->bgn[i] != NNID_INVALID)) {
      c++;
    } else {
      if (up->num[i] != 0) {
	jlog("Error: ngram_compact_context: internal error\n");
	return FALSE;
      }
      if (this->bo_wt[i] != 0.0) {
	jlog("Warning: ngram_compact_context: found a %d-gram that has non-zero back-off weight but not a context of upper N-gram (%f)\n", n, this->bo_wt[i]);
	jlog("Warning: ngram_compact_context: context compaction disabled\n");
	ndata->d[n-1].ct_compaction = FALSE;
	return TRUE;		/* no op */
      }
    }
  }
  
  if (this->totalnum == c) {
    jlog("Stat: ngram_compact_context: %d-gram has full bo_wt, compaction disabled\n", n);
    ndata->d[n-1].ct_compaction = FALSE;
    return TRUE;		/* no op */
  }

  if (c >= NNID_MAX_24) {
    jlog("Stat: ngram_compact_context: %d-gram bo_wt exceeds 24bit, compaction diabled\n", n);
    ndata->d[n-1].ct_compaction = FALSE;
    return TRUE;		/* no op */
  }    

  this->context_num = c;
  jlog("Stat: ngram_compact_context: %d-gram back-off weight compaction: %d -> %d\n", n, this->totalnum, this->context_num);
  
  /* allocate index buffer */
  this->nnid2ctid_upper = (NNID_UPPER *)mymalloc(sizeof(NNID_UPPER) * this->totalnum);
  this->nnid2ctid_lower = (NNID_LOWER *)mymalloc(sizeof(NNID_LOWER) * this->totalnum);
  /* make index and do compaction of context informations */
  dst = 0;
  for(i=0;i<up->bgnlistlen;i++) {
    if ((up->is24bit == TRUE && up->bgn_upper[i] != NNID_INVALID_UPPER)
	|| (up->is24bit == FALSE && up->bgn[i] != NNID_INVALID)) {
      this->bo_wt[dst] = this->bo_wt[i];
      if (up->is24bit) {
	up->bgn_upper[dst] = up->bgn_upper[i];
	up->bgn_lower[dst] = up->bgn_lower[i];
      } else {
	up->bgn[dst] = up->bgn[i];
      }
      up->num[dst] = up->num[i];
      ntmp = dst & 0xffff;
      this->nnid2ctid_lower[i] = ntmp;
      ntmp = dst >> 16;
      this->nnid2ctid_upper[i] = ntmp;
      dst++;
    } else {
      this->nnid2ctid_upper[i] = NNID_INVALID_UPPER;
Beispiel #17
0
/* Authentication Request from the node */
int authRequest(struct session *session, DNDSMessage_t *req_msg)
{
	char *certName = NULL;
	size_t length = 0;
	uint32_t context_id = 0;

	struct session *old_session = NULL;

	AuthRequest_get_certName(req_msg, &certName, &length);

	if (session->state != SESSION_STATE_NOT_AUTHED) {
		jlog(L_WARNING, "authRequest duplicate");
		return -1;
	}

	DNDSMessage_t *msg = NULL;

	DNDSMessage_new(&msg);
	DNDSMessage_set_channel(msg, 0);
	DNDSMessage_set_pdu(msg, pdu_PR_dnm);

	DNMessage_set_seqNumber(msg, 1);
	DNMessage_set_ackNumber(msg, 0);
	DNMessage_set_operation(msg, dnop_PR_authResponse);

	AuthRequest_get_certName(req_msg, &certName, &length);

	session->node_info = cn2node_info(certName);
	if (session->node_info == NULL) {
		jlog(L_WARNING, "cn2node_info failed");
		DNDSMessage_del(msg);
		return -1;
	}

	jlog(L_DEBUG, "type: %s", session->node_info->type);
	jlog(L_DEBUG, "uuid: %s", session->node_info->uuid);
	jlog(L_DEBUG, "context_id: %s", session->node_info->context_id);

	context_id = atoi(session->node_info->context_id);
	session->context = context_lookup(context_id);

	if (session->context == NULL) {
		AuthResponse_set_result(msg, DNDSResult_insufficientAccessRights);
		net_send_msg(session->netc, msg);
		DNDSMessage_del(msg);
		return -1;
	}

	/* check if the node's uuid is known */
	if (ctable_find(session->context->atable, session->node_info->uuid) == NULL) {
		AuthResponse_set_result(msg, DNDSResult_insufficientAccessRights);
		net_send_msg(session->netc, msg);
		DNDSMessage_del(msg);
		jlog(L_ERROR, "authentication failed, invalid certificate");
		return -1;
	}

	/* check if the node is already connected */
	old_session = ctable_find(session->context->ctable, session->node_info->uuid);
	if (old_session == NULL) {
		ctable_insert(session->context->ctable, session->node_info->uuid, session);
	} else {
		// that node is already connected, if the new session is from the same IP
		// disconnect the old session, and let this one connect
		if (strcmp(old_session->ip, session->ip) == 0) {
			net_disconnect(old_session->netc);
			ctable_insert(session->context->ctable, session->node_info->uuid, session);
		}
	}

	session->cert_name = strdup(certName);
	if (session->netc->security_level == NET_UNSECURE) {

		AuthResponse_set_result(msg, DNDSResult_success);
		net_send_msg(session->netc, msg);

		session->state = SESSION_STATE_AUTHED;
		session->netc->on_secure(session->netc);

	} else {

		AuthResponse_set_result(msg, DNDSResult_secureStepUp);
		net_send_msg(session->netc, msg);

		krypt_add_passport(session->netc->kconn, session->context->passport);
		session->state = SESSION_STATE_WAIT_STEPUP;
		net_step_up(session->netc);
	}

	DNDSMessage_del(msg);

	return 0;
}
/** 
 * @brief  Main top routine to read in HTK %HMM definition file.
 *
 * A HTK %HMM definition file will be read from @a fp.  After reading,
 * the parameter type is checked and calculate some statistics.
 * 
 * @param fp [in] file pointer
 * @param hmm [out] pointer to a %HMM definition structure to store data.
 * 
 * @return TRUE on success, FALSE on failure.
 */
boolean
rdhmmdef(FILE *fp, HTK_HMM_INFO *hmm)
{
  char macrosw;
  char *name;

  /* variances in htkdefs are not inversed yet */
  hmm->variance_inversed = FALSE;

  /* read the first token */
  /* read new 1 line */
  line = 1;
  if (getl(buf, MAXBUFLEN, fp) == NULL) {
    rdhmmdef_token = NULL;
  } else {
    rdhmmdef_token = mystrtok_quote(buf, HMMDEF_DELM);
  }
  
  /* the toplevel loop */
  while (rdhmmdef_token != NULL) {/* break on EOF */
    if (rdhmmdef_token[0] != '~') { /* toplevel commands are always macro */
      return FALSE;
    }
    macrosw = rdhmmdef_token[1];
    read_token(fp);		/* read next token after the "~.."  */
    switch(macrosw) {
    case 'o':			/* global option */
      if (set_global_opt(fp,hmm) == FALSE) {
	return FALSE;
      }
      break;
    case 't':			/* transition macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_trans_macro(name, fp, hmm);
      break;
    case 's':			/* state macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_state_macro(name, fp, hmm);
      break;
    case 'm':			/* density (mixture) macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_dens_macro(name, fp, hmm);
      break;
    case 'h':			/* HMM define */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_HMM(name, fp, hmm);
      break;
    case 'v':			/* Variance macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_var_macro(name, fp, hmm);
      break;
    case 'w':			/* Stream weight macro */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_streamweight_macro(name, fp, hmm);
      break;
    case 'r':			/* Regression class macro (ignore) */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_regtree_macro(name, fp, hmm);
      break;
    case 'p':			/* Mixture pdf macro (extension of HTS) */
      name = mybstrdup2(rdhmmdef_token, &(hmm->mroot));
      if (strlen(name) >= MAX_HMMNAME_LEN) rderr("Macro name too long");
      read_token(fp);
      def_mpdf_macro(name, fp, hmm);
      break;
    }
  }

  /* convert transition prob to log scale */
  conv_log_arc(hmm);

  jlog("Stat: rdhmmdef: ascii format HMM definition\n");
  
  /* check limitation */
  if (check_all_hmm_limit(hmm)) {
    jlog("Stat: rdhmmdef: limit check passed\n");
  } else {
    jlog("Error: rdhmmdef: cannot handle this HMM due to system limitation\n");
    return FALSE;
  }

  /* determine whether this model needs multi-path handling */
  hmm->need_multipath = htk_hmm_has_several_arc_on_edge(hmm);
  if (hmm->need_multipath) {
    jlog("Stat: rdhmmdef: this HMM requires multipath handling at decoding\n");
  } else {
    jlog("Stat: rdhmmdef: this HMM does not need multipath handling\n");
  }
  
  /* inverse all variance values for faster computation */
  if (! hmm->variance_inversed) {
    htk_hmm_inverse_variances(hmm);
    hmm->variance_inversed = TRUE;
  }

  /* check HMM parameter option type */
  if (!check_hmm_options(hmm)) {
    jlog("Error: rdhmmdef: hmm options check failed\n");
    return FALSE;
  }

  /* add ID number for all HTK_HMM_State if not assigned */
  {
    HTK_HMM_State *stmp;
    int n;
    boolean has_sid;

    /* caclculate total num and check if has sid */
    has_sid = FALSE;
    n = 0;
    for (stmp = hmm->ststart; stmp; stmp = stmp->next) {
      n++;
      if (n >= MAX_STATE_NUM) {
	jlog("Error: rdhmmdef: too much states in a model > %d\n", MAX_STATE_NUM);
	return FALSE;
      }
      if (stmp->id != -1) {
	has_sid = TRUE;
      }
    }
    hmm->totalstatenum = n;
    if (has_sid) {
      jlog("Stat: rdhmmdef: <SID> found in the definition\n");
      /* check if each state is assigned a valid sid */
      if (htk_hmm_check_sid(hmm) == FALSE) {
	jlog("Error: rdhmmdef: error in SID\n");
	return FALSE;
      }
    } else {
      /* assign internal sid (will not be saved) */
      jlog("Stat: rdhmmdef: no <SID> embedded\n");
      jlog("Stat: rdhmmdef: assign SID by the order of appearance\n");
      n = hmm->totalstatenum;
      for (stmp = hmm->ststart; stmp; stmp = stmp->next) {
	stmp->id = --n;
      }
    }
  }
  /* calculate the maximum number of mixture */
  {
    HTK_HMM_State *stmp;
    int max, s, mix;
    max = 0;
    for (stmp = hmm->ststart; stmp; stmp = stmp->next) {
      for(s=0;s<stmp->nstream;s++) {
	mix = stmp->pdf[s]->mix_num;
	if (max < mix) max = mix;
      }
    }
    hmm->maxmixturenum = max;
  }
  /* compute total number of HMM models and maximum length */
  {
    HTK_HMM_Data *dtmp;
    int n, maxlen;
    n = 0;
    maxlen = 0;
    for (dtmp = hmm->start; dtmp; dtmp = dtmp->next) {
      if (maxlen < dtmp->state_num) maxlen = dtmp->state_num;
      n++;
    }
    hmm->maxstatenum = maxlen;
    hmm->totalhmmnum = n;
  }
  /* compute total number of Gaussians */
  {
    HTK_HMM_Dens *dtmp;
    int n = 0;
    for (dtmp = hmm->dnstart; dtmp; dtmp = dtmp->next) {
      n++;
    }
    hmm->totalmixnum = n;
  }
  /* check of HMM name length exceed the maximum */
  {
    HTK_HMM_Dens *dtmp;
    int n = 0;
    for (dtmp = hmm->dnstart; dtmp; dtmp = dtmp->next) {
      n++;
    }
    hmm->totalmixnum = n;
  }
  /* compute total number of mixture PDFs */
  {
    HTK_HMM_PDF *p;
    int n = 0;
    for (p = hmm->pdfstart; p; p = p->next) {
      n++;
    }
    hmm->totalpdfnum = n;
  }
  /* assign ID number for all HTK_HMM_Trans */
  {
    HTK_HMM_Trans *ttmp;
    int n = 0;
    for (ttmp = hmm->trstart; ttmp; ttmp = ttmp->next) {
      ttmp->id = n++;
    }
    hmm->totaltransnum = n;
  }
#ifdef ENABLE_MSD
  /* check if MSD-HMM */
  htk_hmm_check_msd(hmm);
#endif

  return(TRUE);			/* success */
}
Beispiel #19
0
static
int login_setforward_user(struct clientinfo* clntinfo) {

	const char* forward;
	struct slist_t* forward_list, *forward_list_cur;
	char* tmp;
	int newsize;
	int config_state = TAG_GLOBAL | TAG_FROM | TAG_PORT
			 | TAG_TIME | TAG_SERVERTYPE
			 | TAG_PROXYIP | TAG_PROXYPORT;

	/* this is already a forward */
	if ( clntinfo->before_forward.user ) {
		return CMD_HANDLED;
	}

	if ( clntinfo->destination ) {
		config_state |= TAG_TO;
	}

	if ( clntinfo->user ) {
		config_state |= TAG_USER;
	}

	config_shrink_config(get_uint_ip(GET_IP_CLIENT, clntinfo),
			get_uint_ip(GET_IP_SERVER, clntinfo),
			clntinfo->destination,
			clntinfo->destinationport,
			clntinfo->user,
			-1,          /* before_forward.dest_ip */
			(char*) 0,   /* before_forward.destination */
			0,           /* before_forward.destinationport */
			(char*) 0,   /* before_forward.user */
			0,		/* set no specific time */
			clntinfo->proxy_ip,
			clntinfo->proxy_port,
			srvinfo.servertype,
			&hostcache,
			config_state);

	if (config_compare_option("access", "allow") == 0) {
		say(clntinfo->clientsocket, "531 You are not allowed to "
			"connect to that host. Goodbye.\r\n");
		jlog(5, "%s was not allowed to connect.",
					conv_ip_to_char(clntinfo->client_ip));
		return CMD_ERROR;
	}

	/* see if there is an option for the forward */
	forward = config_get_option("forward");

	if (! forward) {
		/* no forward */
		lcs.userlogin = strnulldup(clntinfo->user);
		lcs.usereffective = strnulldup(clntinfo->user);
		if (lcs.userforwarded) { free(lcs.userforwarded); }
		lcs.userforwarded = strdup("<no forward>");
		enough_mem(lcs.userforwarded);
		return CMD_HANDLED;
	}

	/*
	 * <user ftp>
	 *    forward [email protected]
	 *    forward [email protected],3949,p
	 *    forward [email protected]     *     johnspass
	 *    forward [email protected]   JiKe94  johnspass
	 * </user>
	 *    forward *@fooserver.com:2378
	 *    forward %@fooserver.com:2378
	 */

	/* split the list into tokens */
	if ( ! (forward_list = config_split_line( forward, WHITESPACES )) ) {
		return CMD_HANDLED;
	}

	/* if we have a defaultforward setting, the variable user has to be
	 * defined so that we can decide if we can use defaultforward at
	 * all. If this is not the case, but there is a defaultforward
	 * setting, skip this whole part. This can happen by setting
	 * logintime to "connect" */
	if (!clntinfo->user &&
	    forward_list->value &&
	    forward_list->value[0] == '%' &&
	    forward_list->value[1] == '@') {
		slist_destroy(forward_list);
		return CMD_HANDLED;
	}

	/* if there is a defaultforward but we already have a destination
	 * set, we can quit here as well */
	if (clntinfo->destination &&
	    forward_list->value &&
	    forward_list->value[0] == '%' &&
	    forward_list->value[1] == '@') {
		/* no forward is being used */
		lcs.userlogin = strnulldup(clntinfo->user);
		lcs.usereffective = strnulldup(clntinfo->user);
		if (lcs.userforwarded) { free(lcs.userforwarded); }
		lcs.userforwarded = strdup("<no forward>");
		enough_mem(lcs.userforwarded);
		slist_destroy(forward_list);
		return CMD_HANDLED;
	}


	forward_list_cur = forward_list;

	/* read and save the values */
	clntinfo->forward.login = strdup(forward_list_cur->value);
	enough_mem(clntinfo->forward.login);

	forward_list_cur = forward_list_cur->next;

	if (forward_list_cur && forward_list_cur->value) {
		clntinfo->forward.accept_pw = strdup(forward_list_cur->value);
		enough_mem(clntinfo->forward.accept_pw);
	} else {
		clntinfo->forward.accept_pw = (char*) 0;
	}

	if (forward_list_cur) {
		forward_list_cur = forward_list_cur->next;
	}
	if (forward_list_cur && forward_list_cur->value) {
		clntinfo->forward.send_pw = strdup(forward_list_cur->value);
		enough_mem(clntinfo->forward.send_pw);
	} else {
		clntinfo->forward.send_pw = (char*) 0;
	}
	/* destroy the list again, we have saved the values into
	 * clntinfo->forward.<field>    */
	slist_destroy(forward_list);

	/* delete those configuration values that are evaluated by the
	 * parsing routine  -  they are not necessary anymore */
	config_option_list_delete("transparent-forward");
	config_option_list_delete("forward");

	/* back up */
	clntinfo->before_forward.user = strnulldup(clntinfo->user);
	clntinfo->before_forward.destination
			= strnulldup(clntinfo->destination);
	clntinfo->before_forward.destinationport = clntinfo->destinationport;
	clntinfo->before_forward.dest_ip = get_uint_ip(GET_IP_SERVER,clntinfo);

	/* special case: We don't have set a username. The client could have
	 * used logintime == connect and has a forward that already matches */
	if ( ! clntinfo->before_forward.user ) {
		clntinfo->before_forward.user = malloc(2);
		enough_mem(clntinfo->before_forward.user);
		clntinfo->before_forward.user[0] = '*';
		clntinfo->before_forward.user[1] = '\0';
	}

	/* if there was only a new destination but no new username given,
	 * prepend the old one */
	if ( ! strchr(clntinfo->forward.login, '@')
			&& clntinfo->before_forward.user) {
		newsize = strlen(clntinfo->before_forward.user)
			  + 1 /* @ */
			  + strlen(clntinfo->forward.login)
			  + 1 /* term */;

		tmp = (char*) malloc(newsize);
		enough_mem(tmp);
		snprintf( tmp, newsize, "%s@%s", clntinfo->before_forward.user,
						 clntinfo->forward.login);
		free(clntinfo->forward.login);
		clntinfo->forward.login = tmp;
	}

	if (clntinfo->forward.login[0] == '*' &&
	    clntinfo->forward.login[1] == '@') {
		/* passauth */
		clntinfo->forward.passauth = 1;
	}

	/* If there is still no destination, see if we have a defaultforward
	 * setting */
	if (clntinfo->destination == (char*) 0 &&
	    clntinfo->user &&
	    clntinfo->forward.login[0] == '%' &&
	    clntinfo->forward.login[1] == '@') {
		/* defaultforward */
		int newsize = strlen(&(clntinfo->forward.login[1])) +
				strlen(clntinfo->user) + 1;
		char* tmp = (char*) malloc(newsize);
		enough_mem(tmp);
		snprintf(tmp, newsize, "%s%s", clntinfo->user,
					&(clntinfo->forward.login[1]));
		free(clntinfo->forward.login);
		clntinfo->forward.login = tmp;
		jlog(8, "No destination was set. Using %s because of defaultforward setting", clntinfo->forward.login);
	}

	/* call the parsing routine and let it set the values */
	if (set_userdest(clntinfo->forward.login, 0, clntinfo, "@,: \t") < 0) {
		return CMD_ERROR;
	}

	/* set values for log info struct */
	lcs.userlogin = strnulldup(clntinfo->before_forward.user);
	lcs.usereffective = strnulldup(clntinfo->user);
	lcs.userforwarded = strnulldup(clntinfo->forward.login);

	/* shrink the configuration again - with TAG_FORWARDED this time */

	config_shrink_config(get_uint_ip(GET_IP_CLIENT, clntinfo),
			/* these are the original values */
			/* see above (1) */
			clntinfo->before_forward.dest_ip,
			clntinfo->before_forward.destination,
			clntinfo->before_forward.destinationport,
			clntinfo->before_forward.user,
			/* these are the values set by the forward */
			/* pass them as well, if we are in the
			 * forwarded_tag, config_match_section()
			 * will overwrite the previous with the
			 * following values */
			get_uint_ip(GET_IP_SERVER, clntinfo),
			clntinfo->destination,
			clntinfo->destinationport,
			clntinfo->user,

			0,		/* set no specific time */

			clntinfo->proxy_ip,
			clntinfo->proxy_port,

			srvinfo.servertype, &hostcache,
			TAG_ALL);

	return CMD_HANDLED;
}
Beispiel #20
0
netc_t *net_client(const char *listen_addr,
			const char *port,
			uint8_t protocol,
			uint8_t security_level,
			passport_t *passport,
			void (*on_disconnect)(netc_t *),
			void (*on_input)(netc_t *),
			void (*on_secure)(netc_t *))
{
	int ret = 0;
	netc_t *netc = NULL;

	netc = net_connection_new(security_level);
	if (netc == NULL) {
	        return NULL;
	}

	netc->protocol = protocol;
	netc->on_secure = on_secure;
	netc->on_disconnect = on_disconnect;
	netc->on_input = on_input;
	netc->conn_type = NET_CLIENT;
	netc->security_level = security_level;

	if (security_level > NET_UNSECURE)
		krypt_add_passport(netc->kconn, passport);

	switch (protocol) {
#ifdef __linux__
		case NET_PROTO_TCP:
			netc->peer = tcpbus_client(listen_addr, port,
				net_on_disconnect, net_on_input);
			break;
#endif
		case NET_PROTO_UDT:
			netc->peer = udtbus_client(listen_addr, port,
				net_on_disconnect, net_on_input);
			break;

		default:
			jlog(L_NOTICE, "net> unknown protocol specified");
			net_connection_free(netc);
			return NULL;
	}

	if (netc->peer == NULL) {
		jlog(L_NOTICE, "Unable to connect to %s:%s", listen_addr, port);
		net_connection_free(netc);
		return NULL;
	}

	netc->peer->ext_ptr = netc;

	if (security_level > NET_UNSECURE) {

		// FIXME net and krypt should share constants
		int krypt_security_level;
		if (netc->security_level == NET_SECURE_ADH)
			krypt_security_level = KRYPT_ADH;
		else
			krypt_security_level = KRYPT_RSA;

		ret = krypt_secure_connection(netc->kconn, KRYPT_TLS, KRYPT_CLIENT, krypt_security_level);
		if (ret < 0) {
			jlog(L_NOTICE, "securing client connection failed");
			net_connection_free(netc);
			return NULL;
		}

		krypt_do_handshake(netc->kconn, NULL, 0);
		net_do_krypt(netc);
	}

	return netc;
}
Beispiel #21
0
static
int login_sendauth_pass(struct clientinfo* clntinfo) {
	size_t sendbufsize;
	int ret;
	char* sendbuf, *buffer;

	buffer = clntinfo->login.authresp.lastmsg;
	if ( !checkdigits(buffer, 331) && !checkdigits(buffer, 230)) {
		/* prepend the response from the server with an error code
		 * and return it to the client */
		sendbufsize = strlen(buffer) + 4 + 1;
		sendbuf = (char*) malloc(sendbufsize);
		enough_mem(sendbuf);
		snprintf(sendbuf, sendbufsize, "500 %s", buffer);
		say(clntinfo->clientsocket, sendbuf);
		free(sendbuf);

		jlog(7, "Got \"%s\" after sending the username.", buffer);
		free(clntinfo->login.authresp.fullmsg);
		free(clntinfo->login.welcomemsg.fullmsg);
		clntinfo->login.welcomemsg.fullmsg = (char*) 0;
		clntinfo->login.welcomemsg.lastmsg = (char*) 0;
		clntinfo->login.authresp.fullmsg   = (char*) 0;
		clntinfo->login.authresp.lastmsg   = (char*) 0;
		return CMD_ERROR;
	}

	if (!checkdigits(buffer, 230)) {
		char* userdup;
		size_t size;

		sendbufsize = strlen("PASS \r\n") + strlen(clntinfo->pass) + 1;
		sendbuf = (char*) malloc(sendbufsize);
		enough_mem(sendbuf);
		snprintf(sendbuf, sendbufsize, "PASS %s\r\n", clntinfo->pass);
		ret = say(clntinfo->serversocket, sendbuf);

		size = strlen(clntinfo->user) + 3;
		userdup = (char*) malloc( size );
		snprintf(userdup, size, " %s ", clntinfo->user);

		if (strstr(ANON_USERS, userdup)) {
			clntinfo->anon_user = clntinfo->pass;
			clntinfo->pass = (char*) 0;
		} else {
			memset(sendbuf, (char) 0, sendbufsize);
			clntinfo->anon_user = (char*) 0;
		}
		free(sendbuf);
		free(userdup);
		sendbuf = userdup = (char*) 0;
		free(clntinfo->login.authresp.fullmsg);
		clntinfo->login.authresp.fullmsg   = (char*) 0;
		clntinfo->login.authresp.lastmsg   = (char*) 0;

		if (ret < 0) {
			jlog(2, "Error writing the password to the server: %s",
				strerror(errno));
			free(clntinfo->login.welcomemsg.fullmsg);
			clntinfo->login.welcomemsg.fullmsg = (char*) 0;
			clntinfo->login.welcomemsg.lastmsg = (char*) 0;
			return CMD_ABORT;
		}
	}
	return CMD_HANDLED;
}
/** 
 * @brief  Perform Viterbi alignment.
 *
 * This function performs viterbi alignment for the given sentence %HMM,
 * input parameter and unit definition.  Any segmentatino unit (word, phoneme
 * state, etc.) is allowed: the segmentation unit should be specified by
 * specifying a list of state id which are the end of each unit.
 * For example, if you want to obtain phoneme alignment, the list of state
 * number that exist at the end of phones should be specified by @a endstates.
 * 
 * @param hmm [in] sentence HMM to be matched
 * @param param [in] input parameter data
 * @param wrk [i/o] HMM computation work area
 * @param multipath [in] TRUE if need multi-path handling
 * @param endstates [in] list of state id that corrsponds to the ends of units
 * @param ulen [in] total number of units in the @a hmm
 * @param id_ret [out] Pointer to store the newly allocated array of the resulting id sequence of units on the best path.
 * @param seg_ret [out] Pointer to store the newly allocated array of the resulting end frame of each unit on the best path.
 * @param uscore_ret [out] Pointer to store the newly allocated array of the resulting score at the end frame of each unit on the best path.
 * @param slen_ret [out] Pointer to store the total number of units on the best path.
 * 
 * @return the total acoustic score for the whole input.
 */
LOGPROB
viterbi_segment(HMM *hmm, HTK_Param *param, HMMWork *wrk, boolean multipath, int *endstates, int ulen, int **id_ret, int **seg_ret, LOGPROB **uscore_ret, int *slen_ret)
{
  /* for viterbi */
  LOGPROB *nodescore[2];	/* node buffer */
  SEGTOKEN **tokenp[2];		/* propagating token which holds segment info */
  int startt, endt;
  int *from_node;
  int *u_end, *u_start;	/* the node is an end of the word, or -1 for non-multipath mode*/
  int i, n;
  unsigned int t;
  int tl,tn;
  LOGPROB tmpsum;
  A_CELL *ac;
  SEGTOKEN *newtoken, *token, *tmptoken, *root;
  LOGPROB result_score;
  LOGPROB maxscore, minscore;	/* for debug */
  int maxnode;			/* for debug */
  int *id, *seg, slen;
  LOGPROB *uscore;

  /* assume more than 1 units */
  if (ulen < 1) {
    jlog("Error: vsegment: no unit?\n");
    return LOG_ZERO;
  }

  if (!multipath) {
    /* initialize unit start/end marker */
    u_start = (int *)mymalloc(hmm->len * sizeof(int));
    u_end   = (int *)mymalloc(hmm->len * sizeof(int));
    for (n = 0; n < hmm->len; n++) {
      u_start[n] = -1;
      u_end[n] = -1;
    }
    u_start[0] = 0;
    u_end[endstates[0]] = 0;
    for (i=1;i<ulen;i++) {
      u_start[endstates[i-1]+1] = i;
      u_end[endstates[i]] = i;
    }
#if 0
    for (i=0;i<hmm->len;i++) {
      printf("unit %d: start=%d, end=%d\n", i, u_start[i], u_end[i]);
    }
#endif
  }

  /* initialize node buffers */
  tn = 0;
  tl = 1;
  root = NULL;
  for (i=0;i<2;i++){
    nodescore[i] = (LOGPROB *)mymalloc(hmm->len * sizeof(LOGPROB));
    tokenp[i] = (SEGTOKEN **)mymalloc(hmm->len * sizeof(SEGTOKEN *));
    for (n = 0; n < hmm->len; n++) {
      tokenp[i][n] = NULL;
    }
  }
  for (n = 0; n < hmm->len; n++) {
    nodescore[tn][n] = LOG_ZERO;
    newtoken = (SEGTOKEN *)mymalloc(sizeof(SEGTOKEN));
    newtoken->last_id = -1;
    newtoken->last_end_frame = -1;
    newtoken->last_end_score = 0.0;
    newtoken->list = root;
    root = newtoken;
    newtoken->next = NULL;
    tokenp[tn][n] = newtoken;
  }
  from_node = (int *)mymalloc(sizeof(int) * hmm->len);
  
  /* first frame: only set initial score */
  /*if (hmm->state[0].is_pseudo_state) {
    jlog("Warning: state %d: pseudo state?\n", 0);
    }*/
  if (multipath) {
    nodescore[tn][0] = 0.0;
  } else {
    nodescore[tn][0] = outprob(wrk, 0, &(hmm->state[0]), param);
  }

  /* do viterbi for rest frame */
  if (multipath) {
    startt = 0;  endt = param->samplenum;
  } else {
    startt = 1;  endt = param->samplenum - 1;
  }
  for (t = startt; t <= endt; t++) {
    i = tl;
    tl = tn;
    tn = i;
    maxscore = LOG_ZERO;
    minscore = 0.0;

    /* clear next scores */
    for (i=0;i<hmm->len;i++) {
      nodescore[tn][i] = LOG_ZERO;
      from_node[i] = -1;
    }

    /* select viterbi path for each node */
    for (n = 0; n < hmm->len; n++) {
      if (nodescore[tl][n] <= LOG_ZERO) continue;
      for (ac = hmm->state[n].ac; ac; ac = ac->next) {
        tmpsum = nodescore[tl][n] + ac->a;
        if (nodescore[tn][ac->arc] < tmpsum) {
          nodescore[tn][ac->arc] = tmpsum;
	  from_node[ac->arc] = n;
	}
      }
    }
    /* propagate token, appending new if path was selected between units */
    if (multipath) {
      for (n = 0; n < hmm->len; n++) {
	if (from_node[n] == -1 || nodescore[tn][n] <= LOG_ZERO) {
	  /*tokenp[tn][n] = NULL;*/
	} else {
	  i=0;
	  while (from_node[n] > endstates[i]) i++;
	  if (n > endstates[i]) {
	    newtoken = (SEGTOKEN *)mymalloc(sizeof(SEGTOKEN));
	    newtoken->last_id = i;
	    newtoken->last_end_frame = t-1;
	    newtoken->last_end_score = nodescore[tl][from_node[n]];
	    newtoken->list = root;
	    root = newtoken;
	    newtoken->next = tokenp[tl][from_node[n]];
	    tokenp[tn][n] = newtoken;
	  } else {
	    tokenp[tn][n] = tokenp[tl][from_node[n]];
	  }
	}
      }
    } else {			/* not multipath */
      for (n = 0; n < hmm->len; n++) {
	if (from_node[n] == -1) {
	  tokenp[tn][n] = NULL;
	} else if (nodescore[tn][n] <= LOG_ZERO) {
	  tokenp[tn][n] = tokenp[tl][from_node[n]];
	} else {
	  if (u_end[from_node[n]] != -1 && u_start[n] != -1
	      && from_node[n] !=  n) {
	    newtoken = (SEGTOKEN *)mymalloc(sizeof(SEGTOKEN));
	    newtoken->last_id = u_end[from_node[n]];
	    newtoken->last_end_frame = t-1;
	    newtoken->last_end_score = nodescore[tl][from_node[n]];
	    newtoken->list = root;
	    root = newtoken;
	    newtoken->next = tokenp[tl][from_node[n]];
	    tokenp[tn][n] = newtoken;
	  } else {
	    tokenp[tn][n] = tokenp[tl][from_node[n]];
	  }
	}
      }
    }

    if (multipath) {
      /* if this is next of last frame, loop ends here */
      if (t == param->samplenum) break;
    }
	
    /* calc outprob to new nodes */
    for (n = 0; n < hmm->len; n++) {
      if (multipath) {
	if (hmm->state[n].out.state == NULL) continue;
      }
      if (nodescore[tn][n] > LOG_ZERO) {
	if (hmm->state[n].is_pseudo_state) {
	  jlog("Warning: vsegment: state %d: pseudo state?\n", n);
	}
	nodescore[tn][n] += outprob(wrk, t, &(hmm->state[n]), param);
      }
      if (nodescore[tn][n] > maxscore) { /* for debug */
	maxscore = nodescore[tn][n];
	maxnode = n;
      }
    }
    
#if 0
    for (i=0;i<ulen;i++) {
      printf("%d: unit %d(%d-%d): begin_frame = %d\n", t - 1, i,
	     (i > 0) ? endstates[i-1]+1 : 0, endstates[i],
	     (multipath && tokenp[tl][endstates[i]] == NULL) ? -1 : tokenp[tl][endstates[i]]->last_end_frame + 1);
    }
#endif

    /* printf("t=%3d max=%f n=%d\n",t,maxscore, maxnode); */
    
  }

  result_score = nodescore[tn][hmm->len-1];

  /* parse back the last token to see the trail of best viterbi path */
  /* and store the informations to returning buffer */
  slen = 0;
  if (!multipath) slen++;
  for(token = tokenp[tn][hmm->len-1]; token; token = token->next) {
    if (token->last_end_frame == -1) break;
    slen++;
  }
  id = (int *)mymalloc(sizeof(int)*slen);
  seg = (int *)mymalloc(sizeof(int)*slen);
  uscore = (LOGPROB *)mymalloc(sizeof(LOGPROB)*slen);

  if (multipath) {
    i = slen - 1;
  } else {
    id[slen-1] = ulen - 1;
    seg[slen-1] = t - 1;
    uscore[slen-1] = result_score;
    i = slen - 2;
  }
  for(token = tokenp[tn][hmm->len-1]; token; token = token->next) {
    if (i < 0 || token->last_end_frame == -1) break;
    id[i] = token->last_id;
    seg[i] = token->last_end_frame;
    uscore[i] = token->last_end_score;
    i--;
  }

  /* normalize scores by frame */
  for (i=slen-1;i>0;i--) {
    uscore[i] = (uscore[i] - uscore[i-1]) / (seg[i] - seg[i-1]);
  }
  uscore[0] = uscore[0] / (seg[0] + 1);

  /* set return value */
  *id_ret = id;
  *seg_ret = seg;
  *uscore_ret = uscore;
  *slen_ret = slen;

  /* free memory */
  if (!multipath) {
    free(u_start);
    free(u_end);
  }
  free(from_node);
  token = root;
  while(token) {
    tmptoken = token->list;
    free(token);
    token = tmptoken;
  }
  for (i=0;i<2;i++) {
    free(nodescore[i]);
    free(tokenp[i]);
  }

  return(result_score);

}
Beispiel #23
0
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_log(JNIEnv *env, jclass unused, jdouble d)
{
    return (jdouble) jlog((double)d);
}
Beispiel #24
0
/** 
 * <EN>
 * @brief  Process one input frame for all recognition process instance.
 *
 * This function proceeds the recognition for one frame.  All
 * recognition process instance will be processed synchronously.
 * The input frame for each instance is stored in mfcc->f, where mfcc
 * is the MFCC calculation instance assigned to each process instance.
 *
 * If an instance's mfcc->invalid is set to TRUE, its processing will
 * be skipped.
 *
 * When using GMM, GMM computation will also be executed here.
 * If GMM_VAD is defined, GMM-based voice detection will be performed
 * inside this function, by using a scheme of short-pause segmentation.
 *
 * This function also handles segmentation of recognition process.  A
 * segmentation will occur when end of speech is detected by level-based
 * sound detection or GMM-based / decoder-based VAD, or by request from
 * application.  When segmented, it stores current frame and return with
 * that status.
 *
 * The frame-wise callbacks will be executed inside this function,
 * when at least one valid recognition process instances exists.
 * 
 * </EN>
 * <JA>
 * @brief  全ての認識処理インスタンス処理を1フレーム分進める.
 *
 * 全ての認識処理インスタンスについて,割り付けられているMFCC計算インスタンス
 * の mfcc->f をカレントフレームとして処理を1フレーム進める. 
 *
 * なお,mfcc->invalid が TRUE となっている処理インスタンスの処理はスキップ
 * される. 
 *
 * GMMの計算もここで呼び出される. GMM_VAD 定義時は,GMM による
 * 発話区間開始・終了の検出がここで行われる. また,GMMの計算結果,
 * あるいは認識処理内のショートポーズセグメンテーション判定やデバイス・外部
 * からの要求によりセグメンテーションが要求されたかどうかの判定も行う. 
 *
 * フレーム単位で呼び出されるコールバックが登録されている場合は,それらの
 * 呼出しも行う. 
 * </JA>
 * 
 * @param recog [in] engine instance
 * 
 * @return 0 on success, -1 on error, or 1 when an input segmentation
 * occured/requested inside this function.
 *
 * @callgraph
 * @callergraph
 * 
 */
int
decode_proceed(Recog *recog)
{
  MFCCCalc *mfcc;
  boolean break_flag;
  boolean break_decode;
  RecogProcess *p;
  boolean ok_p;
#ifdef GMM_VAD
  GMMCalc *gmm;
  boolean break_gmm;
#endif
  
  break_decode = FALSE;

  for(p = recog->process_list; p; p = p->next) {
#ifdef DETERMINE
    p->have_determine = FALSE;
#endif
    p->have_interim = FALSE;
  }
  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
    mfcc->segmented = FALSE;
  }

#ifdef POWER_REJECT
  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
    if (!mfcc->valid) continue;
    if (mfcc->f == 0) {
      mfcc->avg_power = 0.0;
      if (debug2_flag) jlog("STAT: power_reject: reset\n");
    }
  }
#endif


#ifdef GMM_VAD
  if (recog->gmm != NULL) {
    /* reset flags */
    break_gmm = FALSE;
    recog->gc->want_rewind = FALSE;
  }
#endif
  if (recog->gmm != NULL && recog->gmmmfcc->valid) {
    /* GMM 計算を行う */
    if (recog->gmmmfcc->f == 0) {
      /* GMM 計算の初期化 */
      gmm_prepare(recog);
    }
    /* このフレームに対するGMMの尤度を計算 */
    gmm_proceed(recog);
#ifdef GMM_VAD
    /* Check for GMM-based VAD */
    gmm = recog->gc;
    gmm_check_trigger(recog);
    if (gmm->after_trigger) {
      /* after trigger, in speech area */
      if (gmm->down_trigger) {
	/* down trigger, end segment */
#ifdef GMM_VAD_DEBUG
	printf("GMM_VAD: %d: down trigger\n", recog->gmmmfcc->f);
#endif
	recog->gmmmfcc->sparea_start = recog->gmmmfcc->f + 1 - recog->jconf->detect.gmm_margin;
	if (recog->gmmmfcc->sparea_start < 0) recog->gmmmfcc->sparea_start = 0;
	gmm->after_trigger = FALSE;
	recog->gmmmfcc->segmented = TRUE;
	break_gmm = TRUE;
      } else {
	/* keep recognition */
      }
    } else {
      /* before trigger, in noise area */
      if (gmm->up_trigger) {
	/* start recognition */
	/* request caller to rewind to the backstep point and
	   re-start with normal search */
	if (recog->gmmmfcc->f + 1 < recog->jconf->detect.gmm_margin) {
	  gmm->rewind_frame = 0;
	} else {
	  gmm->rewind_frame = recog->gmmmfcc->f + 1 - recog->jconf->detect.gmm_margin;
	}
#ifdef GMM_VAD_DEBUG
	printf("GMM_VAD: %d: up trigger, start recognition with %d frame rewind\n", recog->gmmmfcc->f, recog->gmmmfcc->f - gmm->rewind_frame);
#endif
	gmm->want_rewind = TRUE;
	gmm->want_rewind_reprocess = TRUE;
	gmm->after_trigger = TRUE;
	return 0;
      } else {
	/* before trigger, noise continues */

	/* if noise goes more than a certain frame, shrink the noise area
	   to avoid unlimited memory usage */
	if (recog->gmmmfcc->f + 1 > GMM_VAD_AUTOSHRINK_LIMIT) {
	  gmm->want_rewind = TRUE;
	  gmm->want_rewind_reprocess = FALSE;
	  gmm->rewind_frame = recog->gmmmfcc->f + 1 - recog->jconf->detect.gmm_margin;
	  if (debug2_flag) {
	    jlog("DEBUG: GMM_VAD: pause exceeded %d, rewind\n", GMM_VAD_AUTOSHRINK_LIMIT);
	  }
	}

	/* skip recognition processing */
	return 0;
      }
    }
#endif /* GMM_VAD */
  }

  for(p = recog->process_list; p; p = p->next) {
    if (!p->live) continue;
    mfcc = p->am->mfcc;
    if (!mfcc->valid) {
      /* このフレームの処理をスキップ */
      /* skip processing the frame */
      continue;
    }

    /* mfcc-f のフレームについて認識処理(フレーム同期ビーム探索)を進める */
    /* proceed beam search for mfcc->f */
    if (mfcc->f == 0) {
      /* 最初のフレーム: 探索処理を初期化 */
      /* initial frame: initialize search process */
      if (get_back_trellis_init(mfcc->param, p) == FALSE) {
	jlog("ERROR: %02d %s: failed to initialize the 1st pass\n", p->config->id, p->config->name);
	return -1;
      }
    }
    if (mfcc->f > 0 || p->am->hmminfo->multipath) {
      /* 1フレーム探索を進める */
      /* proceed search for 1 frame */
      if (get_back_trellis_proceed(mfcc->f, mfcc->param, p, FALSE) == FALSE) {
	mfcc->segmented = TRUE;
	break_decode = TRUE;
      }
      if (p->config->successive.enabled) {
	if (detect_end_of_segment(p, mfcc->f - 1)) {
	  /* セグメント終了検知: 第1パスここで中断 */
	  mfcc->segmented = TRUE;
	  break_decode = TRUE;
	}
      }
    }
  }

  /* セグメントすべきかどうか最終的な判定を行う.
     デコーダベースVADあるいは spsegment の場合,複数インスタンス間で OR
     を取る.また,GMMなど複数基準がある場合は基準間で AND を取る.*/
  /* determine whether to segment at here
     If multiple segmenter exists, take their AND */
  break_flag = FALSE;
  if (break_decode
#ifdef GMM_VAD
      || (recog->gmm != NULL && break_gmm)
#endif
      ) {
    break_flag = TRUE;
  }

  if (break_flag) {
    /* 探索処理の終了が発生したのでここで認識を終える. 
       最初のフレームから [f-1] 番目までが認識されたことになる
    */
    /* the recognition process tells us to stop recognition, so
       recognition should be terminated here.
       the recognized data are [0..f-1] */

    /* 最終フレームを last_time にセット */
    /* set the last frame to last_time */
    for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
      mfcc->last_time = mfcc->f - 1;
    }

    if (! recog->jconf->decodeopt.segment) {
      /* ショートポーズ以外で切れた場合,残りのサンプルは認識せずに捨てる */
      /* drop rest inputs if segmented by error */
      for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
	mfcc->param->header.samplenum = mfcc->f;
	mfcc->param->samplenum = mfcc->f;
      }
    }

    return 1;
  }

  /* call frame-wise callback for the processing results if any */
#ifdef DETERMINE
  ok_p = FALSE;
  for(p=recog->process_list;p;p=p->next) {
    if (!p->live) continue;
    if (p->have_determine) {
      ok_p = TRUE;
    }
  }
  if (ok_p) callback_exec(CALLBACK_RESULT_PASS1_DETERMINED, recog);
#endif
  ok_p = FALSE;
  for(p=recog->process_list;p;p=p->next) {
    if (!p->live) continue;
    if (p->have_interim) {
      ok_p = TRUE;
    }
  }
  if (ok_p) callback_exec(CALLBACK_RESULT_PASS1_INTERIM, recog);
  
  return 0;
}
Beispiel #25
0
/** 
 * <EN>
 * 
 * </EN>
 * <JA>
 * 
 * </JA>
 * 
 * @param recog 
 * @param ad_check 
 * 
 * @return 2 when input termination requested by recognition process,
 * 1 when segmentation request returned from input module, 0 when end
 * of input returned from input module, -1 on error, -2 when input
 * termination requested by ad_check().
 * 
 */
int
mfcc_go(Recog *recog, int (*ad_check)(Recog *))
{
  RealBeam *r;
  MFCCCalc *mfcc;
  int new_f;
  int ret, ret3;

  r = &(recog->real);

  r->last_is_segmented = FALSE;
  
  while(1/*in_data_vec*/) {

    ret = mfc_module_read(recog->mfcclist, &new_f);

    if (debug2_flag) {
      if (recog->mfcclist->f < new_f) {
	jlog("%d: %d (%d)\n", recog->mfcclist->f, new_f, ret);
      }
    }
 
    /* callback poll */
    if (ad_check != NULL) {
      if ((ret3 = (*(ad_check))(recog)) < 0) {
	if ((ret3 == -1 && recog->mfcclist->f == 0) || ret3 == -2) {
	  return(-2);
	}
      }
    }

    while(recog->mfcclist->f < new_f) {

      recog->mfcclist->valid = TRUE;

#ifdef ENABLE_PLUGIN
      /* call post-process plugin if exist */
      plugin_exec_vector_postprocess(recog->mfcclist->param->parvec[recog->mfcclist->f], recog->mfcclist->param->veclen, recog->mfcclist->f);
#endif

      /* 処理を1フレーム進める */
      /* proceed one frame */
      
      switch(proceed_one_frame(recog)) {
      case -1:			/* error */
	return -1;
      case 0:			/* normal */
	break;
      case 1:			/* segmented by process */
	return 2;
      }

      /* 1フレーム処理が進んだのでポインタを進める */
      /* proceed frame pointer */
      for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
	if (!mfcc->valid) continue;
	mfcc->f++;
      }
    }
    
    /* check if input end */
    switch(ret) {
    case -1: 			/* end of input */
      return 0;
    case -2:			/* error */
      return -1;
    case -3:			/* end of segment request */
      return 1;
    }
  }
  /* 与えられた音声セグメントに対する認識処理が全て終了
     呼び出し元に, 入力を続けるよう伝える */
  /* input segment is fully processed
     tell the caller to continue input */
  return(1);
}
Beispiel #26
0
/** 
 * <EN>
 * @brief  End procedure of the first pass
 *
 * This function finish the first pass, when the input was fully
 * processed to the end.
 *
 * The best path at each recognition process instance will be parsed
 * and stored.  In case of recognition error or input rejection, the
 * error status will be set.
 *
 * </EN>
 * <JA>
 * @brief  第1パスの終了処理
 * 
 * 入力が最後まで処理されて終了したときに,第1パスの認識処理を
 * 終了させる. 
 *
 * 各認識処理インスタンスに対して,その時点での第1パスの最尤単語
 * 系列を格納する. また,認識失敗・入力棄却の時はエラーステータスをそ
 * れぞれセットする.
 * 
 * </JA>
 * 
 * @param recog [in] engine instance
 * 
 * @callgraph
 * @callergraph
 */
void
decode_end(Recog *recog)
{
  MFCCCalc *mfcc;
  int mseclen;
  boolean ok_p;
  RecogProcess *p;
  int last_status;

  for (mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
    mfcc->segmented = FALSE;
  }

  if (recog->gmm != NULL) {
    /* GMM 計算の終了 */
    gmm_end(recog);
  }

#ifdef GMM_VAD
  /* もしトリガがかからないまま入力終了に達したのなら,そのままエラー終了 */
  if (recog->jconf->decodeopt.segment) {
    if (recog->gmm) {
      if (recog->gc->after_trigger == FALSE) {
	for(p=recog->process_list;p;p=p->next) {
	  p->result.status = J_RESULT_STATUS_ONLY_SILENCE;	/* reject by decoding */
	}
	/* ショートポーズセグメンテーションの場合,
	   入力パラメータ分割などの最終処理も行なう */
	/* When short-pause segmentation enabled */
	finalize_segment(recog);
	return;
      }
    }
  }
#endif

  /* 第1パスの最後のフレームの認識処理を行う */
  /* finalize 1st pass */
  for(p=recog->process_list;p;p=p->next) {
    if (!p->live) continue;
#ifdef SPSEGMENT_NAIST
    if (recog->jconf->decodeopt.segment) {
      if (p->pass1.after_trigger == FALSE) continue;
    }
#endif
    mfcc = p->am->mfcc;
    if (mfcc->f > 0) {
      get_back_trellis_end(mfcc->param, p);
    }
  }

  /* 終了処理 */
  for(p=recog->process_list;p;p=p->next) {
    if (!p->live) continue;

    ok_p = TRUE;

    /* check rejection by no input */
    if (ok_p) {
      mfcc = p->am->mfcc;
      /* 入力長がデルタの計算に十分でない場合,入力無しとする. */
      /* if input is short for compute all the delta coeff., terminate here */
      if (mfcc->f == 0) {
	jlog("STAT: no input frame\n");
	last_status = J_RESULT_STATUS_FAIL;
	ok_p = FALSE;
      }
    }

    /* check rejection by input length */
    if (ok_p) {
      if (recog->jconf->reject.rejectshortlen > 0) {
	mseclen = (float)mfcc->param->samplenum * (float)recog->jconf->input.period * (float)recog->jconf->input.frameshift / 10000.0;
	if (mseclen < recog->jconf->reject.rejectshortlen) {
	  last_status = J_RESULT_STATUS_REJECT_SHORT;
	  ok_p = FALSE;
	}
      }
    }

#ifdef POWER_REJECT
    /* check rejection by average power */
    if (ok_p) {
      if (power_reject(recog)) {
	last_status = J_RESULT_STATUS_REJECT_POWER;
	ok_p = FALSE;
      }
    }
#endif

#ifdef SPSEGMENT_NAIST
    /* check rejection non-triggered input segment */
    if (ok_p) {
      if (recog->jconf->decodeopt.segment) {
	if (p->pass1.after_trigger == FALSE) {
	  last_status = J_RESULT_STATUS_ONLY_SILENCE;	/* reject by decoding */
	  ok_p = FALSE;
	}
      }
    }
#endif

    if (ok_p) {
      /* valid input segment, finalize it */
      finalize_1st_pass(p, mfcc->param->samplenum);
    } else {
      /* invalid input segment */
      p->result.status = last_status;
    }
  }
  if (recog->jconf->decodeopt.segment) {
    /* ショートポーズセグメンテーションの場合,
       入力パラメータ分割などの最終処理も行なう */
    /* When short-pause segmentation enabled */
    finalize_segment(recog);
  }
}
Beispiel #27
0
/** 
 * <JA>
 * @brief  第1パス平行認識処理の準備
 *
 * 計算用変数をリセットし,各種データを準備する. 
 * この関数は,ある入力(あるいはセグメント)の認識が
 * 始まる前に呼ばれる. 
 * 
 * </JA>
 * <EN>
 * @brief  Preparation for the on-the-fly 1st pass decoding.
 *
 * Variables are reset and data are prepared for the next input recognition.
 *
 * This function will be called before starting each input (segment).
 * 
 * </EN>
 *
 * @param recog [i/o] engine instance
 *
 * @return TRUE on success. FALSE on failure.
 *
 * @callgraph
 * @callergraph
 * 
 */
boolean
RealTimePipeLinePrepare(Recog *recog)
{
  RealBeam *r;
  PROCESS_AM *am;
  MFCCCalc *mfcc;
#ifdef SPSEGMENT_NAIST
  RecogProcess *p;
#endif

  r = &(recog->real);

  /* 計算用の変数を初期化 */
  /* initialize variables for computation */
  r->windownum = 0;
  /* parameter check */
  for(mfcc = recog->mfcclist; mfcc; mfcc = mfcc->next) {
    /* パラメータ初期化 */
    /* parameter initialization */
    if (recog->jconf->input.speech_input == SP_MFCMODULE) {
      if (mfc_module_set_header(mfcc, recog) == FALSE) return FALSE;
    } else {
      init_param(mfcc);
    }
    /* フレームごとのパラメータベクトル保存の領域を確保 */
    /* あとで必要に応じて伸長される */
    if (param_alloc(mfcc->param, 1, mfcc->param->veclen) == FALSE) {
      j_internal_error("ERROR: segmented: failed to allocate memory for rest param\n");
    }
    /* フレーム数をリセット */
    /* reset frame count */
    mfcc->f = 0;
  }
  /* 準備した param 構造体のデータのパラメータ型を音響モデルとチェックする */
  /* check type coherence between param and hmminfo here */
  if (recog->jconf->input.paramtype_check_flag) {
    for(am=recog->amlist;am;am=am->next) {
      if (!check_param_coherence(am->hmminfo, am->mfcc->param)) {
	jlog("ERROR: input parameter type does not match AM\n");
	return FALSE;
      }
    }
  }

  /* 計算用のワークエリアを準備 */
  /* prepare work area for calculation */
  if (recog->jconf->input.type == INPUT_WAVEFORM) {
    reset_mfcc(recog);
  }
  /* 音響尤度計算用キャッシュを準備 */
  /* prepare cache area for acoustic computation of HMM states and mixtures */
  for(am=recog->amlist;am;am=am->next) {
    outprob_prepare(&(am->hmmwrk), r->maxframelen);
  }

#ifdef BACKEND_VAD
  if (recog->jconf->decodeopt.segment) {
    /* initialize segmentation parameters */
    spsegment_init(recog);
  }
#else
  recog->triggered = FALSE;
#endif

#ifdef DEBUG_VTLN_ALPHA_TEST
  /* store speech */
  recog->speechlen = 0;
#endif

  return TRUE;
}
Beispiel #28
0
static void pki_sign_certificate(EVP_PKEY *keyring, X509 *certificate)
{
	jlog(L_NOTICE, "pki_sign_certificate");

	X509_sign(certificate, keyring, EVP_sha1());
}
Beispiel #29
0
/** 
 * Sub function to Add a dictionary entry line to the word dictionary.
 * 
 * @param buf [i/o] buffer to hold the input string, will be modified in this function
 * @param vnum_p [in] current number of words in @a winfo
 * @param linenum [in] current line number of the input
 * @param winfo [out] pointer to word dictionary to append the data.
 * @param hmminfo [in] HTK %HMM definition data.  if NULL, phonemes are ignored.
 * @param do_conv [in] TRUE if performing triphone conversion
 * @param ok_flag [out] will be set to FALSE if an error occured for this input.
 * 
 * @return FALSE if buf == "DICEND", else TRUE will be returned.
 */
boolean
voca_load_htkdict_line(char *buf, WORD_ID *vnum_p, int linenum, WORD_INFO *winfo, HTK_HMM_INFO *hmminfo, boolean do_conv, boolean *ok_flag)
{
  char *ptmp, *lp = NULL, *p;
  static char cbuf[MAX_HMMNAME_LEN];
  HMM_Logical **tmpwseq;
  int len;
  HMM_Logical *tmplg;
  boolean pok;
  int vnum;

  vnum = *vnum_p;

  if (strmatch(buf, "DICEND")) return FALSE;

  /* allocate temporal work area for the first call */
  if (winfo->work == NULL) {
    winfo->work_num = PHONEMELEN_STEP;
    winfo->work = (void *)mybmalloc2(sizeof(HMM_Logical *) * winfo->work_num, &(winfo->mroot));
  }
  tmpwseq = (HMM_Logical **)winfo->work;

  /* backup whole line for debug output */
  strcpy(bufbak, buf);
  
  /* GrammarEntry */
  if ((ptmp = mystrtok_quote(buf, " \t\n")) == NULL) {
    jlog("Error: voca_load_htkdict: line %d: corrupted data:\n> %s\n", linenum, bufbak);
    winfo->errnum++;
    *ok_flag = FALSE;
    return TRUE;
  }
  winfo->wname[vnum] = strcpy((char *)mybmalloc2(strlen(ptmp)+1, &(winfo->mroot)), ptmp);

  /* just move pointer to next token */
  if ((ptmp = mystrtok_movetonext(NULL, " \t\n")) == NULL) {
    jlog("Error: voca_load_htkdict: line %d: corrupted data:\n> %s\n", linenum, bufbak);
    winfo->errnum++;
    *ok_flag = FALSE;
    return TRUE;
  }
#ifdef CLASS_NGRAM
  winfo->cprob[vnum] = 0.0;	/* prob = 1.0, logprob = 0.0 */
#endif
  
  if (ptmp[0] == '@') {		/* class N-gram prob */
#ifdef CLASS_NGRAM
    /* word probability within the class (for class N-gram) */
    /* format: classname @classprob wordname [output] phoneseq */
    /* classname equals to wname, and wordname will be omitted */
    /* format: @%f (log scale) */
    /* if "@" not found or "@0", it means class == word */
    if ((ptmp = mystrtok(NULL, " \t\n")) == NULL) {
      jlog("Error: voca_load_htkdict: line %d: corrupted data:\n> %s\n", linenum, bufbak);
      winfo->errnum++;
      *ok_flag = FALSE;
      return TRUE;
    }
    if (ptmp[1] == '\0') {	/* space between '@' and figures */
      jlog("Error: voca_load_htkdict: line %d: value after '@' missing, maybe wrong space?\n> %s\n", linenum, bufbak);
      winfo->errnum++;
      *ok_flag = FALSE;
      return TRUE;
    }
    winfo->cprob[vnum] = atof(&(ptmp[1]));
    if (winfo->cprob[vnum] != 0.0) winfo->cwnum++;
    /* read next word entry (just skip them) */
    if ((ptmp = mystrtok(NULL, " \t\n")) == NULL) {
      jlog("Error: voca_load_htkdict: line %d: corrupted data:\n> %s\n", linenum,bufbak);
      winfo->errnum++;
      *ok_flag = FALSE;
      return TRUE;
    }
    /* move to the next word entry */
    if ((ptmp = mystrtok_movetonext(NULL, " \t\n")) == NULL) {
      jlog("Error: voca_load_htkdict: line %d: corrupted data:\n> %s\n", linenum, bufbak);
      winfo->errnum++;
      *ok_flag = FALSE;
      return TRUE;
    }
#else  /* ~CLASS_NGRAM */
    jlog("Error: voca_load_htkdict: line %d: cannot handle in-class word probability\n> %s\n", linenum, ptmp, bufbak);
    winfo->errnum++;
    *ok_flag = FALSE;
    return TRUE;
#endif /* CLASS_NGRAM */
  }

  /* OutputString */
  switch(ptmp[0]) {
  case '[':			/* not transparent word */
    winfo->is_transparent[vnum] = FALSE;
    ptmp = mystrtok_quotation(NULL, " \t\n", '[', ']', 0);
    break;
  case '{':			/* transparent word */
    winfo->is_transparent[vnum] = TRUE;
    ptmp = mystrtok_quotation(NULL, " \t\n", '{', '}', 0);
    break;
  default:
#if 1
    /* ALLOW no entry for output */
    /* same as wname is used */
    winfo->is_transparent[vnum] = FALSE;
    ptmp = winfo->wname[vnum];
#else
    /* error */
    jlog("Error: voca_load_htkdict: line %d: missing output string??\n> %s\n", linenum, bufbak);
    winfo->errnum++;
    *ok_flag = FALSE;
    return TRUE;
#endif
  }
  if (ptmp == NULL) {
    jlog("Error: voca_load_htkdict: line %d: corrupted data:\n> %s\n", linenum, bufbak);
    winfo->errnum++;
    *ok_flag = FALSE;
    return TRUE;
  }
  winfo->woutput[vnum] = strcpy((char *)mybmalloc2(strlen(ptmp)+1, &(winfo->mroot)), ptmp);
    
  /* phoneme sequence */
  if (hmminfo == NULL) {
    /* don't read */
    winfo->wseq[vnum] = NULL;
    winfo->wlen[vnum] = 0;
  } else {

    /* store converted phone sequence to temporal bufffer */
    len = 0;
      
    if (do_conv) {
      /* convert phoneme to triphone expression (word-internal) */
      cycle_triphone(NULL);
      if ((lp = mystrtok(NULL, " \t\n")) == NULL) {
	jlog("Error: voca_load_htkdict: line %d: word %s has no phoneme:\n> %s\n", linenum, winfo->wname[vnum], bufbak);
	winfo->errnum++;
	*ok_flag = FALSE;
	return TRUE;
      }
      if (strlen(lp) >= MAX_HMMNAME_LEN) {
	jlog("Error: voca_load_htkdict: line %d: too long phone name: %s\n", linenum, lp);
	winfo->errnum++;
	*ok_flag = FALSE;
	return TRUE;
      }
      cycle_triphone(lp);
    }

    pok = TRUE;
    for (;;) {
      if (do_conv) {
/*	if (lp != NULL) jlog(" %d%s",len,lp);*/
	if (lp != NULL) lp = mystrtok(NULL, " \t\n");
	if (lp != NULL) {
	  if (strlen(lp) >= MAX_HMMNAME_LEN) {
	    jlog("Error: voca_load_htkdict: line %d: too long phone name: %s\n", linenum, lp);
	    winfo->errnum++;
	    *ok_flag = FALSE;
	    return TRUE;
	  }
	  p = cycle_triphone(lp);
	}
	else p = cycle_triphone_flush();
      } else {
	p = mystrtok(NULL, " \t\n");
      }
      if (p == NULL) break;

      /* both defined/pseudo phone is allowed */
      tmplg = htk_hmmdata_lookup_logical(hmminfo, p);
      if (tmplg == NULL) {
	/* not found */
	if (do_conv) {
	  /* both defined or pseudo phone are not found */
	  if (len == 0 && lp == NULL) {
	    jlog("Error: voca_load_htkdict: line %d: triphone \"*-%s+*\" or monophone \"%s\" not found\n", linenum, p, p);
	    snprintf(cbuf,MAX_HMMNAME_LEN,"*-%s+* or monophone %s", p, p);
	  } else if (len == 0) {
	    jlog("Error: voca_load_htkdict: line %d: triphone \"*-%s\" or biphone \"%s\" not found\n", linenum, p, p);
	    snprintf(cbuf,MAX_HMMNAME_LEN,"*-%s or biphone %s", p, p);
	  } else if (lp == NULL) {
	    jlog("Error: voca_load_htkdict: line %d: triphone \"%s+*\" or biphone \"%s\" not found\n", linenum, p, p);
	    snprintf(cbuf,MAX_HMMNAME_LEN,"%s+* or biphone %s", p, p);
	  } else {
	    jlog("Error: voca_load_htkdict: line %d: triphone \"%s\" not found\n", linenum, p);
	    snprintf(cbuf,MAX_HMMNAME_LEN,"%s", p);
	  }
	} else {
	  jlog("Error: voca_load_htkdict: line %d: phone \"%s\" not found\n", linenum, p);
	  snprintf(cbuf, MAX_HMMNAME_LEN, "%s", p);
	}
	add_to_error(winfo, cbuf);
	pok = FALSE;
      } else {
	/* found */
	if (len >= winfo->work_num) {
	  /* expand wseq area by PHONEMELEN_STEP */
	  winfo->work_num += PHONEMELEN_STEP;
	  winfo->work = (void *)mybmalloc2(sizeof(HMM_Logical *) * winfo->work_num, &(winfo->mroot));
	  memcpy(winfo->work, tmpwseq, sizeof(HMM_Logical *) * (winfo->work_num - PHONEMELEN_STEP));
	  tmpwseq = (HMM_Logical **)winfo->work;
	}
	/* store to temporal buffer */
	tmpwseq[len] = tmplg;
      }
      len++;
    }
    if (!pok) {			/* error in phoneme */
      jlog("Error: voca_load_htkdict: the line content was: %s\n", bufbak);
      winfo->errnum++;
      *ok_flag = FALSE;
      return TRUE;
    }
    if (len == 0) {
      jlog("Error: voca_load_htkdict: line %d: no phone specified:\n> %s\n", linenum, bufbak);
      winfo->errnum++;
      *ok_flag = FALSE;
      return TRUE;
    }
    /* store to winfo */
    winfo->wseq[vnum] = (HMM_Logical **)mybmalloc2(sizeof(HMM_Logical *) * len, &(winfo->mroot));
    memcpy(winfo->wseq[vnum], tmpwseq, sizeof(HMM_Logical *) * len);
    winfo->wlen[vnum] = len;
  }

  vnum++;

  *vnum_p = vnum;
  
  return(TRUE);
}
/** 
 * <JA>
 * @brief  単語辞書をファイルから読み込んでセットアップする. 
 *
 * 辞書上のモノフォン表記からトライフォンへの計算は init_voca() で
 * 読み込み時に行われる. このため,辞書読み込み時には,認識で使用する
 * 予定のHMM情報を与える必要がある. 
 *
 * N-gram 使用時は,文頭無音単語およぶ文末無音単語をここで設定する. 
 * また,"-iwspword" 指定時は,ポーズ単語を辞書の最後に挿入する. 
 * 
 * </JA>
 * <EN>
 * @brief  Read in word dictionary from a file and setup for recognition.
 *
 * Monophone-to-triphone conversion will be performed inside init_voca().
 * So, an HMM definition data that will be used with the LM should also be
 * specified as an argument.
 * 
 * When reading dictionary for N-gram, sentence head silence word and
 * tail silence word will be determined in this function.  Also,
 * when an option "-iwspword" is specified, this will insert a pause
 * word at the last of the given dictionary.
 * 
 * </EN>
 *
 * @param lmconf [in] LM configuration variables
 * @param hmminfo [in] HMM definition of each phone in dictionary, for
 * phone checking and monophone-to-triphone conversion.
 *
 * @return the newly created word dictionary structure, or NULL on failure.
 * 
 */
static WORD_INFO *
initialize_dict(JCONF_LM *lmconf, HTK_HMM_INFO *hmminfo)
{
  WORD_INFO *winfo;
  JCONF_LM_NAMELIST *nl;
  char buf[MAXLINELEN];
  int n;

  /* allocate new word dictionary */
  winfo = word_info_new();
  /* read in dictinary from file */
  if ( ! 
#ifdef MONOTREE
      /* leave winfo monophone for 1st pass lexicon tree */
       init_voca(winfo, lmconf->dictfilename, hmminfo, TRUE, lmconf->forcedict_flag)
#else 
       init_voca(winfo, lmconf->dictfilename, hmminfo, FALSE, lmconf->forcedict_flag)
#endif
       ) {
    jlog("ERROR: m_fusion: failed to read dictionary, terminated\n");
    word_info_free(winfo);
    return NULL;
  }

  /* load additional entries */
  for (nl = lmconf->additional_dict_files; nl; nl=nl->next) {
    FILE *fp;
    if ((fp = fopen(nl->name, "rb")) == NULL) {
      jlog("ERROR: m_fusion: failed to open %s\n",nl->name);
      word_info_free(winfo);
      return NULL;
    }
    n = winfo->num;
    while (getl_fp(buf, MAXLINELEN, fp) != NULL) {
      if (voca_load_line(buf, winfo, hmminfo) == FALSE) break;
    }
    if (voca_load_end(winfo) == FALSE) {
      if (lmconf->forcedict_flag) {
	jlog("Warning: m_fusion: the error words above are ignored\n");
      } else {
	jlog("ERROR: m_fusion: error in reading dictionary %s\n", nl->name);
	fclose(fp);
	word_info_free(winfo);
	return NULL;
      }
    }
    if (fclose(fp) == -1) {
      jlog("ERROR: m_fusion: failed to close %s\n", nl->name);
      word_info_free(winfo);
      return NULL;
    }
    jlog("STAT: + additional dictionary: %s (%d words)\n", nl->name, winfo->num - n);
  }
  n = winfo->num;
  for (nl = lmconf->additional_dict_entries; nl; nl=nl->next) {
    if (voca_load_line(nl->name, winfo, hmminfo) == FALSE) {
      jlog("ERROR: m_fusion: failed to set entry: %s\n", nl->name);
    }
  }
  if (lmconf->additional_dict_entries) {
    if (voca_load_end(winfo) == FALSE) {
      jlog("ERROR: m_fusion: failed to read additinoal word entry\n");
      word_info_free(winfo);
      return NULL;
    }
    jlog("STAT: + additional entries: %d words\n", winfo->num - n);
  }

  if (lmconf->lmtype == LM_PROB) {
    /* if necessary, append a IW-sp word to the dict if "-iwspword" specified */
    if (lmconf->enable_iwspword) {
      if (
#ifdef MONOTREE
	  voca_append_htkdict(lmconf->iwspentry, winfo, hmminfo, TRUE)
#else 
	  voca_append_htkdict(lmconf->iwspentry, winfo, hmminfo, FALSE)
#endif
	  == FALSE) {
	jlog("ERROR: m_fusion: failed to make IW-sp word entry \"%s\"\n", lmconf->iwspentry);
	word_info_free(winfo);
	return NULL;
      } else {
	jlog("STAT: 1 IW-sp word entry added\n");
      }
    }
    /* set {head,tail}_silwid */
    winfo->head_silwid = voca_lookup_wid(lmconf->head_silname, winfo);
    if (winfo->head_silwid == WORD_INVALID) { /* not exist */
      jlog("ERROR: m_fusion: head sil word \"%s\" not exist in voca\n", lmconf->head_silname);
      word_info_free(winfo);
      return NULL;
    }
    winfo->tail_silwid = voca_lookup_wid(lmconf->tail_silname, winfo);
    if (winfo->tail_silwid == WORD_INVALID) { /* not exist */
      jlog("ERROR: m_fusion: tail sil word \"%s\" not exist in voca\n", lmconf->tail_silname);
      word_info_free(winfo);
      return NULL;
    }
  }
  
  return(winfo);
  
}