Julius 4.2
|
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 }