/**
* @file gms_gprune.c
*
*
* @brief Gaussian Mixture Selection のための Gaussian pruning を用いたモノフォンHMMの計算
*
*
*
* @brief Calculate the GMS monophone %HMM for Gaussian Mixture Selection using Gaussian pruning
*
*
* @author Akinobu LEE
* @date Thu Feb 17 15:05:08 2005
*
* $Revision: 1.6 $
*
*/
/*
* Copyright (c) 1991-2012 Kawahara Lab., Kyoto University
* Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
* Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology
* All rights reserved
*/
#include
#include
#include
#include
#include
/* activate experimental methods */
#define GS_MAX_PROB ///< Compute only max for GS states
#define LAST_BEST ///< Compute last best Gaussians first
/************************************************************************/
/**
* Initialization of GMS %HMM likelihood computation.
*
* @param wrk [i/o] HMM computation work area
*
*/
void
gms_gprune_init(HMMWork *wrk)
{
int i;
wrk->gms_last_max_id_list = (int **)mymalloc(sizeof(int *) * wrk->gsset_num);
for(i=0;igsset_num;i++) {
wrk->gms_last_max_id_list[i] = (int *)mymalloc(sizeof(int) * wrk->OP_nstream);
}
}
/**
* Prepare GMS %HMM computation for the next speech input.
*
* @param wrk [i/o] HMM computation work area
*
*/
void
gms_gprune_prepare(HMMWork *wrk)
{
int i, j;
for(i=0;igsset_num;i++) {
for(j=0;jOP_nstream;j++) {
wrk->gms_last_max_id_list[i][j] = -1;
}
}
}
/**
* Free GMS related work area.
*
* @param wrk [i/o] HMM computation work area
*
*/
void
gms_gprune_free(HMMWork *wrk)
{
int i;
for(i=0;igsset_num;i++) free(wrk->gms_last_max_id_list[i]);
free(wrk->gms_last_max_id_list);
}
/**********************************************************************/
/* LAST_BEST ... compute the maximum component in last frame first */
/**
* Compute only max by safe pruning
*
* @param wrk [i/o] HMM computation work area
* @param binfo [in] Gaussian density
* @param thres [in] constant pruning threshold
*
* @return the computed likelihood.
*/
static LOGPROB
calc_contprob_with_safe_pruning(HMMWork *wrk, HTK_HMM_Dens *binfo, LOGPROB thres)
{
LOGPROB tmp, x;
VECT *mean;
VECT *var;
LOGPROB fthres = thres * (-2.0);
VECT *vec = wrk->OP_vec;
short veclen = wrk->OP_veclen;
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);
}
#ifdef LAST_BEST
/**
* Compute log output likelihood of a state. Only maximum Gaussian will be
* computed.
*
* @param wrk [i/o] HMM computation work area
* @param stateinfo [in] %HMM state to compute
* @param last_maxi [in] the mixture id that got the maximum value at the previous frame, or -1 if not exist.
* @param maxi_ret [out] tue mixture id that get the maximum value at this call.
*
* @return the log likelihood.
*/
static LOGPROB
compute_g_max(HMMWork *wrk, HTK_HMM_State *stateinfo, int *last_maxi)
{
int i, maxi;
LOGPROB prob;
LOGPROB maxprob = LOG_ZERO;
int s;
PROB stream_weight;
LOGPROB logprobsum;
logprobsum = 0.0;
for(s=0;sOP_nstream;s++) {
/* set stream weight */
if (stateinfo->w) stream_weight = stateinfo->w->weight[s];
else stream_weight = 1.0;
/* setup storage pointer for this mixture pdf */
wrk->OP_vec = wrk->OP_vec_stream[s];
wrk->OP_veclen = wrk->OP_veclen_stream[s];
if (last_maxi[s] != -1) {
maxi = last_maxi[s];
maxprob = calc_contprob_with_safe_pruning(wrk, stateinfo->pdf[s]->b[maxi], LOG_ZERO);
for (i = stateinfo->pdf[s]->mix_num - 1; i >= 0; i--) {
if (i == last_maxi[s]) continue;
prob = calc_contprob_with_safe_pruning(wrk, stateinfo->pdf[s]->b[i], maxprob);
if (prob > maxprob) {
maxprob = prob;
maxi = i;
}
}
last_maxi[s] = maxi;
} else {
maxi = stateinfo->pdf[s]->mix_num - 1;
maxprob = calc_contprob_with_safe_pruning(wrk, stateinfo->pdf[s]->b[maxi], LOG_ZERO);
for (i = maxi - 1; i >= 0; i--) {
prob = calc_contprob_with_safe_pruning(wrk, stateinfo->pdf[s]->b[i], maxprob);
if (prob > maxprob) {
maxprob = prob;
maxi = i;
}
}
last_maxi[s] = maxi;
}
logprobsum += (maxprob + stateinfo->pdf[s]->bweight[maxi]) * stream_weight;
}
return (logprobsum * INV_LOG_TEN);
}
#else /* ~LAST_BEST */
/**
* Compute log output likelihood of a state. Only maximum Gaussian will be
* computed.
*
* @param wrk [i/o] HMM computation work area
* @param stateinfo [in] %HMM state to compute
*
* @return the log likelihood.
*/
static LOGPROB
compute_g_max(HMMWork *wrk, HTK_HMM_State *stateinfo)
{
int i, maxi;
LOGPROB prob;
LOGPROB maxprob = LOG_ZERO;
int s;
PROB stream_weight;
LOGPROB logprob, logprobsum;
logprobsum = 0.0;
for(s=0;sOP_nstream;s++) {
/* set stream weight */
if (stateinfo->w) stream_weight = stateinfo->w->weight[s];
else stream_weight = 1.0;
/* setup storage pointer for this mixture pdf */
wrk->OP_vec = wrk->OP_vec_stream[s];
wrk->OP_veclen = wrk->OP_veclen_stream[s];
i = maxi = stateinfo->pdf[s]->mix_num - 1;
for (; i >= 0; i--) {
prob = calc_contprob_with_safe_pruning(wrk, stateinfo->pdf[s]->b[i], maxprob);
if (prob > maxprob) {
maxprob = prob;
maxi = i;
}
}
logprobsum += (maxprob + stateinfo->pdf[s]->bweight[maxi]) * stream_weight;
}
return (logprobsum * INV_LOG_TEN);
}
#endif
/**********************************************************************/
/* main function: compute all gshmm scores */
/* *** assume to be called for sequencial frame (using last result) */
/**
* Main function to compute all the GMS %HMM states in a frame
* with the input vectore specified by OP_vec. This function assumes
* that this will be called for sequencial frame, since it utilizes the
* result of previous frame for faster pruning.
*
* @param wrk [i/o] HMM computation work area
*
*/
void
compute_gs_scores(HMMWork *wrk)
{
int i;
for (i=0;igsset_num;i++) {
#ifdef GS_MAX_PROB
#ifdef LAST_BEST
/* compute only the maximum with pruning (last best first) */
wrk->t_fs[i] = compute_g_max(wrk, wrk->gsset[i].state, wrk->gms_last_max_id_list[i]);
#else
wrk->t_fs[i] = compute_g_max(wrk, wrk->gsset[i].state);
#endif /* LAST_BEST */
#else
/* compute all mixture */
wrk->t_fs[i] = compute_g_base(wrk, wrk->gsset[i].state);
#endif
/*printf("%d:%s:%f\n",i,gsset[i].book->name,t_fs[i]);*/
}
}