Home | History | Annotate | Download | only in crec
      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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