diff options
Diffstat (limited to 'media/sphinxbase/src/libsphinxbase/lm/fsg_model.c')
-rw-r--r-- | media/sphinxbase/src/libsphinxbase/lm/fsg_model.c | 944 |
1 files changed, 0 insertions, 944 deletions
diff --git a/media/sphinxbase/src/libsphinxbase/lm/fsg_model.c b/media/sphinxbase/src/libsphinxbase/lm/fsg_model.c deleted file mode 100644 index 374897754..000000000 --- a/media/sphinxbase/src/libsphinxbase/lm/fsg_model.c +++ /dev/null @@ -1,944 +0,0 @@ -/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* ==================================================================== - * Copyright (c) 1999-2004 Carnegie Mellon University. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY - * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ==================================================================== - * - */ - -/* System headers. */ -#ifdef _WIN32_WCE -/*MC in a debug build it's implicitly included by assert.h - but you need this in a release build */ -#include <windows.h> -#else -#include <time.h> -#endif /* _WIN32_WCE */ -#include <stdio.h> -#include <string.h> -#include <assert.h> - -/* SphinxBase headers. */ -#include "sphinxbase/err.h" -#include "sphinxbase/pio.h" -#include "sphinxbase/ckd_alloc.h" -#include "sphinxbase/prim_type.h" -#include "sphinxbase/strfuncs.h" -#include "sphinxbase/hash_table.h" -#include "sphinxbase/fsg_model.h" - -/** - * Adjacency list (opaque) for a state in an FSG. - * - * Actually we use hash tables so that random access is a bit faster. - * Plus it allows us to make the lookup code a bit less ugly. - */ - -struct trans_list_s { - hash_table_t *null_trans; /* Null transitions keyed by state. */ - hash_table_t *trans; /* Lists of non-null transitions keyed by state. */ -}; - -/** - * Implementation of arc iterator. - */ -struct fsg_arciter_s { - hash_iter_t *itor, *null_itor; - gnode_t *gn; -}; - -#define FSG_MODEL_BEGIN_DECL "FSG_BEGIN" -#define FSG_MODEL_END_DECL "FSG_END" -#define FSG_MODEL_N_DECL "N" -#define FSG_MODEL_NUM_STATES_DECL "NUM_STATES" -#define FSG_MODEL_S_DECL "S" -#define FSG_MODEL_START_STATE_DECL "START_STATE" -#define FSG_MODEL_F_DECL "F" -#define FSG_MODEL_FINAL_STATE_DECL "FINAL_STATE" -#define FSG_MODEL_T_DECL "T" -#define FSG_MODEL_TRANSITION_DECL "TRANSITION" -#define FSG_MODEL_COMMENT_CHAR '#' - - -static int32 -nextline_str2words(FILE * fp, int32 * lineno, - char **lineptr, char ***wordptr) -{ - for (;;) { - size_t len; - int32 n; - - ckd_free(*lineptr); - if ((*lineptr = fread_line(fp, &len)) == NULL) - return -1; - - (*lineno)++; - - if ((*lineptr)[0] == FSG_MODEL_COMMENT_CHAR) - continue; /* Skip comment lines */ - - n = str2words(*lineptr, NULL, 0); - if (n == 0) - continue; /* Skip blank lines */ - - /* Abuse of realloc(), but this doesn't have to be fast. */ - if (*wordptr == NULL) - *wordptr = ckd_calloc(n, sizeof(**wordptr)); - else - *wordptr = ckd_realloc(*wordptr, n * sizeof(**wordptr)); - return str2words(*lineptr, *wordptr, n); - } -} - -void -fsg_model_trans_add(fsg_model_t * fsg, - int32 from, int32 to, int32 logp, int32 wid) -{ - fsg_link_t *link; - glist_t gl; - gnode_t *gn; - - if (fsg->trans[from].trans == NULL) - fsg->trans[from].trans = hash_table_new(5, HASH_CASE_YES); - - /* Check for duplicate link (i.e., link already exists with label=wid) */ - for (gn = gl = fsg_model_trans(fsg, from, to); gn; gn = gnode_next(gn)) { - link = (fsg_link_t *) gnode_ptr(gn); - if (link->wid == wid) { - if (link->logs2prob < logp) - link->logs2prob = logp; - return; - } - } - - /* Create transition object */ - link = listelem_malloc(fsg->link_alloc); - link->from_state = from; - link->to_state = to; - link->logs2prob = logp; - link->wid = wid; - - /* Add it to the list of transitions and update the hash table */ - gl = glist_add_ptr(gl, (void *) link); - hash_table_replace_bkey(fsg->trans[from].trans, - (char const *) &link->to_state, - sizeof(link->to_state), gl); -} - -int32 -fsg_model_tag_trans_add(fsg_model_t * fsg, int32 from, int32 to, - int32 logp, int32 wid) -{ - fsg_link_t *link, *link2; - - /* Check for transition probability */ - if (logp > 0) { - E_FATAL("Null transition prob must be <= 1.0 (state %d -> %d)\n", - from, to); - } - - /* Self-loop null transitions (with prob <= 1.0) are redundant */ - if (from == to) - return -1; - - if (fsg->trans[from].null_trans == NULL) - fsg->trans[from].null_trans = hash_table_new(5, HASH_CASE_YES); - - /* Check for a duplicate link; if found, keep the higher prob */ - link = fsg_model_null_trans(fsg, from, to); - if (link) { - if (link->logs2prob < logp) { - link->logs2prob = logp; - return 0; - } - else - return -1; - } - - /* Create null transition object */ - link = listelem_malloc(fsg->link_alloc); - link->from_state = from; - link->to_state = to; - link->logs2prob = logp; - link->wid = -1; - - link2 = (fsg_link_t *) - hash_table_enter_bkey(fsg->trans[from].null_trans, - (char const *) &link->to_state, - sizeof(link->to_state), link); - assert(link == link2); - - return 1; -} - -int32 -fsg_model_null_trans_add(fsg_model_t * fsg, int32 from, int32 to, - int32 logp) -{ - return fsg_model_tag_trans_add(fsg, from, to, logp, -1); -} - -glist_t -fsg_model_null_trans_closure(fsg_model_t * fsg, glist_t nulls) -{ - gnode_t *gn1; - int updated; - fsg_link_t *tl1, *tl2; - int32 k, n; - - E_INFO("Computing transitive closure for null transitions\n"); - - /* If our caller didn't give us a list of null-transitions, - make such a list. Just loop through all the FSG states, - and all the null-transitions in that state (which are kept in - their own hash table). */ - if (nulls == NULL) { - int i; - for (i = 0; i < fsg->n_state; ++i) { - hash_iter_t *itor; - hash_table_t *null_trans = fsg->trans[i].null_trans; - if (null_trans == NULL) - continue; - for (itor = hash_table_iter(null_trans); - itor != NULL; - itor = hash_table_iter_next(itor)) { - nulls = glist_add_ptr(nulls, hash_entry_val(itor->ent)); - } - } - } - - /* - * Probably not the most efficient closure implementation, in general, but - * probably reasonably efficient for a sparse null transition matrix. - */ - n = 0; - do { - updated = FALSE; - - for (gn1 = nulls; gn1; gn1 = gnode_next(gn1)) { - hash_iter_t *itor; - - tl1 = (fsg_link_t *) gnode_ptr(gn1); - assert(tl1->wid < 0); - - if (fsg->trans[tl1->to_state].null_trans == NULL) - continue; - - for (itor = hash_table_iter(fsg->trans[tl1->to_state].null_trans); - itor; itor = hash_table_iter_next(itor)) { - - tl2 = (fsg_link_t *) hash_entry_val(itor->ent); - - k = fsg_model_null_trans_add(fsg, - tl1->from_state, - tl2->to_state, - tl1->logs2prob + - tl2->logs2prob); - if (k >= 0) { - updated = TRUE; - if (k > 0) { - nulls = glist_add_ptr(nulls, (void *) - fsg_model_null_trans - (fsg, tl1->from_state, - tl2->to_state)); - n++; - } - } - } - } - } while (updated); - - E_INFO("%d null transitions added\n", n); - - return nulls; -} - -glist_t -fsg_model_trans(fsg_model_t * fsg, int32 i, int32 j) -{ - void *val; - - if (fsg->trans[i].trans == NULL) - return NULL; - if (hash_table_lookup_bkey(fsg->trans[i].trans, (char const *) &j, - sizeof(j), &val) < 0) - return NULL; - return (glist_t) val; -} - -fsg_link_t * -fsg_model_null_trans(fsg_model_t * fsg, int32 i, int32 j) -{ - void *val; - - if (fsg->trans[i].null_trans == NULL) - return NULL; - if (hash_table_lookup_bkey(fsg->trans[i].null_trans, (char const *) &j, - sizeof(j), &val) < 0) - return NULL; - return (fsg_link_t *) val; -} - -fsg_arciter_t * -fsg_model_arcs(fsg_model_t * fsg, int32 i) -{ - fsg_arciter_t *itor; - - if (fsg->trans[i].trans == NULL && fsg->trans[i].null_trans == NULL) - return NULL; - itor = ckd_calloc(1, sizeof(*itor)); - if (fsg->trans[i].null_trans) - itor->null_itor = hash_table_iter(fsg->trans[i].null_trans); - if (fsg->trans[i].trans) - itor->itor = hash_table_iter(fsg->trans[i].trans); - if (itor->itor != NULL) - itor->gn = hash_entry_val(itor->itor->ent); - return itor; -} - -fsg_link_t * -fsg_arciter_get(fsg_arciter_t * itor) -{ - /* Iterate over non-null arcs first. */ - if (itor->gn) - return (fsg_link_t *) gnode_ptr(itor->gn); - else if (itor->null_itor) - return (fsg_link_t *) hash_entry_val(itor->null_itor->ent); - else - return NULL; -} - -fsg_arciter_t * -fsg_arciter_next(fsg_arciter_t * itor) -{ - /* Iterate over non-null arcs first. */ - if (itor->gn) { - itor->gn = gnode_next(itor->gn); - /* Move to the next destination arc. */ - if (itor->gn == NULL) { - itor->itor = hash_table_iter_next(itor->itor); - if (itor->itor != NULL) - itor->gn = hash_entry_val(itor->itor->ent); - else if (itor->null_itor == NULL) - goto stop_iteration; - } - } - else { - if (itor->null_itor == NULL) - goto stop_iteration; - itor->null_itor = hash_table_iter_next(itor->null_itor); - if (itor->null_itor == NULL) - goto stop_iteration; - } - return itor; - stop_iteration: - fsg_arciter_free(itor); - return NULL; - -} - -void -fsg_arciter_free(fsg_arciter_t * itor) -{ - if (itor == NULL) - return; - hash_table_iter_free(itor->null_itor); - hash_table_iter_free(itor->itor); - ckd_free(itor); -} - -int -fsg_model_word_id(fsg_model_t * fsg, char const *word) -{ - int wid; - - /* Search for an existing word matching this. */ - for (wid = 0; wid < fsg->n_word; ++wid) { - if (0 == strcmp(fsg->vocab[wid], word)) - break; - } - /* If not found, add this to the vocab. */ - if (wid == fsg->n_word) - return -1; - return wid; -} - -int -fsg_model_word_add(fsg_model_t * fsg, char const *word) -{ - int wid, old_size; - - /* Search for an existing word matching this. */ - wid = fsg_model_word_id(fsg, word); - /* If not found, add this to the vocab. */ - if (wid == -1) { - wid = fsg->n_word; - if (fsg->n_word == fsg->n_word_alloc) { - old_size = fsg->n_word_alloc; - fsg->n_word_alloc += 10; - fsg->vocab = ckd_realloc(fsg->vocab, - fsg->n_word_alloc * - sizeof(*fsg->vocab)); - if (fsg->silwords) - fsg->silwords = - bitvec_realloc(fsg->silwords, old_size, fsg->n_word_alloc); - if (fsg->altwords) - fsg->altwords = - bitvec_realloc(fsg->altwords, old_size, fsg->n_word_alloc); - } - ++fsg->n_word; - fsg->vocab[wid] = ckd_salloc(word); - } - return wid; -} - -int -fsg_model_add_silence(fsg_model_t * fsg, char const *silword, - int state, float32 silprob) -{ - int32 logsilp; - int n_trans, silwid, src; - - E_INFO("Adding silence transitions for %s to FSG\n", silword); - - silwid = fsg_model_word_add(fsg, silword); - logsilp = (int32) (logmath_log(fsg->lmath, silprob) * fsg->lw); - if (fsg->silwords == NULL) - fsg->silwords = bitvec_alloc(fsg->n_word_alloc); - bitvec_set(fsg->silwords, silwid); - - n_trans = 0; - if (state == -1) { - for (src = 0; src < fsg->n_state; src++) { - fsg_model_trans_add(fsg, src, src, logsilp, silwid); - ++n_trans; - } - } - else { - fsg_model_trans_add(fsg, state, state, logsilp, silwid); - ++n_trans; - } - - E_INFO("Added %d silence word transitions\n", n_trans); - return n_trans; -} - -int -fsg_model_add_alt(fsg_model_t * fsg, char const *baseword, - char const *altword) -{ - int i, basewid, altwid; - int ntrans; - - /* FIXME: This will get slow, eventually... */ - for (basewid = 0; basewid < fsg->n_word; ++basewid) - if (0 == strcmp(fsg->vocab[basewid], baseword)) - break; - if (basewid == fsg->n_word) { - E_ERROR("Base word %s not present in FSG vocabulary!\n", baseword); - return -1; - } - altwid = fsg_model_word_add(fsg, altword); - if (fsg->altwords == NULL) - fsg->altwords = bitvec_alloc(fsg->n_word_alloc); - bitvec_set(fsg->altwords, altwid); - if (fsg_model_is_filler(fsg, basewid)) { - if (fsg->silwords == NULL) - fsg->silwords = bitvec_alloc(fsg->n_word_alloc); - bitvec_set(fsg->silwords, altwid); - } - - E_DEBUG(2, ("Adding alternate word transitions (%s,%s) to FSG\n", - baseword, altword)); - - /* Look for all transitions involving baseword and duplicate them. */ - /* FIXME: This will also get slow, eventually... */ - ntrans = 0; - for (i = 0; i < fsg->n_state; ++i) { - hash_iter_t *itor; - if (fsg->trans[i].trans == NULL) - continue; - for (itor = hash_table_iter(fsg->trans[i].trans); itor; - itor = hash_table_iter_next(itor)) { - glist_t trans; - gnode_t *gn; - - trans = hash_entry_val(itor->ent); - for (gn = trans; gn; gn = gnode_next(gn)) { - fsg_link_t *fl = gnode_ptr(gn); - if (fl->wid == basewid) { - fsg_link_t *link; - - /* Create transition object */ - link = listelem_malloc(fsg->link_alloc); - link->from_state = fl->from_state; - link->to_state = fl->to_state; - link->logs2prob = fl->logs2prob; /* FIXME!!!??? */ - link->wid = altwid; - - trans = glist_add_ptr(trans, (void *) link); - ++ntrans; - } - } - hash_entry_val(itor->ent) = trans; - } - } - - E_DEBUG(2, ("Added %d alternate word transitions\n", ntrans)); - return ntrans; -} - - -fsg_model_t * -fsg_model_init(char const *name, logmath_t * lmath, float32 lw, - int32 n_state) -{ - fsg_model_t *fsg; - - /* Allocate basic stuff. */ - fsg = ckd_calloc(1, sizeof(*fsg)); - fsg->refcount = 1; - fsg->link_alloc = listelem_alloc_init(sizeof(fsg_link_t)); - fsg->lmath = lmath; - fsg->name = name ? ckd_salloc(name) : NULL; - fsg->n_state = n_state; - fsg->lw = lw; - - fsg->trans = ckd_calloc(fsg->n_state, sizeof(*fsg->trans)); - - return fsg; -} - -fsg_model_t * -fsg_model_read(FILE * fp, logmath_t * lmath, float32 lw) -{ - fsg_model_t *fsg; - hash_table_t *vocab; - hash_iter_t *itor; - int32 lastwid; - char **wordptr; - char *lineptr; - char *fsgname; - int32 lineno; - int32 n, i, j; - int n_state, n_trans, n_null_trans; - glist_t nulls; - float32 p; - - lineno = 0; - vocab = hash_table_new(32, FALSE); - wordptr = NULL; - lineptr = NULL; - nulls = NULL; - fsgname = NULL; - fsg = NULL; - - /* Scan upto FSG_BEGIN header */ - for (;;) { - n = nextline_str2words(fp, &lineno, &lineptr, &wordptr); - if (n < 0) { - E_ERROR("%s declaration missing\n", FSG_MODEL_BEGIN_DECL); - goto parse_error; - } - - if ((strcmp(wordptr[0], FSG_MODEL_BEGIN_DECL) == 0)) { - if (n > 2) { - E_ERROR("Line[%d]: malformed FSG_BEGIN declaration\n", - lineno); - goto parse_error; - } - break; - } - } - /* Save FSG name, or it will get clobbered below :(. - * If name is missing, try the default. - */ - if (n == 2) { - fsgname = ckd_salloc(wordptr[1]); - } - else { - E_WARN("FSG name is missing\n"); - fsgname = ckd_salloc("unknown"); - } - - /* Read #states */ - n = nextline_str2words(fp, &lineno, &lineptr, &wordptr); - if ((n != 2) - || ((strcmp(wordptr[0], FSG_MODEL_N_DECL) != 0) - && (strcmp(wordptr[0], FSG_MODEL_NUM_STATES_DECL) != 0)) - || (sscanf(wordptr[1], "%d", &n_state) != 1) - || (n_state <= 0)) { - E_ERROR - ("Line[%d]: #states declaration line missing or malformed\n", - lineno); - goto parse_error; - } - - /* Now create the FSG. */ - fsg = fsg_model_init(fsgname, lmath, lw, n_state); - ckd_free(fsgname); - fsgname = NULL; - - /* Read start state */ - n = nextline_str2words(fp, &lineno, &lineptr, &wordptr); - if ((n != 2) - || ((strcmp(wordptr[0], FSG_MODEL_S_DECL) != 0) - && (strcmp(wordptr[0], FSG_MODEL_START_STATE_DECL) != 0)) - || (sscanf(wordptr[1], "%d", &(fsg->start_state)) != 1) - || (fsg->start_state < 0) - || (fsg->start_state >= fsg->n_state)) { - E_ERROR - ("Line[%d]: start state declaration line missing or malformed\n", - lineno); - goto parse_error; - } - - /* Read final state */ - n = nextline_str2words(fp, &lineno, &lineptr, &wordptr); - if ((n != 2) - || ((strcmp(wordptr[0], FSG_MODEL_F_DECL) != 0) - && (strcmp(wordptr[0], FSG_MODEL_FINAL_STATE_DECL) != 0)) - || (sscanf(wordptr[1], "%d", &(fsg->final_state)) != 1) - || (fsg->final_state < 0) - || (fsg->final_state >= fsg->n_state)) { - E_ERROR - ("Line[%d]: final state declaration line missing or malformed\n", - lineno); - goto parse_error; - } - - /* Read transitions */ - lastwid = 0; - n_trans = n_null_trans = 0; - for (;;) { - int32 wid, tprob; - - n = nextline_str2words(fp, &lineno, &lineptr, &wordptr); - if (n <= 0) { - E_ERROR("Line[%d]: transition or FSG_END statement expected\n", - lineno); - goto parse_error; - } - - if ((strcmp(wordptr[0], FSG_MODEL_END_DECL) == 0)) { - break; - } - - if ((strcmp(wordptr[0], FSG_MODEL_T_DECL) == 0) - || (strcmp(wordptr[0], FSG_MODEL_TRANSITION_DECL) == 0)) { - - - if (((n != 4) && (n != 5)) - || (sscanf(wordptr[1], "%d", &i) != 1) - || (sscanf(wordptr[2], "%d", &j) != 1) - || (i < 0) || (i >= fsg->n_state) - || (j < 0) || (j >= fsg->n_state)) { - E_ERROR - ("Line[%d]: transition spec malformed; Expecting: from-state to-state trans-prob [word]\n", - lineno); - goto parse_error; - } - - p = atof_c(wordptr[3]); - if ((p <= 0.0) || (p > 1.0)) { - E_ERROR - ("Line[%d]: transition spec malformed; Expecting float as transition probability\n", - lineno); - goto parse_error; - } - } - else { - E_ERROR("Line[%d]: transition or FSG_END statement expected\n", - lineno); - goto parse_error; - } - - tprob = (int32) (logmath_log(lmath, p) * fsg->lw); - /* Add word to "dictionary". */ - if (n > 4) { - if (hash_table_lookup_int32(vocab, wordptr[4], &wid) < 0) { - (void) hash_table_enter_int32(vocab, - ckd_salloc(wordptr[4]), - lastwid); - wid = lastwid; - ++lastwid; - } - fsg_model_trans_add(fsg, i, j, tprob, wid); - ++n_trans; - } - else { - if (fsg_model_null_trans_add(fsg, i, j, tprob) == 1) { - ++n_null_trans; - nulls = - glist_add_ptr(nulls, fsg_model_null_trans(fsg, i, j)); - } - } - } - - E_INFO("FSG: %d states, %d unique words, %d transitions (%d null)\n", - fsg->n_state, hash_table_inuse(vocab), n_trans, n_null_trans); - - - /* Now create a string table from the "dictionary" */ - fsg->n_word = hash_table_inuse(vocab); - fsg->n_word_alloc = fsg->n_word + 10; /* Pad it a bit. */ - fsg->vocab = ckd_calloc(fsg->n_word_alloc, sizeof(*fsg->vocab)); - for (itor = hash_table_iter(vocab); itor; - itor = hash_table_iter_next(itor)) { - char const *word = hash_entry_key(itor->ent); - int32 wid = (int32) (long) hash_entry_val(itor->ent); - fsg->vocab[wid] = (char *) word; - } - hash_table_free(vocab); - - /* Do transitive closure on null transitions */ - nulls = fsg_model_null_trans_closure(fsg, nulls); - glist_free(nulls); - - ckd_free(lineptr); - ckd_free(wordptr); - - return fsg; - - parse_error: - for (itor = hash_table_iter(vocab); itor; - itor = hash_table_iter_next(itor)) - ckd_free((char *) hash_entry_key(itor->ent)); - glist_free(nulls); - hash_table_free(vocab); - ckd_free(fsgname); - ckd_free(lineptr); - ckd_free(wordptr); - fsg_model_free(fsg); - return NULL; -} - - -fsg_model_t * -fsg_model_readfile(const char *file, logmath_t * lmath, float32 lw) -{ - FILE *fp; - fsg_model_t *fsg; - - if ((fp = fopen(file, "r")) == NULL) { - E_ERROR_SYSTEM("Failed to open FSG file '%s' for reading", file); - return NULL; - } - fsg = fsg_model_read(fp, lmath, lw); - fclose(fp); - return fsg; -} - -fsg_model_t * -fsg_model_retain(fsg_model_t * fsg) -{ - ++fsg->refcount; - return fsg; -} - -static void -trans_list_free(fsg_model_t * fsg, int32 i) -{ - hash_iter_t *itor; - - /* FIXME (maybe): FSG links will all get freed when we call - * listelem_alloc_free() so don't bother freeing them explicitly - * here. */ - if (fsg->trans[i].trans) { - for (itor = hash_table_iter(fsg->trans[i].trans); - itor; itor = hash_table_iter_next(itor)) { - glist_t gl = (glist_t) hash_entry_val(itor->ent); - glist_free(gl); - } - } - hash_table_free(fsg->trans[i].trans); - hash_table_free(fsg->trans[i].null_trans); -} - -int -fsg_model_free(fsg_model_t * fsg) -{ - int i; - - if (fsg == NULL) - return 0; - - if (--fsg->refcount > 0) - return fsg->refcount; - - for (i = 0; i < fsg->n_word; ++i) - ckd_free(fsg->vocab[i]); - for (i = 0; i < fsg->n_state; ++i) - trans_list_free(fsg, i); - ckd_free(fsg->trans); - ckd_free(fsg->vocab); - listelem_alloc_free(fsg->link_alloc); - bitvec_free(fsg->silwords); - bitvec_free(fsg->altwords); - ckd_free(fsg->name); - ckd_free(fsg); - return 0; -} - - -void -fsg_model_write(fsg_model_t * fsg, FILE * fp) -{ - int32 i; - - fprintf(fp, "%s %s\n", FSG_MODEL_BEGIN_DECL, - fsg->name ? fsg->name : ""); - fprintf(fp, "%s %d\n", FSG_MODEL_NUM_STATES_DECL, fsg->n_state); - fprintf(fp, "%s %d\n", FSG_MODEL_START_STATE_DECL, fsg->start_state); - fprintf(fp, "%s %d\n", FSG_MODEL_FINAL_STATE_DECL, fsg->final_state); - - for (i = 0; i < fsg->n_state; i++) { - fsg_arciter_t *itor; - - for (itor = fsg_model_arcs(fsg, i); itor; - itor = fsg_arciter_next(itor)) { - fsg_link_t *tl = fsg_arciter_get(itor); - - fprintf(fp, "%s %d %d %f %s\n", FSG_MODEL_TRANSITION_DECL, - tl->from_state, tl->to_state, - logmath_exp(fsg->lmath, - (int32) (tl->logs2prob / fsg->lw)), - (tl->wid < 0) ? "" : fsg_model_word_str(fsg, tl->wid)); - } - } - - fprintf(fp, "%s\n", FSG_MODEL_END_DECL); - - fflush(fp); -} - -void -fsg_model_writefile(fsg_model_t * fsg, char const *file) -{ - FILE *fp; - - assert(fsg); - - E_INFO("Writing FSG file '%s'\n", file); - - if ((fp = fopen(file, "w")) == NULL) { - E_ERROR_SYSTEM("Failed to open FSG file '%s' for reading", file); - return; - } - - fsg_model_write(fsg, fp); - - fclose(fp); -} - -static void -fsg_model_write_fsm_trans(fsg_model_t * fsg, int i, FILE * fp) -{ - fsg_arciter_t *itor; - - for (itor = fsg_model_arcs(fsg, i); itor; - itor = fsg_arciter_next(itor)) { - fsg_link_t *tl = fsg_arciter_get(itor); - fprintf(fp, "%d %d %s %f\n", - tl->from_state, tl->to_state, - (tl->wid < 0) ? "<eps>" : fsg_model_word_str(fsg, tl->wid), - -logmath_log_to_ln(fsg->lmath, tl->logs2prob / fsg->lw)); - } -} - -void -fsg_model_write_fsm(fsg_model_t * fsg, FILE * fp) -{ - int i; - - /* Write transitions from initial state first. */ - fsg_model_write_fsm_trans(fsg, fsg_model_start_state(fsg), fp); - - /* Other states. */ - for (i = 0; i < fsg->n_state; i++) { - if (i == fsg_model_start_state(fsg)) - continue; - fsg_model_write_fsm_trans(fsg, i, fp); - } - - /* Final state. */ - fprintf(fp, "%d 0\n", fsg_model_final_state(fsg)); - - fflush(fp); -} - -void -fsg_model_writefile_fsm(fsg_model_t * fsg, char const *file) -{ - FILE *fp; - - assert(fsg); - - E_INFO("Writing FSM file '%s'\n", file); - - if ((fp = fopen(file, "w")) == NULL) { - E_ERROR_SYSTEM("Failed to open fsm file '%s' for writing", file); - return; - } - - fsg_model_write_fsm(fsg, fp); - - fclose(fp); -} - -void -fsg_model_write_symtab(fsg_model_t * fsg, FILE * file) -{ - int i; - - fprintf(file, "<eps> 0\n"); - for (i = 0; i < fsg_model_n_word(fsg); ++i) { - fprintf(file, "%s %d\n", fsg_model_word_str(fsg, i), i + 1); - } - fflush(file); -} - -void -fsg_model_writefile_symtab(fsg_model_t * fsg, char const *file) -{ - FILE *fp; - - assert(fsg); - - E_INFO("Writing FSM symbol table '%s'\n", file); - - if ((fp = fopen(file, "w")) == NULL) { - E_ERROR("Failed to open symbol table '%s' for writing", file); - return; - } - - fsg_model_write_symtab(fsg, fp); - - fclose(fp); -} |