⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gmm.c

📁 julius version 4.12.about sound recognition.
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file   gmm.c *  * <JA> * @brief  GMM による掐蜗逮笛およびVAD * * Gaussian Mixture Model (GMM) が弹瓢箕に回年された眷圭·Julius/Julian は * 掐蜗券厦に滦してフレ〖ムごとにスコアを纷换し·その芜姥スコアを换叫する.  * これはGMMに答づく掐蜗不兰の券厦浮沮および逮笛に脱いられる. 悸狠の纷换は * 妈1パスの千急借妄と事乖してリアルタイムに乖なわれ·妈1パス姜位と票箕に * 冯蔡が叫蜗される.  * * GMMのスコア纷换には Gaussian pruning の safe algorithm が脱いられ· * 称フレ〖ムにおいて惧疤 N 改だけが赖しく评られるように纷换される.  * ただし奶撅の千急脱不读モデルの眷圭と佰なり·木涟フレ〖ムの界疤攫鼠は * 脱いていない.  * * GMM_VAD 年盗箕は·惧淡の掐蜗逮笛に裁えて·short-pause segmentation と * 票じ先寥にを脱いた VAD が乖われる.  * </JA> *  * <EN> * @brief  Input rejection and VAD using GMM * * When a Gaussian Mixture Model (GMM) is specified on startup, Julius/Julian * will compute the frame-wise likelihoods of each GMM for given inputs, * and produces the accumulated scores for each.  Then the input rejection is * determined from the value.  Actually, the recognition will be computed * on-line concurrently with the 1st pass, and the result will be got as * soon as the 1st pass ends. * * Gaussian pruning is performed using the safe algorithm in the computation * of GMM scores.  In each frame, pruning will be done to fully compute only * the top N Gaussians.  The algorithm is slightly simpler than AM computation, * i.e. the score order of the previous frame is not used here. * * When GMM_VAD is defined, a GMM-based VAD will be enabled in addition to * the input rejection, using the scheme of short-pause segmentation. * </EN> *  * @author Akinobu LEE * @date   Tue Mar 15 05:14:10 2005 * * $Revision: 1.4 $ *  *//* * Copyright (c) 2003-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2007 Julius project team, Nagoya Institute of Technology * All rights reserved */#include <julius/julius.h>#undef MES/**  * <JA> * Gaussianのスコアを纷换貉みGaussianリストのどの疤弥に赁掐すべきかを手す.  * * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param score [in] 赁掐したいスコア * @param len [in] 附哼のリストの墓さ *  * @return リスト柒の赁掐疤弥 * </JA> * <EN> * Return insertion point where a computed Gaussian score should be * inserted in current list of computed Gaussians. * * @param gc [i/o] work area for GMM calculation * @param score [in] a score to be inserted * @param len [in] current length of the list *  * @return index to insert the value at the list. * </EN> */static intgmm_find_insert_point(GMMCalc *gc, LOGPROB score, int len){  /* binary search on score */  int left = 0;  int right = len - 1;  int mid;  while (left < right) {    mid = (left + right) / 2;    if (gc->OP_calced_score[mid] > score) {      left = mid + 1;    } else {      right = mid;    }  }  return(left);}/**  * <JA> * あるGaussianの纷换冯蔡を纷换貉みGaussianリストに呈羌する.  *  * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param id [in] Gaussian の GMM 柒での戎规 * @param score [in] その Gaussian の纷换された不读锑刨 * @param len [in] 附哼のリストの墓さ∈附哼呈羌されている Gaussian の眶∷ *  * @return 呈羌稿のリストの墓さ.  * </JA> * <EN> * Store a Gaussian likelihood to the list of computed Gaussians. *  * @param gc [i/o] work area for GMM calculation * @param id [in] id of a Gaussian in the GMM to be stored * @param score [in] the likelihood of the Gaussian to be stored * @param len [in] current list length (= current number of Gaussians in cache) *  * @return the current length of list after the storing. * </EN> */static intgmm_cache_push(GMMCalc *gc, int id, LOGPROB score, int len){  int insertp;  if (len == 0) {               /* first one */    gc->OP_calced_score[0] = score;    gc->OP_calced_id[0] = id;    return(1);  }  if (gc->OP_calced_score[len-1] >= score) { /* bottom */    if (len < gc->OP_gprune_num) {          /* append to bottom */      gc->OP_calced_score[len] = score;      gc->OP_calced_id[len] = id;      len++;    }    return len;  }  if (gc->OP_calced_score[0] < score) {    insertp = 0;  } else {    insertp = gmm_find_insert_point(gc, score, len);  }  if (len < gc->OP_gprune_num) {    memmove(&(gc->OP_calced_score[insertp+1]), &(gc->OP_calced_score[insertp]), sizeof(LOGPROB)*(len - insertp));    memmove(&(gc->OP_calced_id[insertp+1]), &(gc->OP_calced_id[insertp]), sizeof(int)*(len - insertp));      } else if (insertp < len - 1) {    memmove(&(gc->OP_calced_score[insertp+1]), &(gc->OP_calced_score[insertp]), sizeof(LOGPROB)*(len - insertp - 1));    memmove(&(gc->OP_calced_id[insertp+1]), &(gc->OP_calced_id[insertp]), sizeof(int)*(len - insertp - 1));  }  gc->OP_calced_score[insertp] = score;  gc->OP_calced_id[insertp] = id;  if (len < gc->OP_gprune_num) len++;  return(len);}/**  * <JA> * 附哼のフレ〖ムの掐蜗ベクトルに滦する Gaussian の叫蜗澄唯を纷换する.  * Gaussian pruning は乖なわない.  *  * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param binfo [in] Gaussian *  * @return 叫蜗澄唯の滦眶猛 * </JA> * <EN> * Compute an output probability of a Gaussian for the input vector of * current frame.  No Gaussian pruning is performed in this function. *  * @param gc [i/o] work area for GMM calculation * @param binfo [in] Gaussian *  * @return the log output probability. * </EN> */static LOGPROBgmm_compute_g_base(GMMCalc *gc, HTK_HMM_Dens *binfo){  VECT tmp, x;  VECT *mean;  VECT *var;  VECT *vec = gc->OP_vec;  short veclen = gc->OP_veclen;  if (binfo == NULL) return(LOG_ZERO);  mean = binfo->mean;  var = binfo->var->vec;  tmp = 0.0;  for (; veclen > 0; veclen--) {    x = *(vec++) - *(mean++);    tmp += x * x * *(var++);  }  return((tmp + binfo->gconst) * -0.5);}/**  * <JA> * 附哼のフレ〖ムの掐蜗ベクトルに滦する Gaussian の叫蜗澄唯を纷换する.  * 纷换箕には盖年しきい猛による safe pruning を乖なう.  *  * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param binfo [in] Gaussian * @param thres [in] safe pruning のための晦储りしきい猛 *  * @return 叫蜗澄唯の滦眶猛 * </JA> * <EN> * Compute an output probability of a Gaussian for the input vector of * current frame.  Safe pruning is performed in this function. *  * @param gc [i/o] work area for GMM calculation * @param binfo [in] Gaussian * @param thres [in] pruning threshold for safe pruning *  * @return the log output probability. * </EN> */static LOGPROBgmm_compute_g_safe(GMMCalc *gc, HTK_HMM_Dens *binfo, LOGPROB thres){  VECT tmp, x;  VECT *mean;  VECT *var;  VECT *vec = gc->OP_vec;  short veclen = gc->OP_veclen;  VECT fthres = thres * (-2.0);  if (binfo == NULL) return(LOG_ZERO);  mean = binfo->mean;  var = binfo->var->vec;  tmp = binfo->gconst;  for (; veclen > 0; veclen--) {    x = *(vec++) - *(mean++);    tmp += x * x * *(var++);    if (tmp > fthres)  return LOG_ZERO;  }  return(tmp * -0.5);}/**  * <JA> * GMM纷换における Gaussian pruning のためのワ〖クエリアを澄瘦する *  * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param hmminfo [in] HMM 菇陇挛 * @param prune_num [in] Gaussian pruning において纷换する惧疤ガウス尸邵眶 * </JA> * <EN> * Allocate work area for Gaussian pruning for GMM calculation. *  * @param gc [i/o] work area for GMM calculation * @param hmminfo [in] HMM structure * @param prune_num [in] number of top Gaussians to be computed at the pruning * </EN> */static voidgmm_gprune_safe_init(GMMCalc *gc, HTK_HMM_INFO *hmminfo, int prune_num){  /* store the pruning num to local area */  gc->OP_gprune_num = prune_num;  /* maximum Gaussian set size = maximum mixture size * nstream */  gc->OP_calced_maxnum = hmminfo->maxmixturenum * gc->OP_nstream;  /* allocate memory for storing list of currently computed Gaussian in a frame */  gc->OP_calced_score = (LOGPROB *)mymalloc(sizeof(LOGPROB) * gc->OP_calced_maxnum);  gc->OP_calced_id = (int *)mymalloc(sizeof(int) * gc->OP_calced_maxnum);}/**  * <JA> * @brief  ガウス尸邵礁圭柒の称ガウス尸邵の附フレ〖ムに滦する叫蜗澄唯を纷换する.  * * Gaussian pruning により·悸狠には惧疤 N 改のみを瘦沮する晦储りが乖なわれ· * スコアの你いガウス尸邵は纷换されない.  * * 纷换冯蔡は纷换貉みGaussianリスト (OP_calced_score, OP_calced_id) に * 呈羌される.  *  * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param g [in] ガウス尸邵礁圭 * @param gnum [in] @a g の墓さ * </JA> * <EN> * @brief  Compute scores for a set of Gaussians with Gaussian pruning for * the current frame. * * Gaussian pruning will be performed to guarantee only the top N Gaussians * to be fully computed.  The results will be stored in the list of * computed Gaussians in OP_calced_score and OP_calced_id. *  * @param gc [i/o] work area for GMM calculation * @param g [in] set of Gaussians * @param gnum [in] length of @a g * </EN> */static voidgmm_gprune_safe(GMMCalc *gc, HTK_HMM_Dens **g, int gnum){  int i, num = 0;  LOGPROB score, thres;  thres = LOG_ZERO;  for (i = 0; i < gnum; i++) {    if (num < gc->OP_gprune_num) {      score = gmm_compute_g_base(gc, g[i]);    } else {      score = gmm_compute_g_safe(gc, g[i], thres);      if (score <= thres) continue;    }    num = gmm_cache_push(gc, i, score, num);    thres = gc->OP_calced_score[num-1];  }  gc->OP_calced_num = num;}/**  * <JA> * あるGMM觉轮の附フレ〖ムに滦する叫蜗澄唯を纷换する.  *  * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param state [in] GMM 觉轮 *  * @return 叫蜗澄唯の滦眶スコア * </JA> * <EN> * Compute the output probability of a GMM state for the current frame. *  * @param gc [i/o] work area for GMM calculation * @param state [in] GMM state *  * @return the log probability. * </EN> */static LOGPROBgmm_calc_mix(GMMCalc *gc, HTK_HMM_State *state){  int i;  LOGPROB logprob, logprobsum;  int s;  PROB stream_weight;  /* compute Gaussian set */  logprobsum = 0.0;  for(s=0;s<gc->OP_nstream;s++) {    /* set stream weight */    if (state->w) stream_weight = state->w->weight[s];    else stream_weight = 1.0;    /* setup storage pointer for this mixture pdf */    gc->OP_vec = gc->OP_vec_stream[s];    gc->OP_veclen = gc->OP_veclen_stream[s];    /* compute output probabilities */    gmm_gprune_safe(gc, state->pdf[s]->b, state->pdf[s]->mix_num);    /* computed Gaussians will be set in:       score ... OP_calced_score[0..OP_calced_num]       id    ... OP_calced_id[0..OP_calced_num] */  /* sum */    for(i=0;i<gc->OP_calced_num;i++) {      gc->OP_calced_score[i] += state->pdf[s]->bweight[gc->OP_calced_id[i]];    }    /* add log probs */    logprob = addlog_array(gc->OP_calced_score, gc->OP_calced_num);    /* if outprob of a stream is zero, skip this stream */    if (logprob <= LOG_ZERO) continue;    /* sum all the obtained mixture scores */    logprobsum += logprob * stream_weight;  }  if (logprobsum == 0.0) return(LOG_ZERO); /* no valid stream */  if (logprobsum <= LOG_ZERO) return(LOG_ZERO);	/* lowest == LOG_ZERO */  return (logprob * INV_LOG_TEN);}/**  * <JA> * 掐蜗の回年フレ〖ムにおけるGMM觉轮のスコアを滇めるメイン簇眶.  *  * @param gc [i/o] GMM纷换脱ワ〖クエリア * @param t [in] 纷换するフレ〖ム * @param stateinfo [in] GMM觉轮 * @param param [in] 掐蜗ベクトル废误 *  * @return 叫蜗澄唯の滦眶スコア * </JA> * <EN> * Main function to compute the output probability of a GMM state for * the specified input frame. *  * @param gc [i/o] work area for GMM calculation * @param t [in] time frame on which the output probability should be computed * @param stateinfo [in] GMM state * @param param [in] input vector sequence *  * @return the log output probability. * </EN> */static LOGPROBoutprob_state_nocache(GMMCalc *gc, int t, HTK_HMM_State *stateinfo, HTK_Param *param){  int d, i;  /* set global values for outprob functions to access them */  for(d=0,i=0;i<gc->OP_nstream;i++) {    gc->OP_vec_stream[i] = &(param->parvec[t][d]);    d += gc->OP_veclen_stream[i];  }  return(gmm_calc_mix(gc, stateinfo));}/************************************************************************//* global functions *//**  * <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 *  */booleangmm_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) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -