Julius 4.2
libsent/src/phmm/calc_tied_mix.c
説明を見る。
00001 
00028 /*
00029  * Copyright (c) 1991-2011 Kawahara Lab., Kyoto University
00030  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00031  * Copyright (c) 2005-2011 Julius project team, Nagoya Institute of Technology
00032  * All rights reserved
00033  */
00034 
00035 #include <sent/stddefs.h>
00036 #include <sent/speech.h>
00037 #include <sent/htk_hmm.h>
00038 #include <sent/htk_param.h>
00039 #include <sent/hmm.h>
00040 #include <sent/hmm_calc.h>
00041 
00042 
00050 boolean
00051 calc_tied_mix_init(HMMWork *wrk)
00052 {
00053   wrk->mixture_cache = NULL;
00054   wrk->mixture_cache_num = NULL;
00055   wrk->tmix_allocframenum = 0;
00056   wrk->mroot = NULL;
00057   wrk->tmix_last_id = (int *)mymalloc(sizeof(int) * wrk->OP_hmminfo->maxmixturenum * wrk->OP_nstream);
00058   return TRUE;
00059 }
00060 
00069 boolean
00070 calc_tied_mix_prepare(HMMWork *wrk, int framenum)
00071 {
00072   int bid, t;
00073 
00074   /* clear */
00075   for(t=0;t<wrk->tmix_allocframenum;t++) {
00076     for(bid=0;bid<wrk->OP_hmminfo->codebooknum;bid++) {
00077       wrk->mixture_cache_num[t][bid] = 0;
00078     }
00079   }
00080 
00081   return TRUE;
00082 }
00083 
00090 static void
00091 calc_tied_mix_extend(HMMWork *wrk, int reqframe)
00092 {
00093   int newnum;
00094   int bid, t, size;
00095   
00096   /* if enough length are already allocated, return immediately */
00097   if (reqframe < wrk->tmix_allocframenum) return;
00098 
00099   /* allocate per certain period */
00100   newnum = reqframe + 1;
00101   if (newnum < wrk->tmix_allocframenum + OUTPROB_CACHE_PERIOD)
00102     newnum = wrk->tmix_allocframenum + OUTPROB_CACHE_PERIOD;
00103 
00104   if (wrk->mixture_cache == NULL) {
00105     wrk->mixture_cache = (MIXCACHE ***)mymalloc(sizeof(MIXCACHE **) * newnum);
00106     wrk->mixture_cache_num = (short **)mymalloc(sizeof(short *) * newnum);
00107   } else {
00108     wrk->mixture_cache = (MIXCACHE ***)myrealloc(wrk->mixture_cache, sizeof(MIXCACHE **) * newnum);
00109     wrk->mixture_cache_num = (short **)myrealloc(wrk->mixture_cache_num, sizeof(short *) * newnum);
00110   }
00111 
00112   size = wrk->OP_gprune_num * wrk->OP_hmminfo->codebooknum;
00113 
00114   for(t = wrk->tmix_allocframenum; t < newnum; t++) {
00115     wrk->mixture_cache[t] = (MIXCACHE **)mybmalloc2(sizeof(MIXCACHE *) * wrk->OP_hmminfo->codebooknum, &(wrk->mroot));
00116     wrk->mixture_cache_num[t] = (short *)mybmalloc2(sizeof(short) * wrk->OP_hmminfo->codebooknum, &(wrk->mroot));
00117     wrk->mixture_cache[t][0] = (MIXCACHE *)mybmalloc2(sizeof(MIXCACHE) * size, &(wrk->mroot));
00118     for(bid=1;bid<wrk->OP_hmminfo->codebooknum;bid++) {
00119       wrk->mixture_cache[t][bid] = &(wrk->mixture_cache[t][0][wrk->OP_gprune_num * bid]);
00120     }
00121     /* clear the new part */
00122     for(bid=0;bid<wrk->OP_hmminfo->codebooknum;bid++) {
00123       wrk->mixture_cache_num[t][bid] = 0;
00124     }
00125   }
00126 
00127   wrk->tmix_allocframenum = newnum;
00128 }
00129 
00136 void
00137 calc_tied_mix_free(HMMWork *wrk)
00138 {
00139   if (wrk->mroot != NULL) mybfree2(&(wrk->mroot));
00140   if (wrk->mixture_cache_num != NULL) free(wrk->mixture_cache_num);
00141   if (wrk->mixture_cache != NULL) free(wrk->mixture_cache);
00142   free(wrk->tmix_last_id);
00143   wrk->mroot = NULL;
00144   wrk->mixture_cache_num = NULL;
00145   wrk->mixture_cache = NULL;
00146 }
00147 
00161 LOGPROB
00162 calc_tied_mix(HMMWork *wrk)
00163 {
00164   GCODEBOOK *book;
00165   LOGPROB logprob, logprobsum;
00166   int i, id;
00167   MIXCACHE *ttcache;
00168   short ttcachenum;
00169   MIXCACHE *last_ttcache;
00170   short last_ttcachenum;
00171   PROB *weight;
00172   PROB stream_weight;
00173   int s;
00174   int num;
00175 
00176   logprobsum = 0.0;
00177   for(s=0;s<wrk->OP_nstream;s++) {
00178     book = (GCODEBOOK *)(wrk->OP_state->pdf[s]->b);
00179     weight = wrk->OP_state->pdf[s]->bweight;
00180     /* set stream weight */
00181     if (wrk->OP_state->w) stream_weight = wrk->OP_state->w->weight[s];
00182     else stream_weight = 1.0;
00183     /* setup storage pointer for this mixture pdf */
00184     wrk->OP_vec = wrk->OP_vec_stream[s];
00185     wrk->OP_veclen = wrk->OP_veclen_stream[s];
00186     /* extend cache if needed */
00187     calc_tied_mix_extend(wrk, wrk->OP_time);
00188     /* prepare cache for this codebook at this time */
00189     ttcache = wrk->mixture_cache[wrk->OP_time][book->id];
00190     ttcachenum = wrk->mixture_cache_num[wrk->OP_time][book->id];
00191     /* consult cache */
00192     if (ttcachenum > 0) {
00193       /* calculate using cache and weight */
00194       for (i=0;i<ttcachenum;i++) {
00195         wrk->OP_calced_score[i] = ttcache[i].score + weight[ttcache[i].id];
00196       }
00197       num = ttcachenum;
00198     } else {
00199       /* compute Gaussian set */
00200       /* computed Gaussians will be set in:
00201          score ... OP_calced_score[0..OP_calced_num]
00202          id    ... OP_calced_id[0..OP_calced_num] */
00203       if (wrk->OP_time >= 1) {
00204         last_ttcache = wrk->mixture_cache[wrk->OP_time-1][book->id];
00205         last_ttcachenum = wrk->mixture_cache_num[wrk->OP_time-1][book->id];
00206         if (last_ttcachenum > 0) {
00207           for(i=0;i<last_ttcachenum;i++) wrk->tmix_last_id[i] = last_ttcache[i].id;
00208           /* tell last calced best */
00209           (*(wrk->compute_gaussset))(wrk, book->d, book->num, wrk->tmix_last_id, last_ttcachenum);
00210         } else {
00211           (*(wrk->compute_gaussset))(wrk, book->d, book->num, NULL, 0);
00212         }
00213       } else {
00214         (*(wrk->compute_gaussset))(wrk, book->d, book->num, NULL, 0);
00215       }
00216       /* store to cache */
00217       wrk->mixture_cache_num[wrk->OP_time][book->id] = wrk->OP_calced_num;
00218       for (i=0;i<wrk->OP_calced_num;i++) {
00219         id = wrk->OP_calced_id[i];
00220         ttcache[i].id = id;
00221         ttcache[i].score = wrk->OP_calced_score[i];
00222         /* now OP_calced_{id|score} can be used for work area */
00223         /* add weights */
00224         wrk->OP_calced_score[i] += weight[id];
00225       }
00226       num = wrk->OP_calced_num;
00227     }
00228     /* add log probs */
00229     logprob = addlog_array(wrk->OP_calced_score, num);
00230     /* if outprob of a stream is zero, skip this stream */
00231     if (logprob <= LOG_ZERO) continue;
00232     /* sum all the obtained mixture scores */
00233     logprobsum += logprob * stream_weight;
00234   }
00235   if (logprobsum == 0.0) return(LOG_ZERO); /* no valid stream */
00236   if (logprobsum <= LOG_ZERO) return(LOG_ZERO); /* lowest == LOG_ZERO */
00237   return (logprobsum * INV_LOG_TEN);
00238 }  
00239 
00240 
00257 LOGPROB
00258 calc_compound_mix(HMMWork *wrk)
00259 {
00260   HTK_HMM_PDF *m;
00261   GCODEBOOK *book;
00262   LOGPROB logprob, logprobsum;
00263   int i, id;
00264   MIXCACHE *ttcache;
00265   short ttcachenum;
00266   MIXCACHE *last_ttcache;
00267   short last_ttcachenum;
00268   PROB *weight;
00269   PROB stream_weight;
00270   int s;
00271   int num;
00272 
00273   logprobsum = 0.0;
00274   for(s=0;s<wrk->OP_nstream;s++) {
00275     /* set stream weight */
00276     if (wrk->OP_state->w) stream_weight = wrk->OP_state->w->weight[s];
00277     else stream_weight = 1.0;
00278     m = wrk->OP_state->pdf[s];
00279     /* setup storage pointer for this mixture pdf */
00280     wrk->OP_vec = wrk->OP_vec_stream[s];
00281     wrk->OP_veclen = wrk->OP_veclen_stream[s];
00282     weight = wrk->OP_state->pdf[s]->bweight;
00283     if (m->tmix) {
00284       /* tied-mixture PDF */
00285       book = (GCODEBOOK *)(m->b);
00286       /* extend cache if needed */
00287       calc_tied_mix_extend(wrk, wrk->OP_time);
00288       /* prepare cache for this codebook at this time */
00289       ttcache = wrk->mixture_cache[wrk->OP_time][book->id];
00290       ttcachenum = wrk->mixture_cache_num[wrk->OP_time][book->id];
00291       /* consult cache */
00292       if (ttcachenum > 0) {
00293         /* calculate using cache and weight */
00294         for (i=0;i<ttcachenum;i++) {
00295           wrk->OP_calced_score[i] = ttcache[i].score + weight[ttcache[i].id];
00296         }
00297         num = ttcachenum;
00298       } else {
00299         /* compute Gaussian set */
00300         /* computed Gaussians will be set in:
00301            score ... OP_calced_score[0..OP_calced_num]
00302            id    ... OP_calced_id[0..OP_calced_num] */
00303         if (wrk->OP_time >= 1) {
00304           last_ttcache = wrk->mixture_cache[wrk->OP_time-1][book->id];
00305           last_ttcachenum = wrk->mixture_cache_num[wrk->OP_time-1][book->id];
00306           if (last_ttcachenum > 0) {
00307             for(i=0;i<last_ttcachenum;i++) wrk->tmix_last_id[i] = last_ttcache[i].id;
00308             /* tell last calced best */
00309             (*(wrk->compute_gaussset))(wrk, book->d, book->num, wrk->tmix_last_id, last_ttcachenum);
00310           } else {
00311             (*(wrk->compute_gaussset))(wrk, book->d, book->num, NULL, 0);
00312           }
00313         } else {
00314           (*(wrk->compute_gaussset))(wrk, book->d, book->num, NULL, 0);
00315         }
00316         /* store to cache */
00317         wrk->mixture_cache_num[wrk->OP_time][book->id] = wrk->OP_calced_num;
00318         for (i=0;i<wrk->OP_calced_num;i++) {
00319           id = wrk->OP_calced_id[i];
00320           ttcache[i].id = id;
00321           ttcache[i].score = wrk->OP_calced_score[i];
00322           /* now OP_calced_{id|score} can be used for work area */
00323           /* add weights */
00324           wrk->OP_calced_score[i] += weight[id];
00325         }
00326         num = wrk->OP_calced_num;
00327       }
00328     } else {
00329       /* normal state */
00330       (*(wrk->compute_gaussset))(wrk, m->b, m->mix_num, NULL, 0);
00331       /* add weights */
00332       for(i=0;i<wrk->OP_calced_num;i++) {
00333         wrk->OP_calced_score[i] += weight[wrk->OP_calced_id[i]];
00334       }
00335       num = wrk->OP_calced_num;
00336     }
00337     /* add log probs */
00338     logprob = addlog_array(wrk->OP_calced_score, num);
00339     /* if outprob of a stream is zero, skip this stream */
00340     if (logprob <= LOG_ZERO) continue;
00341     /* sum all the obtained mixture scores */
00342     logprobsum += logprob * stream_weight;
00343   }
00344   if (logprobsum == 0.0) return(LOG_ZERO); /* no valid stream */
00345   if (logprobsum <= LOG_ZERO) return(LOG_ZERO); /* lowest == LOG_ZERO */
00346   return (logprobsum * INV_LOG_TEN);
00347 }