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