1 /* ====================================================================
2 * Copyright (c) 1999-2004 Carnegie Mellon University. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * This work was supported in part by funding from the Defense Advanced
18 * Research Projects Agency and the National Science Foundation of the
19 * United States of America, and the CMU Sphinx Speech Consortium.
20 *
21 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
22 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
25 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * ====================================================================
34 *
35 */
36 /*
37 * corpus.c -- Corpus-file related misc functions.
38 *
39 * **********************************************
40 * CMU ARPA Speech Project
41 *
42 * Copyright (c) 1996-2004 Carnegie Mellon University.
43 * ALL RIGHTS RESERVED.
44 * **********************************************
45 *
46 * HISTORY
47 *
48 * $Log$
49 * Revision 1.12 2006/02/22 19:49:25 arthchan2003
50 * Merged from SPHINX3_5_2_RCI_IRII:
51 * 1, Add structure utt_res_t, this is an utterance-based resouce
52 * structure. Add basic operation such as free and report.
53 * 2, Modify the structure of the loop in ctl_corpus to make it not so
54 * clunky. Tested with make check .
55 * 3, Completely removed ctl_process_dyn_lm, it is a product of code
56 * duplication (alright, it is written by me......)
57 * 4, Fixed doc-dox.
58 *
59 * Revision 1.11.4.3 2005/08/02 21:09:07 arthchan2003
60 * Removed error message
61 *
62 * Revision 1.11.4.2 2005/07/27 23:19:11 arthchan2003
63 * 1, Added utt_res_t structure and its methods. 2, Changed the function pointer prototype. 3, Removed the lm and mllr set process out of ctl_process
64 *
65 * Revision 1.11.4.1 2005/07/26 03:14:17 arthchan2003
66 * Removed ctl_process_dyn_lm. One of my sin.
67 *
68 * Revision 1.11 2005/06/21 20:44:34 arthchan2003
69 * 1, Fixed doxygen documentation, 2, Add the $ keyword.
70 *
71 *
72 * 09-Dec-1999 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon
73 * Added ctl_process_utt ().
74 *
75 * 01-Mar-1999 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon
76 * Added check for already existing file extension in ctl_infile().
77 *
78 * 23-Mar-1998 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon
79 * Added a general purpose data argument to ctl_process() and its function
80 * argument func.
81 *
82 * 22-Nov-1997 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon
83 * Added an optional validation function argument and an optional
84 * duplicate-resolution function argument to both corpus_load_headid() and
85 * corpus_load_tailid().
86 *
87 * 25-Oct-1997 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
88 * Started.
89 */
90
91
92 #include <string.h>
93 #ifndef WIN32
94 #include <unistd.h>
95 #else
96 #include <stdlib.h>
97 #endif
98
99 #include "filename.h"
100 #include "pio.h"
101 #include "corpus.h"
102 #include "kb.h"
103
104 #if (defined(WIN32) && !defined(__CYGWIN__))
105 #define SLEEP_SEC(sec) (0) /* Why doesn't Sleep((sec)*1000) work? */
106 #else
107 #define SLEEP_SEC(sec) sleep(sec) /* sec must be integer */
108 #endif
109
110 utt_res_t *
new_utt_res()111 new_utt_res()
112 {
113 utt_res_t *ur;
114 ur = ckd_calloc(1, sizeof(utt_res_t));
115 utt_res_set_uttfile(ur, NULL);
116 utt_res_set_lmname(ur, NULL);
117 utt_res_set_fsgname(ur, NULL);
118 utt_res_set_regmatname(ur, NULL);
119 utt_res_set_cb2mllrname(ur, NULL);
120
121 return ur;
122 }
123
124 void
free_utt_res(utt_res_t * ur)125 free_utt_res(utt_res_t * ur)
126 {
127 ckd_free(ur);
128 }
129
130 void
report_utt_res(utt_res_t * ur)131 report_utt_res(utt_res_t * ur)
132 {
133 E_INFO_NOFN("Utt res, report:\n");
134 if (ur->uttfile != NULL)
135 E_INFO_NOFN("uttfile %s\n", ur->uttfile);
136 if (ur->lmname != NULL)
137 E_INFO_NOFN("lmname %s\n", ur->lmname);
138 if (ur->fsgname != NULL)
139 E_INFO_NOFN("fsgname %s\n", ur->fsgname);
140 if (ur->regmatname != NULL)
141 E_INFO_NOFN("regmatname %s\n", ur->regmatname);
142 if (ur->cb2mllrname != NULL)
143 E_INFO_NOFN("cb2mllrname %s\n", ur->cb2mllrname);
144
145
146 }
147
148 corpus_t *
corpus_load_headid(const char * file,int32 (* validate)(char * str),int32 (* dup_resolve)(char * s1,char * s2))149 corpus_load_headid(const char *file,
150 int32(*validate) (char *str),
151 int32(*dup_resolve) (char *s1, char *s2))
152 {
153 FILE *fp;
154 char line[16384], wd[4096], *id;
155 int32 j, k, m, n;
156 corpus_t *corp;
157
158 E_INFO("Loading corpus (%s)\n", file);
159
160 if ((fp = fopen(file, "r")) == NULL)
161 E_FATAL_SYSTEM("fopen(%s,r) failed\n", file);
162
163 corp = (corpus_t *) ckd_calloc(1, sizeof(corpus_t));
164
165 n = 0;
166 while (fgets(line, sizeof(line), fp) != NULL) {
167 /* Skip empty lines */
168 if (sscanf(line, "%s", wd) == 1)
169 n++;
170 }
171 rewind(fp);
172
173 corp->ht = hash_table_new(n, HASH_CASE_YES);
174 corp->n = 0;
175 corp->str = (char **) ckd_calloc(n, sizeof(char *));
176
177 n = 0;
178 while (fgets(line, sizeof(line), fp) != NULL) {
179 /* Skip blank lines */
180 if (sscanf(line, "%s%n", wd, &k) != 1)
181 continue;
182
183 /* Eliminate the line-terminating newline */
184 j = strlen(line);
185 if ((j > 0) && (line[j - 1] == '\n'))
186 line[j - 1] = '\0';
187
188 /* Validate if a validation function is given */
189 if (validate && (!(*validate) (line + k))) {
190 E_INFO("Corpus validation %s failed; skipping\n", wd);
191 continue;
192 }
193
194 id = ckd_salloc(wd);
195 if ((m = (long) hash_table_enter(corp->ht, id, (void *)(long)n)) != n) {
196 /* Duplicate entry */
197 if (!dup_resolve)
198 E_FATAL
199 ("corpus_load_headid(%s) failed; duplicate ID: %s\n",
200 file, id);
201 else {
202 /* Invoke the application provided duplicate resolver function */
203 if ((j = (*dup_resolve) (corp->str[m], line + k)) < 0)
204 E_FATAL
205 ("corpus_load_headid(%s) failed; duplicate ID: %s\n",
206 file, id);
207 ckd_free(id);
208 if (j > 0) {
209 /* Overwrite the original with the new entry */
210 ckd_free(corp->str[m]);
211 corp->str[m] = ckd_salloc(line + k);
212 }
213 else {
214 /* Retain the original entry, discard the new one */
215 }
216 }
217 }
218 else {
219 /* Fill in new entry */
220 corp->str[n] = ckd_salloc(line + k);
221 n++;
222 }
223 }
224 corp->n = n;
225
226 fclose(fp);
227
228 E_INFO("%s: %d entries\n", file, n);
229
230 return corp;
231 }
232
233
234 static int32
sep_tailid(char * line,char * uttid)235 sep_tailid(char *line, char *uttid)
236 {
237 int32 i, k, l;
238
239 l = strlen(line);
240 uttid[0] = '\0';
241
242 /* Find last close-paren */
243 for (i = l - 1; (i >= 0) && ((line[i] == '\n') || (line[i] == ' ')
244 || (line[i] == '\t')); --i);
245 if ((i < 0) || (line[i] != ')')) /* Missing uttid */
246 return -1;
247 k = i;
248
249 /* Find closest open-paren; no spaces allowed in uttid */
250 for (--i; (i >= 0) && (line[i] != ' ') && (line[i] != '\t')
251 && (line[i] != '('); --i);
252 if ((i < 0) || (k - i < 2) || (line[i] != '(')) /* Empty or missing uttid */
253 return -1;
254
255 /* Remove parentheses and copy uttid */
256 line[k] = '\0';
257 strcpy(uttid, line + i + 1);
258
259 /* Strip uttid from line */
260 line[i] = '\0';
261
262 return 0;
263 }
264
265
266 corpus_t *
corpus_load_tailid(const char * file,int32 (* validate)(char * str),int32 (* dup_resolve)(char * s1,char * s2))267 corpus_load_tailid(const char *file,
268 int32(*validate) (char *str),
269 int32(*dup_resolve) (char *s1, char *s2))
270 {
271 FILE *fp;
272 char line[16384], uttid[4096], *id;
273 int32 j, m, n;
274 corpus_t *corp;
275
276 E_INFO("Loading corpus (%s)\n", file);
277
278 if ((fp = fopen(file, "r")) == NULL)
279 E_FATAL_SYSTEM("fopen(%s,r) failed\n", file);
280
281 corp = (corpus_t *) ckd_calloc(1, sizeof(corpus_t));
282
283 n = 0;
284 while (fgets(line, sizeof(line), fp) != NULL) {
285 /* Skip empty lines */
286 if (sscanf(line, "%s", uttid) == 1)
287 n++;
288 }
289 rewind(fp);
290
291 corp->ht = hash_table_new(n, 0 /* Not no-case */ );
292 corp->n = 0;
293 corp->str = (char **) ckd_calloc(n, sizeof(char *));
294
295 n = 0;
296 while (fgets(line, sizeof(line), fp) != NULL) {
297 /* Skip blank lines */
298 if (sscanf(line, "%s", uttid) < 1)
299 continue;
300
301 /* Look for a (uttid) at the end */
302 if (sep_tailid(line, uttid) < 0)
303 E_FATAL("corpus_load_tailid(%s) failed; bad line: %s\n", file,
304 line);
305
306 /* Validate if a validation function is given */
307 if (validate && (!(*validate) (line))) {
308 E_INFO("Corpus validation %s failed; skipping\n", uttid);
309 continue;
310 }
311
312 id = ckd_salloc(uttid);
313 if ((m = (long) hash_table_enter(corp->ht, id, (void *)(long)n)) != n) {
314 /* Duplicate entry */
315 if (!dup_resolve)
316 E_FATAL
317 ("corpus_load_tailid(%s) failed; duplicate ID: %s\n",
318 file, id);
319 else {
320 /* Invoke the application provided duplicate resolver function */
321 if ((j = (*dup_resolve) (corp->str[m], line)) < 0)
322 E_FATAL
323 ("corpus_load(tailid(%s) failed; duplicate ID: %s\n",
324 file, id);
325 ckd_free(id);
326 if (j > 0) {
327 /* Overwrite the original with the new entry */
328 ckd_free(corp->str[m]);
329 corp->str[m] = ckd_salloc(line);
330 }
331 else {
332 /* Retain the original entry, discard the new one */
333 }
334 }
335 }
336 else {
337 /* Fill in new entry */
338 corp->str[n] = ckd_salloc(line);
339 n++;
340 }
341 }
342 corp->n = n;
343
344 fclose(fp);
345
346 E_INFO("%s: %d entries\n", file, n);
347
348 return corp;
349 }
350
351
352 char *
corpus_lookup(corpus_t * corp,const char * id)353 corpus_lookup(corpus_t * corp, const char *id)
354 {
355 void *val;
356 int32 n;
357
358 if (hash_table_lookup(corp->ht, id, &val) < 0)
359 return NULL;
360 n = (int32)(long)val;
361
362 assert((n >= 0) && (n < corp->n));
363 return (corp->str[n]);
364 }
365
366
367 #if _CORPUS_TEST_
main(int32 argc,char * argv[])368 main(int32 argc, char *argv[])
369 {
370 corpus_t *ch, *ct;
371 char id[4096], *str;
372
373 if (argc != 3)
374 E_FATAL("Usage: %s headid-corpusfile tailid-corpusfile\n",
375 argv[0]);
376
377 ch = corpus_load_headid(argv[1], NULL, NULL);
378 ct = corpus_load_tailid(argv[2], NULL, NULL);
379 for (;;) {
380 printf("> ");
381 scanf("%s", id);
382
383 str = corpus_lookup(ch, id);
384 if (str == NULL)
385 printf("%s Not found in 1\n");
386 else
387 printf("%s(1): %s\n", id, str);
388
389 str = corpus_lookup(ct, id);
390 if (str == NULL)
391 printf("%s Not found in 2\n");
392 else
393 printf("%s(2): %s\n", id, str);
394 }
395 }
396 #endif
397
398
399 int32
ctl_read_entry(FILE * fp,char * uttfile,int32 * sf,int32 * ef,char * uttid)400 ctl_read_entry(FILE * fp, char *uttfile, int32 * sf, int32 * ef,
401 char *uttid)
402 {
403 char line[16384];
404 char base[16384];
405 int32 k;
406
407 do {
408 if (fgets(line, sizeof(line), fp) == NULL)
409 return -1;
410 if (line[0] == '#')
411 k = 0;
412 else
413 k = sscanf(line, "%s %d %d %s", uttfile, sf, ef, uttid);
414 } while (k <= 0);
415
416 if ((k == 2) || ((k >= 3) && ((*sf >= *ef) || (*sf < 0))))
417 E_FATAL("Error in ctlfile: %s\n", line);
418
419 if (k < 4) {
420 /* Create utt-id from mfc-filename (and sf/ef if specified) */
421 path2basename(uttfile, base);
422 /* strip_fileext (base, uttid); */
423 strcpy(uttid, base);
424
425 if (k == 3) {
426 k = strlen(uttid);
427 sprintf(uttid + k, "_%d_%d", *sf, *ef);
428 }
429 else {
430 *sf = 0;
431 *ef = -1; /* Signifies "until EOF" */
432 }
433 }
434
435 return 0;
436 }
437
438 #if 0
439 ptmr_t
440 ctl_process(char *ctlfile, char *ctlmllrfile, int32 nskip, int32 count,
441 void (*func) (void *kb, char *uttfile, int32 sf, int32 ef,
442 char *uttid), void *kb)
443 {
444 FILE *fp, *mllrfp;
445 char uttfile[16384], uttid[4096];
446 char regmatfile[4096], cb2mllrfile[4096];
447 int32 sf, ef;
448 ptmr_t tm;
449
450 mllrfp = NULL;
451 E_INFO("Batch mode recognition without dynamic LM\n");
452
453 if (ctlfile) {
454 if ((fp = fopen(ctlfile, "r")) == NULL)
455 E_FATAL_SYSTEM("fopen(%s,r) failed\n", ctlfile);
456 }
457 else
458 fp = stdin;
459
460 if (ctlmllrfile) {
461 if ((mllrfp = fopen(ctlmllrfile, "r")) == NULL)
462 E_FATAL_SYSTEM("fopen(%s,r) failed\n", ctlmllrfile);
463 }
464
465 ptmr_init(&tm);
466
467 if (nskip > 0) {
468 E_INFO("Skipping %d entries at the beginning of %s\n", nskip,
469 ctlfile);
470
471 for (; nskip > 0; --nskip) {
472 if (ctl_read_entry(fp, uttfile, &sf, &ef, uttid) < 0) {
473 fclose(fp);
474 return tm;
475 }
476 }
477
478 if (ctlmllrfile) {
479 for (; nskip > 0; --nskip) {
480 if (ctl_read_entry(fp, regmatfile, &sf, &ef, cb2mllrfile) <
481 0) {
482 E_ERROR
483 ("MLLR cannot be read when skipping the %d-th sentence\n",
484 nskip);
485 fclose(fp);
486 return tm;
487 }
488 }
489 }
490 }
491
492 for (; count > 0; --count) {
493 if (ctl_read_entry(fp, uttfile, &sf, &ef, uttid) < 0)
494 break;
495
496 if (ctlmllrfile) {
497 int32 tmp1, tmp2;
498
499 if (ctl_read_entry
500 (mllrfp, regmatfile, &tmp1, &tmp2, cb2mllrfile) < 0) {
501 E_ERROR
502 ("MLLR cannot be read when counting the %d-th sentence\n",
503 count);
504 break;
505 }
506 if (tmp2 == -1)
507 strcpy(cb2mllrfile, ".1cls.");
508 }
509
510 /* Process this utterance */
511 ptmr_start(&tm);
512 if (func) {
513 if (ctlmllrfile)
514 kb_setmllr(regmatfile, cb2mllrfile, kb);
515 (*func) (kb, uttfile, sf, ef, uttid);
516 }
517 ptmr_stop(&tm);
518
519 E_INFO
520 ("%s: %6.1f sec CPU, %6.1f sec Clk; TOT: %8.1f sec CPU, %8.1f sec Clk\n\n",
521 uttid, tm.t_cpu, tm.t_elapsed, tm.t_tot_cpu,
522 tm.t_tot_elapsed);
523
524
525 ptmr_reset(&tm);
526 }
527
528 if (fp)
529 fclose(fp);
530
531
532 return tm;
533 }
534 #endif
535
536 ptmr_t
ctl_process(const char * ctlfile,const char * ctllmfile,const char * ctlmllrfile,int32 nskip,int32 count,void (* func)(void * kb,utt_res_t * ur,int32 sf,int32 ef,char * uttid),void * kb)537 ctl_process(const char *ctlfile, const char *ctllmfile, const char *ctlmllrfile, int32 nskip,
538 int32 count, void (*func) (void *kb, utt_res_t * ur, int32 sf,
539 int32 ef, char *uttid), void *kb)
540 {
541 FILE *fp;
542 FILE *ctllmfp;
543 FILE *ctlmllrfp;
544 char uttfile[16384], uttid[4096];
545 char lmname[4096];
546 char regmatname[4096], cb2mllrname[4096];
547 char tmp[4096];
548 int32 sf, ef;
549 utt_res_t *ur;
550 ptmr_t tm;
551 kb_t *k;
552
553 k = (kb_t *) kb;
554
555 ctllmfp = NULL;
556 ctlmllrfp = NULL;
557 ur = new_utt_res();
558
559 if (ctlfile) {
560 if ((fp = fopen(ctlfile, "r")) == NULL)
561 E_FATAL_SYSTEM("fopen(%s,r) failed\n", ctlfile);
562 }
563 else
564 fp = stdin;
565
566 if (ctllmfile) {
567 E_INFO("LM is used in this session\n");
568 if ((ctllmfp = fopen(ctllmfile, "r")) == NULL)
569 E_FATAL_SYSTEM("fopen(%s,r) failed\n", ctllmfile);
570 }
571
572 if (ctlmllrfile) {
573 E_INFO("MLLR is used in this session\n");
574 if ((ctlmllrfp = fopen(ctlmllrfile, "r")) == NULL)
575 E_FATAL_SYSTEM("fopen(%s,r) failed\n", ctlmllrfile);
576 }
577
578 ptmr_init(&tm);
579
580 if (nskip > 0) {
581 E_INFO("Skipping %d entries at the beginning of %s\n", nskip,
582 ctlfile);
583
584 for (; nskip > 0; --nskip) {
585 if (ctl_read_entry(fp, uttfile, &sf, &ef, uttid) < 0) {
586 fclose(fp);
587 return tm;
588 }
589
590 /*This checks the size of the control file of the lm in batch mode */
591 if (ctllmfile) {
592 if (ctl_read_entry(ctllmfp, lmname, &sf, &ef, tmp) < 0) {
593 fclose(ctllmfp);
594 E_ERROR
595 ("An LM control file is specified but LM cannot be read when skipping the %d-th sentence\n",
596 nskip);
597 return tm;
598 }
599 }
600
601 /*This checks the size of the control file of the mllr in batch mode */
602 if (ctlmllrfile) {
603 if (ctl_read_entry(ctlmllrfp, regmatname, &sf, &ef, tmp) <
604 0) {
605 fclose(ctlmllrfp);
606 E_ERROR
607 ("A MLLR control file is specified but MLLR cannot be read when skipping the %d-th sentence\n",
608 nskip);
609 return tm;
610 }
611 }
612
613 }
614 }
615
616 for (; count > 0; --count) {
617 int32 tmp1, tmp2;
618
619
620 if (ctl_read_entry(fp, uttfile, &sf, &ef, uttid) < 0)
621 break;
622
623 /*This checks the size of the control file in batch mode */
624 if (ctllmfile) {
625 if (ctl_read_entry(ctllmfp, lmname, &tmp1, &tmp2, tmp) < 0) {
626 fclose(ctllmfp);
627 E_ERROR
628 ("LM control file is specified but LM cannot be read when counting the %d-th sentence\n",
629 count);
630 break;
631 }
632 }
633
634 if (ctlmllrfile) {
635 if (ctl_read_entry
636 (ctlmllrfp, regmatname, &tmp1, &tmp2, cb2mllrname) < 0) {
637 E_ERROR
638 ("MLLR control file is specified but MLLR cannot be read when counting the %d-th sentence\n",
639 count);
640 break;
641 }
642 if (tmp2 == -1)
643 strcpy(cb2mllrname, ".1cls.");
644 }
645
646
647 /* Process this utterance */
648 ptmr_start(&tm);
649 if (func) {
650 utt_res_set_uttfile(ur, uttfile);
651 if (ctllmfile)
652 utt_res_set_lmname(ur, lmname);
653 if (ctlmllrfile) {
654 utt_res_set_regmatname(ur, regmatname);
655 utt_res_set_cb2mllrname(ur, cb2mllrname);
656 }
657 (*func) (kb, ur, sf, ef, uttid);
658 }
659 ptmr_stop(&tm);
660
661 E_INFO
662 ("%s: %6.1f sec CPU, %6.1f sec Clk; TOT: %8.1f sec CPU, %8.1f sec Clk\n\n",
663 uttid, tm.t_cpu, tm.t_elapsed, tm.t_tot_cpu,
664 tm.t_tot_elapsed);
665
666
667 ptmr_reset(&tm);
668 }
669
670 if (fp)
671 fclose(fp);
672 if (ctllmfp)
673 fclose(ctllmfp);
674 if (ctlmllrfp)
675 fclose(ctlmllrfp);
676 if (ur)
677 ckd_free(ur);
678
679 return tm;
680 }
681
682
683
684 ptmr_t
ctl_process_utt(const char * uttfile,int32 count,void (* func)(void * kb,utt_res_t * ur,int32 sf,int32 ef,char * uttid),void * kb)685 ctl_process_utt(const char *uttfile, int32 count,
686 void (*func) (void *kb, utt_res_t * ur, int32 sf, int32 ef,
687 char *uttid), void *kb)
688 {
689 char uttid[4096];
690 char base[16384];
691 int32 i, c;
692 int32 ts, newts;
693 ptmr_t tm;
694 utt_res_t *ur;
695
696
697 ptmr_init(&tm);
698 ur = new_utt_res();
699 path2basename(uttfile, base);
700 /* strip_fileext() copies base to uttid. So, copying uttid to base
701 * is redundant if strip_fileext() is not called.
702 */
703 /*
704 strip_fileext (base, uttid);
705 strcpy (base, uttid);
706 */
707
708 ts = -1;
709 for (c = 0; c < count; c++) {
710 /* Wait for uttfile to change from previous iteration */
711 for (i = 0;; i++) {
712 newts = stat_mtime(uttfile);
713 if ((newts >= 0) && (newts != ts))
714 break;
715
716 if (i == 0)
717 E_INFO("Waiting for %s, count %d, c %d\n", uttfile, count,
718 c);
719 SLEEP_SEC(1);
720 }
721 ts = newts;
722
723 /* Form uttid */
724 sprintf(uttid, "%s_%08d", base, c);
725
726 /* Process this utterance */
727 ptmr_start(&tm);
728 if (func) {
729 utt_res_set_uttfile(ur, uttfile);
730
731 (*func) (kb, ur, 0, -1, uttid);
732 }
733 ptmr_stop(&tm);
734
735 E_INFO
736 ("%s: %6.1f sec CPU, %6.1f sec Clk; TOT: %8.1f sec CPU, %8.1f sec Clk\n\n",
737 uttid, tm.t_cpu, tm.t_elapsed, tm.t_tot_cpu,
738 tm.t_tot_elapsed);
739
740 ptmr_reset(&tm);
741 }
742
743 if (ur)
744 free_utt_res(ur);
745 return tm;
746 }
747
748
749 void
ctl_infile(char * file,const char * dir,const char * ext,const char * utt)750 ctl_infile(char *file, const char *dir, const char *ext, const char *utt)
751 {
752 int32 l1, l2;
753
754 assert(utt);
755
756 if (ext && (ext[0] != '\0')) {
757 l1 = strlen(ext);
758 l2 = strlen(utt);
759 if ((l2 > l1) && (utt[l2 - l1 - 1] == '.')
760 && (strcmp(utt + (l2 - l1), ext) == 0))
761 ext = NULL; /* utt already has the desired extension */
762 }
763
764 if ((utt[0] != '/') && dir) {
765 /* Dir specified for relative uttfile pathname */
766 if (ext && (ext[0] != '\0'))
767 sprintf(file, "%s/%s.%s", dir, utt, ext);
768 else
769 sprintf(file, "%s/%s", dir, utt);
770 }
771 else {
772 if (ext && (ext[0] != '\0'))
773 sprintf(file, "%s.%s", utt, ext);
774 else
775 strcpy(file, utt);
776 }
777 }
778
779
780 void
ctl_outfile(char * file,const char * dir,const char * ext,const char * utt,const char * uttid)781 ctl_outfile(char *file, const char *dir, const char *ext, const char *utt, const char *uttid)
782 {
783 int32 k;
784
785 k = strlen(dir);
786
787 if ((k > 4) && (strcmp(dir + k - 4, ",CTL") == 0)) { /* HACK!! Hardwired ,CTL */
788 if (utt[0] != '/') {
789 strcpy(file, dir);
790 file[k - 4] = '/';
791 strcpy(file + k - 3, utt);
792 }
793 else
794 strcpy(file, utt);
795 }
796 else {
797 strcpy(file, dir);
798 file[k] = '/';
799 strcpy(file + k + 1, uttid);
800 }
801
802 if (ext && (ext[0] != '\0')) {
803 strcat(file, ".");
804 strcat(file, ext);
805 }
806 }
807