• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*---------------------------------------------------------------------------*
2  *  swimodel.c  *
3  *                                                                           *
4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5  *                                                                           *
6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7  *  you may not use this file except in compliance with the License.         *
8  *                                                                           *
9  *  You may obtain a copy of the License at                                  *
10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
11  *                                                                           *
12  *  Unless required by applicable law or agreed to in writing, software      *
13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15  *  See the License for the specific language governing permissions and      *
16  *  limitations under the License.                                           *
17  *                                                                           *
18  *---------------------------------------------------------------------------*/
19 
20 #ifndef _RTT
21 #include <stdio.h>
22 #endif
23 #include <math.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 
27 #include "prelib.h"
28 #include "hmmlib.h"
29 #include "portable.h"
30 #include "errhndl.h"
31 
32 #include "log_add.h"
33 #include "swimodel.h"
34 
35 
36 #define MTAG NULL
37 
38 
39 /*--------------------------------------------------------------*
40  *                                                              *
41  *                                                              *
42  *                                                              *
43  *--------------------------------------------------------------*/
44 
45 /* the looping cost lookup table. This table was generated empirically
46    by looking at resulting residency distributions, trying to make them
47    look roughly like normal distributions centered at the average state
48    durations */
49 
50 const char loop_cost_table [128][6] = {
51 {0,0,0,0,0,0},
52 {13,15,16,16,16,16},
53 {12,13,14,14,14,14},
54 {11,12,13,13,13,13},
55 {10,12,12,12,12,12},
56 {10,11,11,12,12,12},
57 {10,11,11,11,11,11},
58 {10,11,11,11,11,11},
59 {9,11,11,11,11,11},
60 {9,10,11,11,11,11},
61 {9,10,10,10,10,10},
62 {9,10,10,10,10,10},
63 {9,10,10,10,10,10},
64 {9,10,10,10,10,10},
65 {9,10,10,10,10,10},
66 {9,10,10,10,10,10},
67 {9,10,10,10,10,10},
68 {8,10,10,10,10,10},
69 {8,10,10,10,10,10},
70 {8,10,10,10,10,10},
71 {8,10,10,10,10,10},
72 {8,10,10,10,10,10},
73 {8,10,10,10,10,10},
74 {7,10,10,10,10,10},
75 {7,10,10,10,10,10},
76 {7,10,10,10,10,10},
77 {6,10,10,10,10,10},
78 {6,10,10,10,10,10},
79 {6,10,10,10,10,10},
80 {5,10,10,10,10,10},
81 {5,10,10,10,10,10},
82 {4,10,10,10,10,10},
83 {4,9,10,10,10,10},
84 {3,9,10,10,10,10},
85 {2,9,10,10,10,10},
86 {2,9,10,10,10,10},
87 {2,9,10,10,10,10},
88 {1,9,10,10,10,10},
89 {1,9,10,10,10,10},
90 {1,9,10,10,10,10},
91 {0,9,10,10,10,10},
92 {0,9,10,10,10,10},
93 {0,9,10,10,10,10},
94 {0,8,10,10,10,10},
95 {0,8,10,10,10,10},
96 {0,8,10,10,10,10},
97 {0,7,10,10,10,10},
98 {0,7,10,10,10,10},
99 {0,6,10,10,10,10},
100 {0,5,10,10,10,10},
101 {0,5,10,10,10,10},
102 {0,4,10,10,10,10},
103 {0,3,10,10,10,10},
104 {0,2,10,10,10,10},
105 {0,2,10,10,10,10},
106 {0,1,10,10,10,10},
107 {0,1,9,10,10,10},
108 {0,0,9,10,10,10},
109 {0,0,9,10,10,10},
110 {0,0,9,10,10,10},
111 {0,0,9,10,10,10},
112 {0,0,9,10,10,10},
113 {0,0,9,10,10,10},
114 {0,0,9,10,10,10},
115 {0,0,9,10,10,10},
116 {0,0,8,10,10,10},
117 {0,0,8,10,10,10},
118 {0,0,7,10,10,10},
119 {0,0,6,10,10,10},
120 {0,0,6,10,10,10},
121 {0,0,5,10,10,10},
122 {0,0,4,10,10,10},
123 {0,0,3,10,10,10},
124 {0,0,2,10,10,10},
125 {0,0,1,10,10,10},
126 {0,0,1,10,10,10},
127 {0,0,0,10,10,10},
128 {0,0,0,10,10,10},
129 {0,0,0,9,10,10},
130 {0,0,0,9,10,10},
131 {0,0,0,9,10,10},
132 {0,0,0,9,10,10},
133 {0,0,0,9,10,10},
134 {0,0,0,9,10,10},
135 {0,0,0,9,10,10},
136 {0,0,0,9,10,10},
137 {0,0,0,8,10,10},
138 {0,0,0,8,10,10},
139 {0,0,0,7,10,10},
140 {0,0,0,6,10,10},
141 {0,0,0,5,10,10},
142 {0,0,0,3,10,10},
143 {0,0,0,2,10,10},
144 {0,0,0,1,10,10},
145 {0,0,0,1,10,10},
146 {0,0,0,0,10,10},
147 {0,0,0,0,10,10},
148 {0,0,0,0,10,10},
149 {0,0,0,0,10,10},
150 {0,0,0,0,10,10},
151 {0,0,0,0,9,10},
152 {0,0,0,0,9,10},
153 {0,0,0,0,9,10},
154 {0,0,0,0,9,10},
155 {0,0,0,0,9,10},
156 {0,0,0,0,9,10},
157 {0,0,0,0,9,10},
158 {0,0,0,0,8,10},
159 {0,0,0,0,7,10},
160 {0,0,0,0,6,10},
161 {0,0,0,0,5,10},
162 {0,0,0,0,3,10},
163 {0,0,0,0,2,10},
164 {0,0,0,0,1,10},
165 {0,0,0,0,0,10},
166 {0,0,0,0,0,10},
167 {0,0,0,0,0,10},
168 {0,0,0,0,0,10},
169 {0,0,0,0,0,10},
170 {0,0,0,0,0,10},
171 {0,0,0,0,0,10},
172 {0,0,0,0,0,9},
173 {0,0,0,0,0,9},
174 {0,0,0,0,0,9},
175 {0,0,0,0,0,9},
176 {0,0,0,0,0,9},
177 {0,0,0,0,0,9},
178 {0,0,0,0,0,8}
179 };
180 
181 /* the transition cost lookup table. This table was generated empirically
182    by looking at resulting residency distributions, trying to make them
183    look roughly like normal distributions centered at the average state
184    durations */
185 
186 const char trans_cost_table [128][6] = {
187 {0,0,0,0,0,0},
188 {0,0,0,0,0,0},
189 {0,0,0,0,0,0},
190 {0,0,0,0,0,0},
191 {0,0,0,0,0,0},
192 {0,0,0,0,0,0},
193 {0,0,0,0,0,0},
194 {1,0,0,0,0,0},
195 {1,0,0,0,0,0},
196 {1,0,0,0,0,0},
197 {1,0,0,0,0,0},
198 {1,0,0,0,0,0},
199 {1,0,0,0,0,0},
200 {1,0,0,0,0,0},
201 {1,0,0,0,0,0},
202 {1,0,0,0,0,0},
203 {1,0,0,0,0,0},
204 {1,0,0,0,0,0},
205 {1,0,0,0,0,0},
206 {1,0,0,0,0,0},
207 {2,0,0,0,0,0},
208 {2,0,0,0,0,0},
209 {2,0,0,0,0,0},
210 {2,0,0,0,0,0},
211 {2,0,0,0,0,0},
212 {2,0,0,0,0,0},
213 {2,0,0,0,0,0},
214 {3,0,0,0,0,0},
215 {3,0,0,0,0,0},
216 {3,0,0,0,0,0},
217 {3,0,0,0,0,0},
218 {4,0,0,0,0,0},
219 {4,0,0,0,0,0},
220 {4,0,0,0,0,0},
221 {5,0,0,0,0,0},
222 {5,0,0,0,0,0},
223 {6,1,0,0,0,0},
224 {6,1,0,0,0,0},
225 {7,1,0,0,0,0},
226 {7,1,0,0,0,0},
227 {8,1,0,0,0,0},
228 {8,1,0,0,0,0},
229 {9,1,0,0,0,0},
230 {10,1,0,0,0,0},
231 {10,1,0,0,0,0},
232 {11,2,0,0,0,0},
233 {12,2,0,0,0,0},
234 {13,2,0,0,0,0},
235 {13,2,0,0,0,0},
236 {14,3,0,0,0,0},
237 {15,3,0,0,0,0},
238 {15,3,0,0,0,0},
239 {16,4,0,0,0,0},
240 {17,4,0,0,0,0},
241 {17,5,0,0,0,0},
242 {18,6,0,0,0,0},
243 {18,6,0,0,0,0},
244 {19,7,0,0,0,0},
245 {19,8,0,0,0,0},
246 {19,9,0,0,0,0},
247 {20,10,0,0,0,0},
248 {20,11,0,0,0,0},
249 {20,12,0,0,0,0},
250 {20,13,0,0,0,0},
251 {21,14,1,0,0,0},
252 {21,15,1,0,0,0},
253 {21,16,1,0,0,0},
254 {21,17,1,0,0,0},
255 {22,18,2,0,0,0},
256 {22,19,2,0,0,0},
257 {22,19,2,0,0,0},
258 {22,20,3,0,0,0},
259 {22,20,3,0,0,0},
260 {23,21,4,0,0,0},
261 {23,21,5,0,0,0},
262 {23,22,6,0,0,0},
263 {23,22,7,0,0,0},
264 {23,23,8,0,0,0},
265 {23,23,9,0,0,0},
266 {23,23,10,0,0,0},
267 {24,23,12,0,0,0},
268 {24,24,13,0,0,0},
269 {24,24,14,0,0,0},
270 {24,24,16,0,0,0},
271 {24,24,17,0,0,0},
272 {24,24,18,0,0,0},
273 {25,24,20,0,0,0},
274 {25,25,21,1,0,0},
275 {25,25,22,1,0,0},
276 {25,25,22,1,0,0},
277 {25,25,23,2,0,0},
278 {25,25,24,2,0,0},
279 {25,25,24,3,0,0},
280 {25,25,25,3,0,0},
281 {26,26,25,4,0,0},
282 {26,26,25,5,0,0},
283 {26,26,25,6,0,0},
284 {26,26,26,8,0,0},
285 {26,26,26,9,0,0},
286 {26,26,26,11,0,0},
287 {26,26,26,13,0,0},
288 {27,27,26,15,0,0},
289 {27,27,27,17,0,0},
290 {27,27,27,18,0,0},
291 {27,27,27,20,0,0},
292 {27,27,27,22,0,0},
293 {27,27,27,23,0,0},
294 {27,27,27,24,0,0},
295 {27,27,27,25,0,0},
296 {27,27,27,26,1,0},
297 {28,28,28,26,1,0},
298 {28,28,28,27,1,0},
299 {28,28,28,27,2,0},
300 {28,28,28,27,3,0},
301 {28,28,28,28,3,0},
302 {28,28,28,28,5,0},
303 {28,28,28,28,6,0},
304 {28,28,28,28,8,0},
305 {28,28,28,28,10,0},
306 {29,29,29,29,12,0},
307 {29,29,29,29,14,0},
308 {29,29,29,29,16,0},
309 {29,29,29,29,19,0},
310 {29,29,29,29,21,0},
311 {29,29,29,29,23,0},
312 {29,29,29,29,24,0},
313 {29,29,29,29,26,0},
314 {29,29,29,29,27,0}
315 };
316 
317 /*--------------------------------------------------------------*
318  *                                                              *
319  *                                                              *
320  *                                                              *
321  *--------------------------------------------------------------*/
322 
load_short(PFile * fp)323 static short load_short(PFile* fp)
324 {
325   short v;
326   pfread(&v, sizeof(short), 1, fp);
327   return v;
328 }
329 
load_swimodel(const char * filename)330 const SWIModel* load_swimodel(const char *filename)
331 {
332   int i;
333   SWIModel *swimodel = NULL;
334   const void* file = NULL;
335 
336 #ifdef SREC_ENGINE_VERBOSE_LOGGING
337   PLogMessage("load_swimodel: loaded %s", filename);
338 #endif
339   swimodel = (SWIModel*) CALLOC(1, sizeof(SWIModel), "clib.models.base");
340 
341   if (mmap_zip(filename, &swimodel->mmap_zip_data, &swimodel->mmap_zip_size)) {
342       PLogError("load_swimodel: mmap_zip failed for %s\n", filename);
343       goto CLEANUP;
344   }
345   file = swimodel->mmap_zip_data;
346 
347   swimodel->num_hmmstates = *(const short*)file;
348   file += sizeof(short);
349   swimodel->num_dims = *(const short*)file;
350   file += sizeof(short);
351   swimodel->num_pdfs = *(const short*)file;
352   file += sizeof(short);
353 
354   SWIhmmState* hmmstates = (SWIhmmState*) CALLOC(swimodel->num_hmmstates, sizeof(SWIhmmState), "clib.models.states");
355   swimodel->hmmstates = hmmstates;
356 
357   const short* num_pdfs_in_model = (const short*)file;
358   file += sizeof(short) * swimodel->num_hmmstates;
359 
360   swimodel->allmeans = (const featdata*)file;
361   file += sizeof(featdata) * swimodel->num_pdfs * swimodel->num_dims;
362 
363   swimodel->allweights = (const wtdata*)file;
364   file += sizeof(wtdata) * swimodel->num_pdfs;
365 
366   swimodel->avg_state_durations = (const featdata*)file;
367   file += sizeof(featdata) * swimodel->num_hmmstates;
368 
369   if (file > swimodel->mmap_zip_data + swimodel->mmap_zip_size) {
370       PLogError("load_swimodel: not enough data in %s", filename);
371       goto CLEANUP;
372   }
373 
374 #ifdef SREC_ENGINE_VERBOSE_LOGGING
375   PLogMessage("loaded models %s num_hmmstates %d num_dims %d num_pdfs %d weights[0] %d\n",
376               filename, swimodel->num_hmmstates, swimodel->num_dims, swimodel->num_pdfs,
377               *swimodel->allweights);
378 #endif
379 
380   const featdata* mean_ptr = swimodel->allmeans;
381   const wtdata* weight_ptr = swimodel->allweights;
382 
383   for (i = 0;i < swimodel->num_hmmstates;i++)
384   {
385     hmmstates[i].num_pdfs = num_pdfs_in_model[i];
386     hmmstates[i].means = mean_ptr;
387     hmmstates[i].weights = weight_ptr;
388     mean_ptr += swimodel->num_dims * num_pdfs_in_model[i];
389     weight_ptr += num_pdfs_in_model[i];
390   }
391 
392   return swimodel;
393 
394 CLEANUP:
395   free_swimodel(swimodel);
396   return NULL;
397 }
398 
free_swimodel(const SWIModel * swimodel)399 void free_swimodel(const SWIModel* swimodel)
400 {
401   if (!swimodel) return;
402   if (swimodel->mmap_zip_data) munmap_zip(swimodel->mmap_zip_data, swimodel->mmap_zip_size);
403   FREE((void*)swimodel->hmmstates);
404   FREE((void*)swimodel);
405 }
406 
Gaussian_Grand_Density_Swimodel(const preprocessed * data,const featdata * means)407 static PINLINE prdata Gaussian_Grand_Density_Swimodel(const preprocessed *data, const featdata *means)
408 /*
409 **  Observation probability function of a Gaussian pdf
410 **  with diagonal covariance matrix.
411 */
412 {
413   prdata pval;
414   prdata diff;
415   const imeldata *dvec;
416   const imeldata *dend;
417   int count;
418 
419   dvec = data->seq + data->use_from;    /* Move to starting feature element */
420 
421   pval = 0;
422   dend = dvec + data->use_dim;
423   count = 0;
424   while (dvec < dend)
425   {
426     diff = *(means++) - *(dvec++);
427     pval -= diff * diff;
428   }
429   pval = data->mul.multable_factor_gaussian
430          * (pval - data->mul.grand_mod_cov_gaussian);
431   return (pval);
432 }
433 
mixture_diagonal_gaussian_swimodel(const preprocessed * prep,const SWIhmmState * spd,short num_dims)434 scodata mixture_diagonal_gaussian_swimodel(const preprocessed *prep,
435     const SWIhmmState *spd, short num_dims)
436 /*
437 **  Observation probability function
438 */
439 {
440   int ii;
441   prdata pval, gval;
442 
443   prdata dval;
444   const featdata *meanptr;
445   const wtdata *weightptr;
446 
447   ASSERT(prep);
448   ASSERT(spd);
449 
450   pval = -(prdata) MAX_LOG;
451 
452   meanptr = spd->means;
453   weightptr = spd->weights;
454 
455   for (ii = 0; ii < spd->num_pdfs; ii++)
456   {
457     gval = ((prdata) * (weightptr++) * prep->add.scale
458             + Gaussian_Grand_Density_Swimodel(prep, meanptr));
459 
460     meanptr += num_dims;
461 
462     if (pval > gval)
463     {
464       dval = pval - gval;
465       if (dval < prep->add.add_log_limit)
466         pval += log_increment_inline(dval, &prep->add);
467     }
468     else
469     {
470       dval = gval - pval;
471       if (dval < prep->add.add_log_limit)
472         pval = gval + log_increment_inline(dval, &prep->add);
473       else
474         pval = gval;
475     }
476   }
477   ASSERT(pval > ((0x01 << 31) / (prep->mix_score_scale * prep->add.inv_scale)));
478   pval = ((pval * prep->mix_score_scale - 64 * prep->add.scale)
479           * prep->add.inv_scale) >> 19;
480 
481   return ((scodata)pval);
482 }
483