• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*---------------------------------------------------------------------------*
2  *  srec_results.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 #include"passert.h"
21 
22 #include"portable.h"
23 #include"srec.h"
24 #include"search_network.h"
25 #include"srec_stats.h"
26 #if USE_COMP_STATS
27 #include"comp_stats.h"
28 #endif
29 #include"srec_results.h"
30 
WHICH_RECOG(multi_srec * recm)31 static srec* WHICH_RECOG(multi_srec* recm)
32 {
33   srec* return_rec = NULL;
34   costdata current_best_cost = MAXcostdata;
35   int i = 0;
36 #if DO_ALLOW_MULTIPLE_MODELS
37   for (i = 0; i < recm->num_activated_recs; i++)
38   {
39 #endif
40     if (current_best_cost > recm->rec[i].current_best_cost)
41     {
42       current_best_cost = recm->rec[i].current_best_cost;
43       return_rec = &recm->rec[i];
44     }
45 #if DO_ALLOW_MULTIPLE_MODELS
46   }
47 #endif
48   return return_rec;
49 }
50 
srec_get_bestcost_recog_id(multi_srec * recm,int * id)51 int srec_get_bestcost_recog_id(multi_srec* recm, int* id)
52 {
53   srec* rec = WHICH_RECOG(recm);
54   if (!rec) *id = -1;
55   else *id = rec->id;
56   return 0;
57 }
58 
srec_result_strip_slot_markers(char * result)59 void srec_result_strip_slot_markers(char* result)
60 {
61   if (!result) return;
62   else
63   {
64     char *p = result, *q = p;
65     for (; (*q = *p); q++, p++)
66     {
67       if (p[0] == IMPORTED_RULES_DELIM && (p[2] == ' ' || p[2] == '\0'))
68       {
69         p += 2;
70         *q = *p;
71       }
72     }
73   }
74 }
75 
srec_has_results(multi_srec * recm)76 int srec_has_results(multi_srec* recm)
77 {
78   srec* rec = WHICH_RECOG(recm);
79   frameID end_frame;
80   if (!rec)
81     return 0;
82   end_frame = rec->current_search_frame;
83   if (!rec->srec_ended)
84     return 0;
85   if (rec->word_lattice->words_for_frame[end_frame] != MAXwtokenID)
86     return 1;
87   if (rec->astar_stack->num_complete_paths)
88     return 1;
89   return 0;
90 }
91 
srec_clear_results(multi_srec * recm)92 int srec_clear_results(multi_srec* recm)
93 {
94   srec* rec = WHICH_RECOG(recm);
95   frameID ifr;
96   SREC_STATS_SHOW();
97   SREC_STATS_CLEAR();
98 
99   if (!rec)
100     return 1;
101   astar_stack_clear(rec->astar_stack);
102   for (ifr = 0; ifr <= rec->current_search_frame; ifr++)
103     rec->word_lattice->words_for_frame[ifr] = MAXwtokenID;
104 
105   return 0;
106 }
107 
srec_nbest_prepare_list(multi_srec * recm,int n,asr_int32_t * bestcost)108 void* srec_nbest_prepare_list(multi_srec* recm, int n, asr_int32_t* bestcost)
109 {
110   int rc;
111   srec* rec = WHICH_RECOG(recm);
112   AstarStack* stack = rec ? rec->astar_stack : 0;
113 
114   if (!stack)
115     return NULL;
116 #if USE_COMP_STATS
117   start_cs_clock1(&comp_stats->astar);
118 #endif
119   rc = astar_stack_prepare(stack, n, rec);
120   if (rc)
121   {
122     *bestcost = MAXbcostdata;
123     return (void*)rec;
124   }
125   astar_stack_do_backwards_search(rec, n);
126 #if USE_COMP_STATS
127   end_cs_clock1(&comp_stats->astar, 1);
128 #endif
129   if (stack->num_complete_paths)
130   {
131     *bestcost = stack->complete_paths[0]->costsofar;
132   }
133   else
134   {
135     *bestcost = MAXbcostdata;
136   }
137 
138   return (void*)(rec);
139 }
140 
srec_nbest_destroy_list(void * rec_void)141 void srec_nbest_destroy_list(void* rec_void)
142 {
143   srec* rec = (srec*)rec_void;
144   AstarStack* stack = rec ? rec->astar_stack : 0;
145   astar_stack_clear(stack);
146 }
147 
srec_nbest_get_num_choices(void * rec_void)148 int srec_nbest_get_num_choices(void* rec_void)
149 {
150   srec* rec = (srec*)rec_void;
151   AstarStack* stack = rec ? rec->astar_stack : 0;
152   return stack ? stack->num_complete_paths : 0;
153 }
154 
srec_nbest_put_confidence_value(void * rec_void,int choice,int confidence_value)155 int srec_nbest_put_confidence_value(void* rec_void, int choice, int confidence_value)
156 {
157   srec* rec = (srec*)rec_void;
158   AstarStack* stack = rec ? rec->astar_stack : 0;
159   if (!stack)
160   {
161 	  return 1;
162   }
163   else
164   {
165   stack->complete_path_confidences[choice] = confidence_value;
166   return 0;
167   }
168 }
169 
srec_nbest_get_confidence_value(void * rec_void,int choice)170 int srec_nbest_get_confidence_value(void* rec_void, int choice)
171 {
172   srec* rec = (srec*)rec_void;
173   AstarStack* stack = rec ? rec->astar_stack : 0;
174   return stack->complete_path_confidences[choice];
175 }
176 
srec_nbest_fix_homonym_confidence_values(void * rec_void)177 int srec_nbest_fix_homonym_confidence_values(void* rec_void)
178 {
179   int i, num_fixed = 0;
180   srec* rec = (srec*)rec_void;
181   AstarStack* stack = rec ? rec->astar_stack : 0;
182   if (!stack)
183     return num_fixed;
184   for(i=1; i<stack->num_complete_paths; i++) {
185     partial_path* parp = stack->complete_paths[i];
186     for (; parp; parp = parp->next) {
187       word_token* wtoken = &rec->word_token_array[ parp->token_index];
188       if(WORD_TOKEN_GET_HOMONYM( wtoken)) {
189         stack->complete_path_confidences[i] = stack->complete_path_confidences[i-1];
190         num_fixed++;
191         break;
192       }
193     }
194   }
195   return num_fixed;
196 }
197 
srec_nbest_get_word(void * nbest,size_t choice)198 LCHAR* srec_nbest_get_word(void* nbest, size_t choice)
199 {
200   srec* rec = (srec*)nbest;
201   return rec->context->olabels->words[choice];
202 }
203 
srec_nbest_remove_result(void * rec_void,int n)204 int srec_nbest_remove_result(void* rec_void, int n)
205 {
206   int i;
207   srec* rec = (srec*)rec_void;
208   AstarStack* stack = rec ? rec->astar_stack : 0;
209 
210 
211   if (!stack || n < 0 || n >= stack->num_complete_paths)
212   {
213     return 0; /* out of range error */
214   }
215 
216   /* free the partial_path which represents the entry */
217   free_partial_path(stack, stack->complete_paths[n]);
218 
219   /* now I need to move everybody up one so I do not have a hole
220      in the middle of my nbest list */
221   for (i = n + 1 ; i < stack->num_complete_paths; i++)
222     stack->complete_paths[i-1] = stack->complete_paths[i];
223   stack->complete_paths[i-1] = 0; /* empty the last one */
224 
225   /* finally change the size of my nbest list */
226   stack->num_complete_paths--;
227 
228   return 1;
229 }
230 
srec_nbest_get_resultWordIDs(void * rec_void,size_t index,wordID * wordIDs,size_t * len,asr_int32_t * cost)231 ESR_ReturnCode srec_nbest_get_resultWordIDs(void* rec_void, size_t index, wordID* wordIDs, size_t* len, asr_int32_t* cost)
232 {
233   const srec* rec = (srec*) rec_void;
234   AstarStack* stack = rec ? rec->astar_stack : 0;
235   partial_path* parp;
236   wordID id;
237   size_t currentLen = 0;
238 
239   if (!stack || index >= (size_t) stack->num_complete_paths)
240   {
241     if (wordIDs) *wordIDs = MAXwordID;
242     if (len) *len = 0;
243     *cost = MAXbcostdata;
244     return ESR_ARGUMENT_OUT_OF_BOUNDS; /* out of range error */
245   }
246 
247   parp = stack->complete_paths[index];
248   *cost = stack->complete_paths[index]->costsofar;
249   if (len == NULL || wordIDs == NULL)
250     return ESR_SUCCESS;
251   if (parp && parp->word == rec->context->beg_silence_word)
252     parp = parp->next;
253   while (parp)
254   {
255     id = parp->word;
256     if (id == rec->context->end_silence_word)
257       break;
258 
259     if (currentLen >= *len)
260     {
261       *wordIDs = MAXwordID;
262       *len = currentLen + 1;
263       return ESR_BUFFER_OVERFLOW; /* too little space error */
264     }
265     *wordIDs = id;
266     ++wordIDs;
267     ++currentLen;
268     parp = parp->next;
269   }
270   --currentLen;
271 
272   if (currentLen >= *len)
273   {
274     *wordIDs = MAXwordID;
275     *len = currentLen + 1;
276     return ESR_BUFFER_OVERFLOW; /* too little space error */
277   }
278   *wordIDs = MAXwordID;
279   *len = currentLen + 1;
280   return ESR_SUCCESS;
281 }
282 
srec_nbest_get_result(void * rec_void,int n,char * label,int label_len,asr_int32_t * cost,int whether_strip_slot_markers)283 int srec_nbest_get_result(void* rec_void, int n, char* label, int label_len, asr_int32_t* cost, int whether_strip_slot_markers)
284 {
285   const srec* rec = (srec*)rec_void;
286   AstarStack* stack = rec ? rec->astar_stack : 0;
287   partial_path* parp;
288   word_token* wtoken;
289   int return_len;
290 
291   if (!stack || n < 0 || n >= stack->num_complete_paths)
292   {
293     *label = 0;
294     *cost = MAXbcostdata;
295     return 1; /* out of range error */
296   }
297 
298   return_len = 0;
299   parp = stack->complete_paths[n];
300   *cost = stack->complete_paths[n]->costsofar;
301   for (; parp; parp = parp->next)
302   {
303     const char *p;
304     int lenp;
305     wtoken = &rec->word_token_array[ parp->token_index];
306     p = "NULL";
307     if (rec->context->olabels->words[wtoken->word])
308       p = rec->context->olabels->words[wtoken->word];
309     if (!strcmp(p, "-pau2-"))
310       break;
311 
312     lenp = (char)strlen(p);
313     if (return_len + lenp >= label_len)
314     {
315       *label = 0;
316       return 1; /* too little space error */
317     }
318     strcpy(label + return_len, p);
319     return_len += lenp;
320     if (whether_strip_slot_markers)
321     {
322       if (label[return_len-2] == IMPORTED_RULES_DELIM)
323       {
324         label[return_len-2] = 0;
325         return_len -= 2;
326       }
327     }
328 
329 #define SHOW_END_TIMES 1
330 #if SHOW_END_TIMES
331     {
332       char et[16];
333       lenp = sprintf(et, "@%d", wtoken->end_time);
334       if (return_len + lenp >= label_len)
335         return 0;
336       strcpy(label + return_len, et);
337       return_len += lenp;
338     }
339 #endif
340     lenp = 1;
341     if (return_len + lenp >= label_len)
342       return 0; /* too little space error */
343     strcpy(label + return_len, " ");
344     return_len += lenp;
345   }
346   *(label + return_len) = 0;
347   return 0;
348 }
349 
srec_nbest_get_choice_info(void * rec_void,int ibest,asr_int32_t * infoval,char * infoname)350 int srec_nbest_get_choice_info(void* rec_void, int ibest, asr_int32_t* infoval, char* infoname)
351 {
352   srec* rec = (srec*)rec_void;
353   AstarStack* stack = rec ? rec->astar_stack : 0;
354 
355   if (!stack)
356     return 1;
357 
358   if (ibest < 0 || ibest >= stack->num_complete_paths)
359     return 1;
360 
361   /*!strcmp(infoname,"num_speech_frames")||
362     !strcmp(infoname,"speech_frames_cost"))*/
363   if (1)
364   {
365     partial_path* parp = stack->complete_paths[ibest];
366     frameID start_frame = MAXframeID;
367     frameID i, end_frame = MAXframeID;
368     frameID num_speech_frames;
369     bigcostdata speech_frames_cost, start_cost = 0, end_cost = 0;
370     word_token* wtoken;
371     frameID num_words;
372 
373     for (num_words = 0 ; parp; parp = parp->next)
374     {
375       if (parp->token_index == MAXwtokenID) break;
376       wtoken = &rec->word_token_array[ parp->token_index];
377       if (wtoken->word == rec->context->beg_silence_word)
378       {
379         start_frame = wtoken->end_time;
380         start_cost = wtoken->cost + rec->accumulated_cost_offset[ start_frame];
381         num_words--;
382       }
383       else if (parp->next &&
384                parp->next->token_index != MAXwtokenID &&
385                rec->word_token_array[ parp->next->token_index].word == rec->context->end_silence_word)
386       {
387         end_frame = wtoken->end_time;
388         end_cost = wtoken->cost + rec->accumulated_cost_offset[ end_frame];
389         num_words--;
390       }
391       num_words++;
392     }
393 
394     if (start_frame != MAXframeID && end_frame != MAXframeID)
395     {
396       num_speech_frames = (frameID)(end_frame - start_frame);
397       speech_frames_cost = end_cost - start_cost;
398 #define WTW_AT_NNREJ_TRAINING 40
399       speech_frames_cost = speech_frames_cost - (num_words + 1) * (rec->context->wtw_average - WTW_AT_NNREJ_TRAINING);
400       if (!strcmp(infoname,  "num_speech_frames"))
401         *infoval = num_speech_frames;
402       else if (!strcmp(infoname, "speech_frames_cost"))
403         *infoval = speech_frames_cost;
404       else if (!strcmp(infoname, "gsm_states_score_diff"))
405       {
406         /* this is the best cost, unconstrained by state sequence */
407         bigcostdata gsm_states_cost = 0;
408         for (i = start_frame + 1; i <= end_frame; i++)
409         {
410           gsm_states_cost += rec->cost_offset_for_frame[i];
411           *infoval = (asr_int32_t)speech_frames_cost - (asr_int32_t)gsm_states_cost;
412         }
413       }
414       else if (!strcmp(infoname, "gsm_words_score_diff"))
415       {
416         /* this is the best cost, unconstrained by word sequence */
417         /* we can do this with astar.c ... with some work */
418         *infoval = 0;
419       }
420       else if (!strcmp(infoname, "num_words"))
421       {
422         *infoval = num_words;
423       }
424       else if (!strcmp(infoname, "gsm_cost"))
425       {
426         bigcostdata gsm_states_cost = 0;
427         for (i = start_frame + 1; i <= end_frame; i++)
428           gsm_states_cost += rec->best_model_cost_for_frame[i];
429         *infoval = gsm_states_cost;
430       }
431       else if (!strcmp(infoname, "num_total_frames"))
432       {
433         *infoval = rec->current_search_frame;
434       }
435       else if (!strcmp(infoname, "gsm_cost_all_frames"))
436       {
437         bigcostdata gsm_states_cost = 0;
438         for (i = 0; i < rec->current_search_frame; i++)
439           gsm_states_cost += rec->best_model_cost_for_frame[i];
440         *infoval = gsm_states_cost;
441       }
442       else if (!strcmp(infoname, "acoustic_model_index"))
443       {
444         *infoval = rec->id;
445       }
446       else
447       {
448         log_report("Error: srec_nbest_get_choice_info does not know re %s\n", infoname);
449         return 1;
450       }
451     }
452   }
453   return 0;
454 }
455 
456 
srec_nbest_sort(void * rec_void)457 int srec_nbest_sort(void* rec_void)
458 {
459   srec* rec = (srec*)rec_void;
460   AstarStack* stack = rec ? rec->astar_stack : 0;
461   size_t i, j, n;
462   partial_path* parp;
463 
464   if (!stack || stack->num_complete_paths < 1)
465     return 0; /* out of range error */
466 
467   n = stack->num_complete_paths;
468 
469   /* bubble sort is fine */
470   /* PLogError("** srec_nbest_sort **\n"); */
471   for (i = 0;i < n;i++)
472     for (j = i + 1;j < n;j++)
473       if (stack->complete_paths[j]->costsofar < stack->complete_paths[i]->costsofar)
474       {
475         /* PLogMessage(" %d %d", stack->complete_paths[j]->costsofar,      stack->complete_paths[j]->costsofar); */
476         parp = stack->complete_paths[i];
477         stack->complete_paths[i] = stack->complete_paths[j];
478         stack->complete_paths[j] = parp;
479       }
480   return 1;
481 
482 }
483