diff --git a/src/programs/param_cnt/enum_corpus.c b/src/programs/param_cnt/enum_corpus.c index 2bc2f5d1..09a58d14 100644 --- a/src/programs/param_cnt/enum_corpus.c +++ b/src/programs/param_cnt/enum_corpus.c @@ -63,7 +63,8 @@ int enum_corpus(lexicon_t *lex, model_def_t *mdef, uint32 *cnt, - cnt_fn_t cnt_fn) + cnt_fn_t cnt_fn, + uint32 *out_n_utt) { uint32 tick_cnt = 0; char *trans = NULL; @@ -76,6 +77,12 @@ enum_corpus(lexicon_t *lex, char *btw_mark = NULL; while (corpus_next_utt()) { + /* lineiter_start_clean() can expose an indented first-line comment as + * a control entry. It is not an utterance and must not contribute to + * the post-enumeration count. */ + if (corpus_utt()[0] == '#') + continue; + if (trans) { free(trans); trans = NULL; @@ -96,11 +103,6 @@ enum_corpus(lexicon_t *lex, ckd_free(btw_mark); btw_mark = NULL; } - - if ((++tick_cnt % 1000) == 0) { - fprintf(stderr, "[%u] ", tick_cnt); - fflush(stderr); - } if (corpus_get_sent(&trans) != S3_SUCCESS) { E_FATAL("Unable to read word transcript for %s\n", corpus_utt_brief_name()); @@ -131,10 +133,16 @@ enum_corpus(lexicon_t *lex, } } - (*cnt_fn)(cnt, /* observation counts */ - mdef, /* model definitions */ - seg, n_frame, /* Viterbi state segmentation */ - phone, btw_mark, n_phone); /* list of phones */ + if ((*cnt_fn)(cnt, /* observation counts */ + mdef, /* model definitions */ + seg, n_frame, /* Viterbi state segmentation */ + phone, btw_mark, n_phone) != S3_SUCCESS) + continue; + + if ((++tick_cnt % 1000) == 0) { + fprintf(stderr, "[%u] ", tick_cnt); + fflush(stderr); + } } /* free the per utterance data structures from the last utt */ @@ -158,6 +166,9 @@ enum_corpus(lexicon_t *lex, ckd_free(btw_mark); btw_mark = NULL; } - + + if (out_n_utt) + *out_n_utt = tick_cnt; + return S3_SUCCESS; } diff --git a/src/programs/param_cnt/enum_corpus.h b/src/programs/param_cnt/enum_corpus.h index 9650b10a..1ef4e628 100644 --- a/src/programs/param_cnt/enum_corpus.h +++ b/src/programs/param_cnt/enum_corpus.h @@ -55,6 +55,7 @@ int enum_corpus(lexicon_t *lex, model_def_t *mdef, uint32 *cnt, - cnt_fn_t cnt_fn); + cnt_fn_t cnt_fn, + uint32 *out_n_utt); #endif /* ENUM_CORPUS_H */ diff --git a/src/programs/param_cnt/main.c b/src/programs/param_cnt/main.c index 623a1764..3c723338 100644 --- a/src/programs/param_cnt/main.c +++ b/src/programs/param_cnt/main.c @@ -72,13 +72,24 @@ initialize(lexicon_t **out_lex, model_def_t *mdef; const char *fdictfn; const char *dictfn; + const char *ctlfn; + const char *segdir; const char *ts2cbfn; uint32 n_ts; /* define, parse and (partially) validate the command line */ parse_cmd_ln(argc, argv); - corpus_set_seg_dir(cmd_ln_str("-segdir")); + /* State and codebook counting need segmentations; phone counting does + not. Requiring -segdir only where it is used turns a null dereference + into a named initialization error. */ + segdir = cmd_ln_str("-segdir"); + if (segdir) + corpus_set_seg_dir(segdir); + else if (strcmp(cmd_ln_str("-paramtype"), "phone") != 0) { + E_ERROR("You must specify a segmentation directory using -segdir\n"); + return S3_ERROR; + } corpus_set_seg_ext(cmd_ln_str("-segext")); if (cmd_ln_str("-lsnfn")) @@ -88,7 +99,11 @@ initialize(lexicon_t **out_lex, corpus_set_sent_ext(cmd_ln_str("-sentext")); } - corpus_set_ctl_filename(cmd_ln_str("-ctlfn")); + ctlfn = cmd_ln_str("-ctlfn"); + if (corpus_set_ctl_filename(ctlfn) != S3_SUCCESS) { + E_ERROR("Failed to initialize corpus from -ctlfn %s\n", ctlfn); + return S3_ERROR; + } if (cmd_ln_int32("-nskip") && cmd_ln_int32("-runlen")) { corpus_set_interval(cmd_ln_int32("-nskip"), @@ -112,6 +127,10 @@ initialize(lexicon_t **out_lex, } ts2cbfn = cmd_ln_str("-ts2cbfn"); + if (strcmp(cmd_ln_str("-paramtype"), "cb") == 0 && ts2cbfn == NULL) { + E_ERROR("CB parameter counting requires -ts2cbfn\n"); + return S3_ERROR; + } if (ts2cbfn) { E_INFO("Reading %s\n", cmd_ln_str("-ts2cbfn")); @@ -182,7 +201,6 @@ main(int argc, char *argv[]) model_def_t *mdef; const char *type; const char *outfn; - FILE *out_fp = stdout; if (initialize(&lex, &mdef, argc, argv) != S3_SUCCESS) { E_ERROR("errors initializing.\n"); @@ -191,14 +209,8 @@ main(int argc, char *argv[]) type = cmd_ln_str("-paramtype"); outfn = cmd_ln_str("-outputfn"); - if (outfn != NULL) { - out_fp = fopen(outfn, "w"); - if (out_fp == NULL) { - E_ERROR_SYSTEM("Couldn't open %s for writing\n", outfn); - } - } - if (param_cnt(out_fp, lex, mdef, type) != S3_SUCCESS) { + if (param_cnt(outfn, lex, mdef, type) != S3_SUCCESS) { return 1; } diff --git a/src/programs/param_cnt/param_cnt.c b/src/programs/param_cnt/param_cnt.c index d03e760e..422d837e 100644 --- a/src/programs/param_cnt/param_cnt.c +++ b/src/programs/param_cnt/param_cnt.c @@ -56,13 +56,14 @@ #include #include +#include #include #include int -param_cnt(FILE *out_fp, +param_cnt(const char *outfn, lexicon_t *lex, model_def_t *mdef, const char *param_type) @@ -71,7 +72,9 @@ param_cnt(FILE *out_fp, cnt_fn_t cnt_fn=0; uint32 *cnt; uint32 n_cnt=0; + uint32 n_utt=0; uint32 i; + FILE *out_fp = stdout; acmod_set = mdef->acmod_set; @@ -88,11 +91,35 @@ param_cnt(FILE *out_fp, n_cnt = mdef->acmod_set->next_id; cnt_fn = phone_cnt; } + else { + E_ERROR("Unknown parameter type '%s'; expected state, cb, or phone\n", + param_type); + return S3_ERROR; + } cnt = ckd_calloc(n_cnt, sizeof(uint32)); E_INFO("Scanning corpus\n"); - enum_corpus(lex, mdef, cnt, cnt_fn); + if (enum_corpus(lex, mdef, cnt, cnt_fn, &n_utt) != S3_SUCCESS) { + ckd_free(cnt); + return S3_ERROR; + } + + if (n_utt == 0) { + E_ERROR("No utterances were counted from -ctlfn %s\n", + cmd_ln_str("-ctlfn")); + ckd_free(cnt); + return S3_ERROR; + } + + if (outfn != NULL) { + out_fp = fopen(outfn, "w"); + if (out_fp == NULL) { + E_ERROR_SYSTEM("Couldn't open %s for writing\n", outfn); + ckd_free(cnt); + return S3_ERROR; + } + } if (strcmp(param_type, "phone") != 0) { for (i = 0; i < n_cnt; i++) @@ -103,7 +130,11 @@ param_cnt(FILE *out_fp, fprintf(out_fp, "%s %u\n", acmod_set_id2fullname(acmod_set, (acmod_id_t)i), cnt[i]); } - return 0; + if (out_fp != stdout) + fclose(out_fp); + ckd_free(cnt); + + return S3_SUCCESS; } #endif /* PARAM_CNT_H */ diff --git a/src/programs/param_cnt/param_cnt.h b/src/programs/param_cnt/param_cnt.h index 493eecd8..9010fa52 100644 --- a/src/programs/param_cnt/param_cnt.h +++ b/src/programs/param_cnt/param_cnt.h @@ -52,7 +52,7 @@ #include int -param_cnt(FILE *out_fp, +param_cnt(const char *outfn, lexicon_t *lex, model_def_t *mdef, const char *param_type);