1
/* ====================================================================
2
* Copyright (c) 2000 Carnegie Mellon University. All rights
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
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
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.
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.
33
* ====================================================================
36
/*********************************************************************
37
* Various functions used in mk_mdef_gen
40
* Rita Singh (rsingh@cs.cmu.edu)
41
*********************************************************************/
45
#include <s3/acmod_set.h>
46
#include <s3/model_def_io.h>
49
#include <sphinxbase/ckd_alloc.h>
50
#include <sphinxbase/pio.h>
51
#include <sphinxbase/cmd_ln.h>
52
#include <sphinxbase/err.h>
60
#include "parse_cmd_ln.h"
65
#define IS_FILLER(X) ((X[0]=='+'||strcmp(X,"SIL")==0) ? 1 : 0)
68
static const char* wordpos2str(word_posn_t wordpos, int ignore_wordpos);
70
int32 make_ci_list_frm_mdef(const char *mdeffile,
76
int32 nciphns, id, maxphnsize, phnsize;
79
if (model_def_read(&mdef, mdeffile) != S3_SUCCESS)
80
E_ERROR("Unable to read mdef file %s\n",mdeffile);
81
*cilistsize = nciphns = mdef->acmod_set->n_ci;
83
/* Find phone length */
85
for (id = 0; id < nciphns; id++){
86
phnsize = strlen(acmod_set_id2name(mdef->acmod_set,id));
87
if (phnsize > maxphnsize) maxphnsize = phnsize;
89
*CIlist = cilist = (char**)ckd_calloc_2d(nciphns,maxphnsize+1,sizeof(char));
90
for (id = 0; id < nciphns; id++){
91
strcpy(cilist[id],acmod_set_id2name(mdef->acmod_set,id));
98
int32 make_ci_list_cd_hash_frm_phnlist(const char *phnlist,
101
hashelement_t ***CDhash,
104
char bphn[1024],lctx[1024], rctx[1024], wdpos[1024];
105
char **cilist, *silence="SIL";
106
lineiter_t *line = NULL;
107
heapelement_t **heap=NULL, *addciphone;
108
hashelement_t **tphnhash, *tphnptr;
109
phnhashelement_t **phnhash, *phnptr;
111
int32 swdtphs, bwdtphs, ewdtphs, iwdtphs, maxphnsize, phnsize;
112
int32 heapsize, i, nciphns, nwds;
115
fp = fopen(phnlist,"r");
116
if (fp==NULL) E_FATAL("Unable to open %s for reading\n",phnlist);
118
/* Initially hash everything to remove duplications */
119
phnhash = (phnhashelement_t**)calloc(PHNHASHSIZE,sizeof(phnhashelement_t*));
120
tphnhash = (hashelement_t**) ckd_calloc(HASHSIZE, sizeof(hashelement_t*));
122
swdtphs = bwdtphs = ewdtphs = iwdtphs = 0;
123
/* Always install SIL in phonelist */
124
phninstall(silence,phnhash);
126
for (line = lineiter_start_clean(fp); line; line = lineiter_next(line)) {
128
nwds = sscanf(line->buf,"%s %s %s %s",bphn,lctx,rctx,wdpos);
130
if (nwds != 1 && nwds != 3 && nwds != 4)
131
E_FATAL("Incorrect format in triphone file %s\n%s\n",phnlist,line->buf);
132
if (strcmp(bphn,"-") == 0)
133
E_FATAL("Bad entry triphone file %s\n%s\n",phnlist,line->buf);
135
if (nwds == 1 || (!strcmp(lctx,"-") && !strcmp(rctx,"-"))) {
136
phnsize = strlen(bphn);
137
if (phnsize > maxphnsize) maxphnsize = phnsize;
138
phninstall(bphn,phnhash);
141
if (nwds == 3) strcpy(wdpos,"i"); /* default */
142
if (!strcmp(lctx,"-") && !strcmp(rctx,"-") && !strcmp(wdpos,"-")){
143
E_WARN("Bad entry triphone file %s\n%s\n",phnlist,line->buf);
146
if (IS_FILLER(lctx) || IS_FILLER(rctx)){
147
E_WARN("Fillers in triphone, skipping:\n%s\n",line->buf);
150
if (!strcmp(wdpos,"i") && !strcmp(wdpos,"b") &&
151
!strcmp(wdpos,"e") && !strcmp(wdpos,"s")){
152
E_WARN("Bad word position type %s in triphone list\n",wdpos);
153
E_WARN("Mapping it to word internal triphone\n");
156
tphnptr = install(bphn,lctx,rctx,wdpos,tphnhash);
157
if (tphnptr->dictcount == 0){
158
if (strcmp(wdpos,"s")==0) swdtphs++;
159
else if (strcmp(wdpos,"b")==0) bwdtphs++;
160
else if (strcmp(wdpos,"e")==0) ewdtphs++;
161
else if (strcmp(wdpos,"i")==0) iwdtphs++;
162
tphnptr->dictcount++;
168
/* Heap sort CI phones */
170
for (i = 0; i < PHNHASHSIZE; i++) {
172
while (phnptr != NULL) {
173
addciphone = (heapelement_t *) ckd_calloc(1,sizeof(heapelement_t));
174
addciphone->basephone = strdup(phnptr->phone);
175
heapsize = insert(&heap, heapsize, addciphone);
176
phnptr = phnptr->next;
179
freephnhash(phnhash);
180
*cilistsize = nciphns = heapsize;
181
*CIlist = cilist = (char**)ckd_calloc_2d(nciphns,maxphnsize+1,sizeof(char));
182
for (i = 0; i < nciphns; i++){
183
addciphone = yanktop(&heap,heapsize,&heapsize);
184
strcpy(cilist[i],addciphone->basephone);
185
free_heapelement(addciphone);
187
assert(heapsize == 0);
189
E_INFO("%d single word triphones in input phone list\n",swdtphs);
190
E_INFO("%d word beginning triphones in input phone list\n",bwdtphs);
191
E_INFO("%d word internal triphones in input phone list\n",iwdtphs);
192
E_INFO("%d word ending triphones in input phone list\n",ewdtphs);
195
*NCDphones = swdtphs + bwdtphs + iwdtphs + ewdtphs;
201
int32 make_ci_list_cd_hash_frm_mdef(const char *mdeffile,
204
hashelement_t ***CDhash,
207
char bphn[1024],lctx[1024], rctx[1024], wdpos[1024];
209
hashelement_t **tphnhash, *tphnptr;
211
int32 swdtphs, bwdtphs, ewdtphs, iwdtphs, maxphnsize, phnsize;
212
int32 nciphns, id, n_acmod;
215
if (model_def_read(&mdef, mdeffile) != S3_SUCCESS)
216
E_ERROR("Unable to read mdef file %s\n",mdeffile);
217
*cilistsize = nciphns = mdef->acmod_set->n_ci;
218
n_acmod = acmod_set_n_acmod(mdef->acmod_set);
220
/* Find Max phone length */
222
for (id = 0; id < nciphns; id++){
223
phnsize = strlen(acmod_set_id2name(mdef->acmod_set,id));
224
if (phnsize > maxphnsize) maxphnsize = phnsize;
226
*CIlist = cilist = (char**)ckd_calloc_2d(nciphns,maxphnsize+1,sizeof(char));
227
for (id = 0; id < nciphns; id++){
228
strcpy(cilist[id],acmod_set_id2name(mdef->acmod_set,id));
231
tphnhash = (hashelement_t**) ckd_calloc(HASHSIZE, sizeof(hashelement_t*));
232
swdtphs = bwdtphs = ewdtphs = iwdtphs = 0;
233
for (;id < n_acmod; id++){
234
sscanf(acmod_set_id2name(mdef->acmod_set, id),"%s %s %s %s",
235
bphn,lctx,rctx,wdpos);
236
tphnptr = install(bphn,lctx,rctx,wdpos,tphnhash);
237
if (tphnptr->dictcount == 0){
238
if (strcmp(wdpos,"s")==0) swdtphs++;
239
else if (strcmp(wdpos,"b")==0) bwdtphs++;
240
else if (strcmp(wdpos,"e")==0) ewdtphs++;
241
else if (strcmp(wdpos,"i")==0) iwdtphs++;
242
tphnptr->dictcount++;
246
E_INFO("%d single word triphones in triphone list\n",swdtphs);
247
E_INFO("%d word beginning triphones in triphone list\n",bwdtphs);
248
E_INFO("%d word internal triphones in triphone list\n",iwdtphs);
249
E_INFO("%d word ending triphones in triphone list\n",ewdtphs);
252
*NCDphones = swdtphs + bwdtphs + iwdtphs + ewdtphs;
258
int32 read_dict(const char *dictfile, const char *fillerdict,
259
dicthashelement_t ***dicthash)
262
const char *dictfn[2];
263
lineiter_t *liter = NULL;
264
char *dictword, *word, *phone, *tphn;
265
dicthashelement_t **lhash, *sptr;
266
int32 maxphnlen, vocabsiz=0, nphns, numdicts, idict;
269
numdicts = 1; dictfn[0] = dictfile;
270
if (fillerdict != NULL){
271
dictfn[1] = fillerdict;
275
lhash = (dicthashelement_t**)calloc(DICTHASHSIZE,sizeof(dicthashelement_t));
276
if (lhash == NULL) E_FATAL("Unable to allocate space for dictionary\n");
278
/* Create hash table with dictionary words as entries */
279
for (idict = 0; idict < numdicts; idict++){
280
E_INFO("Reading dict %s\n",dictfn[idict]);
281
if ((dict = fopen(dictfn[idict],"r")) == NULL)
282
E_FATAL_SYSTEM("Unable to open dictionary %s", dictfile);
285
for (liter = lineiter_start_clean(dict); liter; liter = lineiter_next(liter)) {
287
if (liter->buf[0] == 0) {
288
E_WARN("Empty line %d in the dictionary file %s\n",
289
lineiter_lineno(liter), dictfn[idict]);
293
dictsent = strdup(liter->buf);
294
if ((dictword = strtok(dictsent, " \t\n")) == NULL)
295
E_FATAL("Empty line in dictionary!\n");
297
if ((sptr = dictinstall(dictword,lhash)) == NULL)
298
E_FATAL("Unable to install dict word %s\n",dictword);
300
if (sptr->nphns != 0)
301
E_FATAL("Duplicate entry for %s in dictionary\n",dictword);
303
/* Count number of phones in pronunciation */
305
for(nphns=0; (tphn=strtok(NULL," \t\n")) != NULL; nphns++){
306
if (strlen(tphn) > maxphnlen) maxphnlen = strlen(tphn);
309
E_FATAL("Dictionary word %s has no pronunciation\n",dictword);
310
sptr->nphns = nphns; maxphnlen++;
311
sptr->phones = (char**)ckd_calloc_2d(nphns,maxphnlen,sizeof(char));
313
word = strtok(liter->buf," \t\n");
314
for(nphns=0;(phone = strtok(NULL," \t\n")) != NULL;nphns++)
315
strcpy(sptr->phones[nphns],phone);
322
E_INFO("%d words in dict %s\n", vocabsiz, dictfn[idict]);
327
lineiter_free(liter);
332
int32 make_dict_triphone_list (dicthashelement_t **dicthash,
333
hashelement_t ***triphonehash,
336
hashelement_t **tphnhash, *tphnptr;
337
dicthashelement_t *word_el;
338
phnhashelement_t *bphnptr, **bphnhash, *ephnptr, **ephnhash;
339
char *bphn, *lctx, *rctx;
341
char *silencephn = "SIL";
342
int32 totaltphs, totwds, bwdtphs, ewdtphs, iwdtphs, swdtphs, lnphns;
345
tphnhash = (hashelement_t**) ckd_calloc(HASHSIZE, sizeof(hashelement_t));
346
bphnhash = (phnhashelement_t**)calloc(PHNHASHSIZE,sizeof(phnhashelement_t));
347
ephnhash = (phnhashelement_t**)calloc(PHNHASHSIZE,sizeof(phnhashelement_t));
348
if (bphnhash == NULL || ephnhash == NULL)
349
E_FATAL("Unable to alloc %d size phone hashtables!\n",(int)PHNHASHSIZE);
351
/*First count all phones that can begin or end a word (SIL can by default)*/
352
phninstall(silencephn,bphnhash);
353
phninstall(silencephn,ephnhash);
354
for (i = 0; i < DICTHASHSIZE; i++){
355
word_el = dicthash[i];
356
while (word_el != NULL){
357
if (!IS_FILLER(word_el->phones[0]))
358
phninstall(word_el->phones[0],bphnhash);
359
if (!IS_FILLER(word_el->phones[word_el->nphns - 1]))
360
phninstall(word_el->phones[word_el->nphns - 1],ephnhash);
361
word_el = word_el->next;
365
/* Scan dictionary and make triphone list */
366
totwds = bwdtphs = ewdtphs = iwdtphs = swdtphs = 0;
367
for (i = 0; i < DICTHASHSIZE; i++){
368
word_el = dicthash[i];
369
while (word_el != NULL){
371
lnphns = word_el->nphns;
373
wpos = wordpos2str(WORD_POSN_SINGLE, ignore_wpos);
374
bphn = word_el->phones[0];
375
if (IS_FILLER(bphn)) {word_el = word_el->next; continue;}
376
for (j = 0; j < PHNHASHSIZE; j++){
377
ephnptr = ephnhash[j];
378
while (ephnptr != NULL){
379
lctx = ephnptr->phone;
380
for (k = 0; k < PHNHASHSIZE; k++){
381
bphnptr = bphnhash[k];
382
while (bphnptr != NULL){
383
rctx = bphnptr->phone;
384
tphnptr = install(bphn,lctx,rctx,wpos,tphnhash);
385
if (tphnptr->dictcount == 0) swdtphs++;
386
tphnptr->dictcount++;
387
bphnptr = bphnptr->next;
390
ephnptr = ephnptr->next;
395
wpos = wordpos2str(WORD_POSN_BEGIN, ignore_wpos);
396
bphn = word_el->phones[0];
397
if (IS_FILLER(bphn)) {word_el = word_el->next; continue;}
398
rctx = word_el->phones[1];
399
if (IS_FILLER(rctx)) rctx = silencephn;
400
for (j = 0; j < PHNHASHSIZE; j++){
401
ephnptr = ephnhash[j];
402
while (ephnptr != NULL){
403
lctx = ephnptr->phone;
404
tphnptr = install(bphn,lctx,rctx,wpos,tphnhash);
405
if (tphnptr->dictcount == 0) bwdtphs++;
406
tphnptr->dictcount++;
407
ephnptr = ephnptr->next;
410
wpos = wordpos2str(WORD_POSN_INTERNAL, ignore_wpos);
411
for (j=1;j<lnphns-1;j++){
412
bphn = word_el->phones[j];
413
if (IS_FILLER(bphn)) continue;
414
lctx = word_el->phones[j-1];
415
if (IS_FILLER(lctx)) lctx = silencephn;
416
rctx = word_el->phones[j+1];
417
if (IS_FILLER(rctx)) rctx = silencephn;
418
tphnptr = install(bphn,lctx,rctx,wpos,tphnhash);
419
if (tphnptr->dictcount == 0) iwdtphs++;
420
tphnptr->dictcount++;
422
wpos = wordpos2str(WORD_POSN_END, ignore_wpos);
423
bphn = word_el->phones[lnphns-1];
424
if (IS_FILLER(bphn)) {word_el = word_el->next; continue;}
425
lctx = word_el->phones[lnphns-2];
426
if (IS_FILLER(lctx)) lctx = silencephn;
427
for (j = 0; j < PHNHASHSIZE; j++){
428
bphnptr = bphnhash[j];
429
while (bphnptr != NULL){
430
rctx = bphnptr->phone;
431
tphnptr = install(bphn,lctx,rctx,wpos,tphnhash);
432
if (tphnptr->dictcount == 0) ewdtphs++;
433
tphnptr->dictcount++;
434
bphnptr = bphnptr->next;
438
word_el = word_el->next;
441
totaltphs = swdtphs + bwdtphs + iwdtphs + ewdtphs;
442
E_INFO("%d words in dictionary\n",totwds);
443
E_INFO("%d unique single word triphones in dictionary\n",swdtphs);
444
E_INFO("%d unique word beginning triphones in dictionary\n",bwdtphs);
445
E_INFO("%d unique word internal triphones in dictionary\n",iwdtphs);
446
E_INFO("%d unique word ending triphones in dictionary\n",ewdtphs);
448
*triphonehash = tphnhash;
450
freephnhash(bphnhash); freephnhash(ephnhash);
456
int32 count_triphones (const char *transfile,
457
dicthashelement_t **dicthash,
458
hashelement_t **tphnhash,
459
phnhashelement_t ***phnhash,
462
int32 nbwdtphns, newdtphns, niwdtphns, nswdtphns;
463
int32 nwords, lnphns, n_totalwds;
464
lineiter_t *line = NULL;
466
char *word, *basephone, *lctxt, *rctxt;
470
dicthashelement_t **wordarr;
471
phnhashelement_t **lphnhash, *phnptr;
472
hashelement_t *tphnptr;
475
strcpy(silencephn,"SIL");
476
if ((fp = fopen(transfile,"r")) == NULL)
477
E_FATAL("Unable to open transcript file %s for reading!\n",transfile);
479
E_INFO("Out of vocabulary words in transcript will be mapped to SIL!\n");
481
lphnhash = (phnhashelement_t**)calloc(PHNHASHSIZE,sizeof(phnhashelement_t));
484
nbwdtphns = newdtphns = niwdtphns = nswdtphns = 0;
486
for (line = lineiter_start_clean(fp); line; line = lineiter_next(line)) {
488
tline = strdup(line->buf);
489
if (strtok(tline," \t\n") == NULL) {
494
/* Count number of phones in pronunciation */
495
for(nwords=1; strtok(NULL," \t\n") != NULL; nwords++);
496
n_totalwds += nwords;
497
wordarr = (dicthashelement_t **)ckd_calloc(nwords+2,sizeof(dicthashelement_t*));
498
word = strtok(line->buf," \t\n");
499
if ((wordarr[1] = dictlookup(word,dicthash)) == NULL) {
500
E_WARN("Word %s not found in dictionary. Mapping to SIL.\n", word);
502
for (j=2; (word = strtok(NULL," \t\n")) != NULL; j++) {
503
if ((wordarr[j] = dictlookup(word,dicthash)) == NULL) {
504
/* If word is surrounded by "()", assume it's the
505
* utterance ID, and don't report it as an OOV */
506
if ((word[0] != '(') && (word[strlen(word) - 1] != ')')) {
507
E_WARN("Word %s not found in dictionary. Mapping to SIL.\n", word);
511
for (i=1; i<=nwords; i++){/* Indices account for padded wordarr array */
512
if (wordarr[i] == NULL) continue;
514
lnphns = wordarr[i]->nphns;
516
wpos = wordpos2str(WORD_POSN_SINGLE, ignore_wpos);
517
basephone = wordarr[i]->phones[0];
518
phnptr = phninstall(basephone,lphnhash);
520
if (IS_FILLER(basephone)) continue;
521
if (wordarr[i-1] != NULL){
522
lctxt = wordarr[i-1]->phones[wordarr[i-1]->nphns - 1];
523
if (IS_FILLER(lctxt)) lctxt = silencephn;
525
else lctxt = silencephn;
526
if (wordarr[i+1] != NULL){
527
rctxt = wordarr[i+1]->phones[0];
528
if (IS_FILLER(rctxt)) rctxt = silencephn;
530
else rctxt = silencephn;
531
tphnptr = lookup(basephone,lctxt,rctxt,wpos,tphnhash);
536
wpos = wordpos2str(WORD_POSN_BEGIN, ignore_wpos);
537
basephone = wordarr[i]->phones[0];
538
phnptr = phninstall(basephone,lphnhash);
540
if (IS_FILLER(basephone)) continue;
541
if (!IS_FILLER(basephone)){
542
if (wordarr[i-1] != NULL){
543
lctxt = wordarr[i-1]->phones[wordarr[i-1]->nphns - 1];
544
if (IS_FILLER(lctxt)) lctxt = silencephn;
546
else lctxt = silencephn;
547
rctxt = wordarr[i]->phones[1];
548
if (IS_FILLER(rctxt)) rctxt = silencephn;
549
tphnptr = lookup(basephone,lctxt,rctxt,wpos,tphnhash);
553
wpos = wordpos2str(WORD_POSN_INTERNAL, ignore_wpos);
554
for (j=1;j<lnphns-1;j++){
555
basephone = wordarr[i]->phones[j];
556
phnptr = phninstall(basephone,lphnhash);
558
if (IS_FILLER(basephone)) continue;
559
lctxt = wordarr[i]->phones[j-1];
560
if (IS_FILLER(lctxt)) lctxt = silencephn;
561
rctxt = wordarr[i]->phones[j+1];
562
if (IS_FILLER(rctxt)) rctxt = silencephn;
563
tphnptr = lookup(basephone,lctxt,rctxt,wpos,tphnhash);
568
wpos = wordpos2str(WORD_POSN_END, ignore_wpos);
569
basephone = wordarr[i]->phones[lnphns-1];
570
phnptr = phninstall(basephone,lphnhash);
572
if (IS_FILLER(basephone)) continue;
574
lctxt = wordarr[i]->phones[lnphns-2];
575
if (IS_FILLER(lctxt)) lctxt = silencephn;
576
if (wordarr[i+1] != NULL){
577
rctxt = wordarr[i+1]->phones[0];
578
if (IS_FILLER(rctxt)) rctxt = silencephn;
580
else rctxt = silencephn;
581
tphnptr = lookup(basephone,lctxt,rctxt,wpos,tphnhash);
593
E_INFO("%d words in transcripts\n",n_totalwds);
594
E_INFO("%d single word triphones in transcripts\n",nswdtphns);
595
E_INFO("%d word beginning triphones in transcripts\n",nbwdtphns);
596
E_INFO("%d word internal triphones in transcripts\n",niwdtphns);
597
E_INFO("%d word ending triphones in transcripts\n",newdtphns);
603
int32 find_threshold(hashelement_t **triphonehash)
605
hashelement_t *triphone_el;
606
int32 tottph, ltottph, mincnt, maxtph, *countofcounts, *lcountofcounts;
607
int32 i, cnt, unique, threshold, ceiling;
609
mincnt = cmd_ln_int32("-minocc");
610
maxtph = cmd_ln_int32("-maxtriphones");
612
ceiling = mincnt < CEILING ? CEILING : mincnt+1;
614
tottph = ltottph = unique = 0;
615
countofcounts = (int32 *) ckd_calloc(ceiling+1,sizeof(int32));
616
lcountofcounts = (int32 *) ckd_calloc(ceiling+1,sizeof(int32));
617
for (i = 0; i < HASHSIZE; i++){
618
triphone_el = triphonehash[i];
619
while (triphone_el != NULL){
620
cnt = triphone_el->count;
625
if (cnt > ceiling) cnt = ceiling;
626
lcountofcounts[cnt]++;
628
countofcounts[cnt]++; unique++;
630
triphone_el = triphone_el->next;
635
while (ltottph > maxtph) {
636
ltottph -= lcountofcounts[threshold];
640
E_INFO("%d triphones extracted from transcripts\n",tottph);
641
E_INFO("%d unique triphones extracted from transcripts\n",unique);
642
E_INFO("%d triphones occur once in the transcripts\n",countofcounts[1]);
643
E_INFO("%d triphones occur twice in the transcripts\n",countofcounts[2]);
644
E_INFO("%d triphones occur thrice in the transcripts\n",countofcounts[3]);
645
E_INFO("The rest of the triphones occur more than three times\n");
646
E_INFO("Count threshold is %d\n",threshold);
648
ckd_free(lcountofcounts); ckd_free(countofcounts);
653
int32 make_CD_heap(hashelement_t **triphonehash,
655
heapelement_t ***CDheap,
658
heapelement_t **heap=NULL, *addtriphone;
659
hashelement_t *triphone_el;
663
for (i = 0; i < HASHSIZE; i++){
664
triphone_el = triphonehash[i];
665
while (triphone_el != NULL){
666
if (triphone_el->count >= threshold) {
667
addtriphone = (heapelement_t *) calloc(1,sizeof(heapelement_t));
668
if (addtriphone == NULL)
669
E_FATAL("Heap install error. Out of memory!\n");
670
addtriphone->basephone = strdup(triphone_el->basephone);
671
addtriphone->leftcontext = strdup(triphone_el->leftcontext);
672
addtriphone->rightcontext = strdup(triphone_el->rightcontext);
673
addtriphone->wordposition = strdup(triphone_el->wordposition);
674
heapsize = insert(&heap, heapsize, addtriphone);
676
triphone_el = triphone_el->next;
680
*cdheapsize = heapsize;
686
int32 print_counts(const char *countfn, phnhashelement_t **CIhash,
687
hashelement_t **CDhash)
689
heapelement_t **CDheap=NULL, **CIheap=NULL, *addphone, *addtriphone;
690
hashelement_t *triphone_el;
691
phnhashelement_t *ciphone_el;
692
int32 i, heapsize,cdheapsize,ciheapsize;
695
if ((ofp = fopen(countfn,"w")) == NULL){
696
E_WARN("Unable to open %s for writing. Not writing counts!\n",countfn);
699
fprintf(ofp,"base\tleft\tright\twdpos\tcount\n");
702
for (i = 0; i < PHNHASHSIZE; i++){
703
ciphone_el = CIhash[i];
704
while (ciphone_el != NULL){
705
if (ciphone_el->count < 1) {
706
ciphone_el = ciphone_el->next;
709
addphone = (heapelement_t *) ckd_calloc(1,sizeof(heapelement_t));
710
addphone->basephone = strdup(ciphone_el->phone);
711
addphone->count = ciphone_el->count;
712
ciheapsize = insert(&CIheap, ciheapsize, addphone);
713
ciphone_el = ciphone_el->next;
716
heapsize = ciheapsize;
717
for (i = 0; i < heapsize; i++) {
718
addphone = yanktop(&CIheap,ciheapsize,&ciheapsize);
719
fprintf(ofp,"%s\t-\t-\t-\t%d\n",addphone->basephone,addphone->count);
720
free_heapelement(addphone);
724
for (i = 0; i < HASHSIZE; i++){
725
triphone_el = CDhash[i];
726
while (triphone_el != NULL){
727
if (triphone_el->count < 1) {
728
triphone_el = triphone_el->next;
731
addtriphone = (heapelement_t *) ckd_calloc(1,sizeof(heapelement_t));
732
addtriphone->basephone = strdup(triphone_el->basephone);
733
addtriphone->leftcontext = strdup(triphone_el->leftcontext);
734
addtriphone->rightcontext = strdup(triphone_el->rightcontext);
735
addtriphone->wordposition = strdup(triphone_el->wordposition);
736
addtriphone->count = triphone_el->count;
737
cdheapsize = insert(&CDheap, cdheapsize, addtriphone);
738
triphone_el = triphone_el->next;
741
heapsize = cdheapsize;
742
for (i = 0; i < heapsize; i++) {
743
addtriphone = yanktop(&CDheap,cdheapsize,&cdheapsize);
744
fprintf(ofp,"%s\t%s\t%s\t%s\t%d\n",addtriphone->basephone,
745
addtriphone->leftcontext,
746
addtriphone->rightcontext,
747
addtriphone->wordposition,
749
free_heapelement(addtriphone);
755
static const char* wordpos2str(word_posn_t wordpos, int ignore_wordpos)
759
if (ignore_wordpos) {
760
if (wordpos == WORD_POSN_UNDEFINED)
766
case WORD_POSN_SINGLE:
769
case WORD_POSN_BEGIN:
772
case WORD_POSN_INTERNAL:
785
word_posn_t posnstr2wordpos(char *posn_str)
787
if (posn_str == NULL) {
788
E_WARN("No word position defined. Assuming word internal\n");
789
return WORD_POSN_INTERNAL;
791
if (posn_str[0] == 's') return WORD_POSN_SINGLE;
792
if (posn_str[0] == 'b') return WORD_POSN_BEGIN;
793
if (posn_str[0] == 'i') return WORD_POSN_INTERNAL;
794
if (posn_str[0] == 'e') return WORD_POSN_END;
795
if (posn_str[0] == 'u') return WORD_POSN_UNDEFINED;
797
E_WARN("unknown word position %s; assuming word internal\n", posn_str);
798
return WORD_POSN_INTERNAL;
803
output_model_def(FILE *fp,
816
uint32 n_tied_ci_state,
824
at = ctime((const time_t *)&t);
825
at[strlen(at)-1] = '\0';
827
fprintf(fp, "# Generated by %s on %s\n", pgm, at);
829
fprintf(fp, "%s\n", MODEL_DEF_VERSION);
830
fprintf(fp, "%u n_base\n", n_base);
831
fprintf(fp, "%u n_tri\n", n_tri);
832
fprintf(fp, "%u n_state_map\n", (n_base + n_tri) * n_state_pm);
833
fprintf(fp, "%u n_tied_state\n", n_tied_state);
834
fprintf(fp, "%u n_tied_ci_state\n", n_tied_ci_state);
835
fprintf(fp, "%u n_tied_tmat\n", n_tied_tmat);
837
fprintf(fp, "#\n# Columns definitions\n");
838
fprintf(fp, "#%4s %3s %3s %1s %6s %4s %s\n",
839
"base", "lft", "rt", "p", "attrib", "tmat",
840
" ... state id's ...");
841
for (i = 0; i < n_total; i++) {
842
if ((base_str[i][0] == '+') ||
843
(strncmp(base_str[i], "SIL", 3) == 0)) {
844
fprintf(fp, "%5s %3s %3s %1s %6s %4d",
846
(left_str[i] != NULL ? left_str[i] : "-"),
847
(right_str[i] != NULL ? right_str[i] : "-"),
848
(posn_str[i] != NULL ? posn_str[i] : "-"),
853
fprintf(fp, "%5s %3s %3s %1s %6s %4d",
855
(left_str[i] != NULL ? left_str[i] : "-"),
856
(right_str[i] != NULL ? right_str[i] : "-"),
857
(posn_str[i] != NULL ? posn_str[i] : "-"),
863
for (j = 0; j < n_state_pm-1; j++) {
864
fprintf(fp, " %4u", state[i][j]);
872
int32 make_mdef_from_list(const char *mdeffile,
875
heapelement_t **CDheap,
879
int32 n_base, n_tri, n_state_pm, n_total;
880
int32 n_tied_state_ci, n_tied_state_cd, n_tied_tmat;
881
char **base_str, **left_str, **right_str, **posn_str;
882
acmod_id_t base, left, right;
884
acmod_set_t *acmod_set;
886
const char *filler_attr[] = {"filler", NULL};
887
const char *base_attr[] = {"base", NULL};
888
const char *na_attr[] = {"n/a", NULL};
891
heapelement_t *cdphone;
894
n_state_pm = cmd_ln_int32("-n_state_pm") + 1;
897
E_INFO("%d n_base, %d n_tri\n", n_base, n_tri);
899
n_tied_state_ci = n_base * (n_state_pm-1);
900
n_tied_state_cd = n_tri * (n_state_pm-1);
901
n_tied_tmat = n_base;
903
n_total = n_base + n_tri;
904
base_str = ckd_calloc(n_total, sizeof(char *));
905
left_str = ckd_calloc(n_total, sizeof(char *));
906
right_str = ckd_calloc(n_total, sizeof(char *));
907
posn_str = ckd_calloc(n_total, sizeof(char *));
909
tmat = ckd_calloc(n_total, sizeof(uint32));
911
smap = (uint32 **)ckd_calloc_2d(n_total, n_state_pm-1, sizeof(uint32));
913
for (i = 0; i < n_base; i++) {
914
base_str[i] = strdup(CIlist[i]);
917
for (j = 0; j < n_tri; j++,i++) {
918
cdphone = yanktop(&CDheap,cdheapsize,&cdheapsize);
919
base_str[i] = strdup(cdphone->basephone);
920
left_str[i] = strdup(cdphone->leftcontext);
921
right_str[i] = strdup(cdphone->rightcontext);
922
posn_str[i] = strdup(cdphone->wordposition);
923
free_heapelement(cdphone);
926
E_FATAL("Error in CD heap! Error in dictionary or phone list!\n");
928
for (i = 0, k = 0; i < n_total; i++)
929
for (j = 0; j < n_state_pm-1; j++)
932
acmod_set = acmod_set_new();
934
acmod_set_set_n_ci_hint(acmod_set, n_base);
935
acmod_set_set_n_tri_hint(acmod_set, n_tri);
937
for (i = 0; i < n_base; i++) {
938
if (base_str[i][0] == '+') {
939
base = acmod_set_add_ci(acmod_set, base_str[i], filler_attr);
942
base = acmod_set_add_ci(acmod_set, base_str[i], base_attr);
947
for (; i < n_total; i++) {
948
if ((base = acmod_set_name2id(acmod_set, base_str[i])) == NO_ACMOD)
949
E_FATAL("Error in dictionary or phonelist. Bad basephone %s in triphone list!\n",base_str[i]);
950
if ((left = acmod_set_name2id(acmod_set, left_str[i])) == NO_ACMOD)
951
E_FATAL("Error in dictionary or phonelist. Bad leftphone %s in triphone list!\n",left_str[i]);
952
if ((right = acmod_set_name2id(acmod_set, right_str[i])) == NO_ACMOD)
953
E_FATAL("Error in dictionary or phonelist. Bad rightphone %s in triphone list!\n",right_str[i]);
955
posn = posnstr2wordpos(posn_str[i]);
957
acmod_set_add_tri(acmod_set, base, left, right, posn, na_attr);
961
if ((fp = fopen(mdeffile, "w")) == NULL)
962
E_FATAL("Unable to open %s for writing!\n",mdeffile);
965
base_str, left_str, right_str, posn_str, tmat, smap,
966
n_base, n_tri, n_total, n_state_pm,
967
n_tied_state_ci+n_tied_state_cd, n_tied_state_ci, n_tied_tmat);
969
E_INFO("Wrote mdef file %s\n",mdeffile);
971
for (j = 0; j < n_tri; j++,i++) {
972
if (base_str[j] != NULL) free(base_str[j]);
973
if (left_str[j] != NULL) free(left_str[j]);
974
if (right_str[j] != NULL) free(right_str[j]);
975
if (posn_str[j] != NULL) free(posn_str[j]);
977
free(base_str); free(left_str); free(right_str); free(posn_str);
978
ckd_free_2d((void**)smap);