1 /* -*- c-basic-offset:4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3  * Copyright (c) 1999-2004 Carnegie Mellon University.  All rights
4  * reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * This work was supported in part by funding from the Defense Advanced
19  * Research Projects Agency and the National Science Foundation of the
20  * United States of America, and the CMU Sphinx Speech Consortium.
21  *
22  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
23  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
26  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * ====================================================================
35  *
36  */
37 /* srch_output.c
38  * HISTORY
39  * $Log: srch_output.c,v $
40  * Revision 1.2  2006/02/23 05:13:26  arthchan2003
41  * Merged from branch SPHINX3_5_2_RCI_IRII_BRANCH: A wrapper for the outptu functions of the search routine
42  *
43  * Revision 1.1.2.1  2006/01/17 01:24:21  arthchan2003
44  * The home of log output functions.
45  *
46  */
47 
48 #include <string.h>
49 
50 #include "srch_output.h"
51 #include "logs3.h"
52 
53 int32
compute_scale(int32 sf,int32 ef,int32 * scalearray)54 compute_scale(int32 sf, int32 ef, int32 * scalearray)
55 {
56     int32 i;
57     int32 hypscale = 0;
58     for (i = sf; i < ef; i++)
59         hypscale += scalearray[i];
60     return hypscale;
61 
62 }
63 
64 /*
65   READ ME.
66   Current match_write has four features which is different with log_hypstr.
67   1, match_write allows the use of hdr.
68   2, log_hypstr allows matchexact in output.
69   3, log_hypstr allows output the score after the match file name.
70   4, log_hypstr will dump the pronounciation variation to the code.
71 
72   I don't think they are very important in processing so I removed them.
73  */
74 
75 void
match_write(FILE * fp,glist_t hyp,char * uttid,dict_t * dict,char * hdr)76 match_write(FILE * fp, glist_t hyp, char *uttid, dict_t * dict, char *hdr)
77 {
78     gnode_t *gn;
79     srch_hyp_t *h;
80     int counter = 0;
81 
82     if (fp == NULL)
83         return;
84 
85     if (hyp == NULL)            /* Following s3.0 convention */
86         fprintf(fp, "(null)");
87 
88     fprintf(fp, "%s", (hdr ? hdr : ""));
89 
90 /*     for (gn = hyp; gn && (gnode_next(gn)); gn = gnode_next(gn)) { */
91     for (gn = hyp; gn; gn = gnode_next(gn)) {
92         h = (srch_hyp_t *) gnode_ptr(gn);
93 
94         if (h->sf != h->ef) {   /* FSG outputs zero-width hyps */
95             if ((!dict_filler_word(dict, h->id))
96                 && (h->id != dict_finishwid(dict))
97                 && (h->id != dict_startwid(dict)))
98                 fprintf(fp, "%s ",
99                         dict_wordstr(dict, dict_basewid(dict, h->id)));
100             counter++;
101         }
102     }
103     if (counter == 0)
104         fprintf(fp, " ");
105     fprintf(fp, "(%s)\n", uttid);
106     fflush(fp);
107 }
108 
109 
110 void
matchseg_write(FILE * fp,glist_t hyp,char * uttid,char * hdr,lm_t * lm,dict_t * dict,int32 num_frm,int32 * ascale,int32 unnorm)111 matchseg_write(FILE * fp, glist_t hyp, char *uttid, char *hdr,
112                lm_t * lm, dict_t * dict, int32 num_frm, int32 * ascale,
113                int32 unnorm)
114 {
115     gnode_t *gn;
116     srch_hyp_t *h;
117     int32 ascr, lscr, scl, hypscale, global_hypscale;
118     int32 i;
119 
120     if (fp == NULL)
121         return;
122 
123     ascr = 0;
124     lscr = 0;
125     scl = 0;
126     hypscale = 0;
127     global_hypscale = 0;
128 
129     for (gn = hyp; gn; gn = gnode_next(gn)) {
130         h = (srch_hyp_t *) gnode_ptr(gn);
131 
132         if (h->sf != h->ef) {   /* FSG outputs zero-width hyps */
133             ascr += h->ascr;
134             lscr += lm ? lm_rawscore(lm, h->lscr) : h->lscr;
135 
136             if (unnorm)
137                 global_hypscale += compute_scale(h->sf, h->ef, ascale);
138         }
139     }
140 
141     for (i = 0; i < num_frm; i++)
142         scl += ascale[i];
143 
144     fprintf(fp, "%s%s S %d T %d A %d L %d", (hdr ? hdr : ""), uttid,
145 	    scl, ascr + lscr + global_hypscale, ascr + global_hypscale,
146 	    lscr);
147 
148     for (gn = hyp; gn; gn = gnode_next(gn)) {
149             h = (srch_hyp_t *) gnode_ptr(gn);
150 
151             if (h->sf != h->ef) {   /* FSG outputs zero-width hyps */
152                 hypscale = 0;
153                 if (unnorm)
154 		    hypscale += compute_scale(h->sf, h->ef, ascale);
155 
156 
157                 fprintf(fp, " %d %d %d %s", h->sf, h->ascr + hypscale,
158                         lm ? lm_rawscore(lm, h->lscr) : h->lscr,
159                         dict_wordstr(dict, h->id));
160             }
161     }
162     fprintf(fp, " %d\n", num_frm);
163 
164     fflush(fp);
165 
166 }
167 
168 void
match_detailed(FILE * fp,glist_t hyp,char * uttid,char * LBL,char * lbl,int32 * senscale,dict_t * dict)169 match_detailed(FILE * fp, glist_t hyp, char *uttid, char *LBL, char *lbl,
170                int32 * senscale, dict_t * dict)
171 {
172     int32 ascr, lscr;
173     int32 scl;
174     gnode_t *gn;
175     srch_hyp_t *h;
176 
177     if (fp == NULL)
178         return;
179 
180     ascr = lscr = scl = 0;
181     assert(dict);
182     if (senscale) {
183         fprintf(fp, "%s:%s> %20s %5s %5s %12s %10s %10s %10s\n", LBL,
184                 uttid, "WORD", "SFrm", "EFrm", "AScr(UnNorm)", "LMScore",
185                 "AScr+LScr", "AScale");
186     }
187     else {
188         fprintf(fp, "%s:%s> %20s %5s %5s %12s %10s %10s %10s\n", LBL,
189                 uttid, "WORD", "SFrm", "EFrm", "AScr(Norm)", "LMScore",
190                 "AScr+LScr", "AScale");
191     }
192 
193     for (gn = hyp; gn; gn = gnode_next(gn)) {
194         h = (srch_hyp_t *) gnode_ptr(gn);
195 
196         if (h->id != dict_finishwid(dict) && h->id != dict_startwid(dict)) {
197 
198             scl = 0;
199 
200             if (h->id < 0 || (h->sf == h->ef))
201                 continue;
202 
203             scl += compute_scale(h->sf, h->ef, senscale);
204 
205             if (senscale) {
206                 fprintf(fp, "%s:%s> %20s %5d %5d %12d %10d %10d %10d \n",
207                         lbl, uttid, dict_wordstr(dict, h->id), h->sf,
208                         h->ef, h->ascr + scl, h->lscr,
209                         h->ascr + scl + h->lscr, scl);
210             }
211             else {
212                 fprintf(fp, "%s:%s> %20s %5d %5d %12d %10d %10d %10d\n",
213                         lbl, uttid, dict_wordstr(dict, h->id), h->sf,
214                         h->ef, h->ascr, h->lscr, h->ascr + h->lscr, scl);
215             }
216 
217             ascr += h->ascr;
218 
219             if (senscale)
220                 ascr += scl;
221 
222             lscr += h->lscr;
223         }
224     }
225 
226     fprintf(fp, "%s:%s> %20s %5s %5s %12d %10d\n", LBL, uttid,
227             "TOTAL", "", "", ascr, lscr);
228 
229 }
230 
231 /* CODE DUPLICATION! Sphinx 3.0 family of logging hyp and hyp segments */
232 /* Write hypothesis in old (pre-Nov95) NIST format */
233 void
log_hypstr(FILE * fp,srch_hyp_t * hypptr,char * uttid,int32 exact,int32 scr,dict_t * dict)234 log_hypstr(FILE * fp, srch_hyp_t * hypptr, char *uttid, int32 exact,
235            int32 scr, dict_t * dict)
236 {
237     srch_hyp_t *h;
238     s3wid_t w;
239 
240     if (fp == NULL)
241         return;
242 
243     if (!hypptr)                /* HACK!! */
244         fprintf(fp, "(null)");
245 
246     for (h = hypptr; h; h = h->next) {
247         if (h->sf != h->ef) {   /* Take care of abnormality caused by
248                                  * FSG search or various different
249                                  * reasons */
250             w = h->id;
251             if (!exact) {
252                 w = dict_basewid(dict, w);
253                 if ((w != dict->startwid) && (w != dict->finishwid)
254                     && (!dict_filler_word(dict, w)))
255                     fprintf(fp, "%s ", dict_wordstr(dict, w));
256             }
257             else
258                 fprintf(fp, "%s ", dict_wordstr(dict, w));
259         }
260     }
261     if (scr != 0)
262         fprintf(fp, " (%s %d)\n", uttid, scr);
263     else
264         fprintf(fp, " (%s)\n", uttid);
265     fflush(fp);
266 }
267 
268 
269 /*
270  * Write exact hypothesis.  Format
271  *   <id> S <scl> T <scr> A <ascr> L <lscr> {<sf> <wascr> <wlscr> <word>}... <ef>
272  * where:
273  *   scl = acoustic score scaling for entire utterance
274  *   scr = ascr + (lscr*lw+N*wip), where N = #words excluding <s>
275  *   ascr = scaled acoustic score for entire utterance
276  *   lscr = LM score (without lw or wip) for entire utterance
277  *   sf = start frame for word
278  *   wascr = scaled acoustic score for word
279  *   wlscr = LM score (without lw or wip) for word
280  *   ef = end frame for utterance.
281  */
282 void
log_hypseg(char * uttid,FILE * fp,srch_hyp_t * hypptr,int32 nfrm,int32 scl,float64 lwf,dict_t * dict,lm_t * lm,int32 unnorm)283 log_hypseg(char *uttid, FILE * fp,      /* Out: output file */
284            srch_hyp_t * hypptr, /* In: Hypothesis */
285            int32 nfrm,          /* In: #frames in utterance */
286            int32 scl,           /* In: Acoustic scaling for entire utt */
287            float64 lwf,         /* In: LM score scale-factor (in dagsearch) */
288            dict_t * dict,       /* In: dictionary */
289            lm_t * lm, int32 unnorm
290                                 /**< Whether unscaled the score back */
291     )
292 {
293     srch_hyp_t *h;
294     int32 ascr, lscr, tscr;
295 
296     if (fp == NULL)
297         return;
298 
299     ascr = lscr = tscr = 0;
300     for (h = hypptr; h; h = h->next) {
301         ascr += h->ascr;
302         if (dict_basewid(dict, h->id) != dict->startwid) {
303             lscr += lm_rawscore(lm, h->lscr);
304         }
305         else {
306             assert(h->lscr == 0);
307         }
308         tscr += h->ascr + h->lscr;
309     }
310 
311     fprintf(fp, "%s S %d T %d A %d L %d", uttid, scl, tscr, ascr, lscr);
312 
313     if (!hypptr)                /* HACK!! */
314         fprintf(fp, " (null)\n");
315     else {
316         for (h = hypptr; h; h = h->next) {
317             lscr =
318                 (dict_basewid(dict, h->id) !=
319                  dict->startwid) ? lm_rawscore(lm, h->lscr) : 0;
320             fprintf(fp, " %d %d %d %s", h->sf, h->ascr, lscr,
321                     dict_wordstr(dict, h->id));
322         }
323         fprintf(fp, " %d\n", nfrm);
324     }
325 
326     fflush(fp);
327 }
328 
329 
330 
331 /* Log hypothesis in detail with word segmentations, acoustic and LM scores  */
332 void
log_hyp_detailed(FILE * fp,srch_hyp_t * hypptr,char * uttid,char * LBL,char * lbl,int32 * senscale)333 log_hyp_detailed(FILE * fp, srch_hyp_t * hypptr, char *uttid, char *LBL,
334                  char *lbl, int32 * senscale)
335 {
336     srch_hyp_t *h;
337     int32 scale, ascr, lscr;
338 
339     if (fp == NULL)
340         return;
341 
342     ascr = 0;
343     lscr = 0;
344 
345     if (senscale) {
346         fprintf(fp, "%s:%s> %20s %5s %5s %12s %10s %10s %10s \n", LBL,
347                 uttid, "WORD", "SFrm", "EFrm", "AScr(UnNorm)", "LMScore",
348                 "AScr+LScr", "AScale");
349     }
350     else {
351         fprintf(fp, "%s:%s> %20s %5s %5s %12s %10s %10s %10s\n", LBL,
352                 uttid, "WORD", "SFrm", "EFrm", "AScr(Norm)", "LMScore",
353                 "AScr+LScr", "AScale");
354     }
355 
356     for (h = hypptr; h; h = h->next) {
357         scale = 0;
358 
359         if (h->id < 0 || (h->sf == h->ef))
360             continue;
361 
362         if (senscale)
363             scale = compute_scale(h->sf, h->ef, senscale);
364 
365 
366         if (senscale) {
367             fprintf(fp, "%s:%s> %20s %5d %5d %12d %10d %10d %10d\n", lbl,
368                     uttid, h->word, h->sf, h->ef, h->ascr + scale, h->lscr,
369                     h->ascr + scale + h->lscr, scale);
370         }
371         else {
372             fprintf(fp, "%s:%s> %20s %5d %5d %12d %10d %10d %10d\n", lbl,
373                     uttid, h->word, h->sf, h->ef, h->ascr, h->lscr,
374                     h->ascr + h->lscr, scale);
375         }
376 
377         ascr += h->ascr;
378 
379         if (senscale)
380             ascr += scale;
381 
382         lscr += h->lscr;
383     }
384 
385     fprintf(fp, "%s:%s> %20s %5s %5s %12d %10d\n", LBL, uttid,
386             "TOTAL", "", "", ascr, lscr);
387 }
388 
389 
390 static int
get_word(char ** string,char * word)391 get_word(char **string, char *word)
392 {
393     char *p = word;
394 
395     while ((**string != '\0')
396            && ((**string == '\n') || (**string == '\t')
397                || (**string == ' ')))
398         (*string)++;
399 
400     while ((**string != '\0') && (**string != '\n') && (**string != '\t')
401            && (**string != ' '))
402         *p++ = *(*string)++;
403 
404     *p = '\0';
405     return strlen(word);
406 }
407 
408 /*Code we need to incorporate into 3.6, a seg reader */
409 /*****************************************************************************/
410 
411 /*
412   %s     S 0 T    %d            A    %   d    L   %   d    %d    %d    %d    %s         %d
413 uttid          totascr+totlscr      totascr      totlscr   sf   ascr  lscr  word        nfr
414 */
415 
416 int
read_s3hypseg_line(char * line,seg_hyp_line_t * seg_hyp_line,lm_t * lm,dict_t * dict)417 read_s3hypseg_line(char *line, seg_hyp_line_t * seg_hyp_line, lm_t * lm,
418                    dict_t * dict)
419 {
420     char *p, str[128];
421     conf_srch_hyp_t *hyp_word, *tail, *g, *h;
422     int sum, t, i;
423     s3wid_t wid;
424 
425     p = line;
426 
427     if (!get_word(&p, str)) {
428         printf("failed to read sequence number in the line: %s\n", line);
429         return HYPSEG_FAILURE;
430     }
431 
432     strcpy(seg_hyp_line->seq, str);
433 
434     if (!get_word(&p, str) || strcmp(str, "S"))
435         E_FATAL("failed to read S in the line: %s\n", line);
436 
437     get_word(&p, str);
438 
439     if (!get_word(&p, str) || strcmp(str, "T"))
440         E_FATAL("failed to read T in the line: %s\n", line);
441 
442     if (!get_word(&p, str))
443         E_FATAL("failed to read ascr+lscr in the line: %s\n", line);
444 
445     sum = atoi(str);
446 
447     if (!get_word(&p, str) || strcmp(str, "A"))
448         E_FATAL("failed to read A in the line: %s\n", line);
449 
450     if (!get_word(&p, str))
451         E_FATAL("failed to read ascr in the line: %s\n", line);
452 
453     seg_hyp_line->ascr = atoi(str);
454 
455     if (!get_word(&p, str) || strcmp(str, "L"))
456         E_FATAL("failed to read L in the line: %s\n", line);
457 
458     if (!get_word(&p, str))
459         E_FATAL("failed to read lscr in the line: %s\n", line);
460 
461     seg_hyp_line->lscr = atoi(str);
462 
463 #if 0
464     if (!get_word(&p, str) || strcmp(str, "0")) {
465         E_FATAL("failed to find 0 in the line: %s\n", line);
466 
467     }
468 #endif
469 
470     if (seg_hyp_line->ascr + seg_hyp_line->lscr != sum) {
471         E_FATAL("the sum of ascr and lscr %d is wrong (%d): %s\n",
472                 seg_hyp_line->ascr + seg_hyp_line->lscr, sum, line);
473     }
474 
475     seg_hyp_line->wordlist = NULL;
476     seg_hyp_line->wordno = 0;
477     seg_hyp_line->nfr = 0;
478     seg_hyp_line->cscore = WORST_CONFIDENCE_SCORE;
479     tail = NULL;
480 
481     while (1) {
482         if (!get_word(&p, str))
483             E_FATAL("failed to read sf or nfr in the line: %s\n", line);
484 
485         t = atoi(str);
486 
487         if (!get_word(&p, str)) {
488             seg_hyp_line->nfr = t;
489             break;
490         }
491 
492         if ((hyp_word =
493              (conf_srch_hyp_t *) ckd_calloc(1,
494                                             sizeof(conf_srch_hyp_t))) ==
495             NULL
496             || (hyp_word->sh.word =
497                 (char *) ckd_calloc(1024, sizeof(char))) == NULL) {
498             E_FATAL("fail to allocate memory\n");
499         }
500 
501         hyp_word->sh.sf = t;
502         hyp_word->sh.ascr = atoi(str);
503         hyp_word->next = NULL;
504 
505         if (!get_word(&p, str))
506             E_FATAL("failed to read lscr in the line: %s\n", line);
507 
508         hyp_word->sh.lscr = atoi(str);
509 
510         if (!get_word(&p, str))
511             E_FATAL("failed to read word in the line: %s\n", line);
512 
513         strcpy(hyp_word->sh.word, str);
514         for (i = strlen(str) - 1; i >= 0; i--)
515             if (str[i] == '(')
516                 break;
517         if (i >= 0)
518             str[i] = '\0';
519 
520 
521         if (dict) {
522             wid = dict_wordid(dict, str);
523             if (wid == BAD_S3WID) {
524                 E_FATAL("String %s doesn't exists in the dictionary\n",
525                         str);
526             }
527 
528             hyp_word->sh.id = wid;
529         }
530 
531         hyp_word->compound = 0;
532         hyp_word->matchtype = 0;
533 
534         seg_hyp_line->wordno++;
535         if (seg_hyp_line->wordlist == NULL)
536             seg_hyp_line->wordlist = hyp_word;
537         else
538             tail->next = hyp_word;
539         tail = hyp_word;
540     }
541 
542 
543     if (seg_hyp_line->wordlist == NULL) {
544         printf("word list is NULL\n");
545         return HYPSEG_FAILURE;
546     }
547 
548     g = seg_hyp_line->wordlist;
549     for (h = g->next; h; h = h->next) {
550         g->sh.ef = h->sh.sf - 1;
551         g = h;
552     }
553     g->sh.ef = seg_hyp_line->nfr;
554 
555     sum = 0;
556     for (h = seg_hyp_line->wordlist; h; h = h->next)
557         sum += h->sh.ascr;
558     if (sum != seg_hyp_line->ascr) {
559         E_FATAL
560             ("the ascr of words is not equal to the ascr of utt: %s (sum %d != tot %d). \n",
561              line, sum, seg_hyp_line->ascr);
562     }
563 
564     sum = 0;
565     for (h = seg_hyp_line->wordlist; h; h = h->next)
566         sum += h->sh.lscr;
567 
568     if (sum != seg_hyp_line->lscr)
569         E_WARN
570             ("the lscr of words is not equal to the lscr of utt: %s %d %d\n",
571              seg_hyp_line->seq, sum, seg_hyp_line->lscr);
572 
573     for (h = seg_hyp_line->wordlist; h; h = h->next) {
574         if (h->sh.ef < h->sh.sf) {
575             E_FATAL("word %s ef (%d) <= sf (%d)in the line: %s\n",
576                     h->sh.word, h->sh.ef, h->sh.sf, line);
577         }
578     }
579 
580     return HYPSEG_SUCCESS;
581 }
582 
583 
584 int
free_seg_hyp_line(seg_hyp_line_t * seg_hyp_line)585 free_seg_hyp_line(seg_hyp_line_t * seg_hyp_line)
586 {
587     conf_srch_hyp_t *w, *nw;
588 
589     for (w = seg_hyp_line->wordlist; w; w = nw) {
590         nw = (conf_srch_hyp_t *) w->next;
591         free(w->sh.word);
592         free(w);
593     }
594     return HYPSEG_SUCCESS;
595 }
596