summaryrefslogtreecommitdiffstats
path: root/media/sphinxbase/src/libsphinxbase/lm/fsg_model.c
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-05-20 10:19:04 +0000
committerMoonchild <moonchild@palemoon.org>2020-05-20 14:04:17 +0000
commit99c2e698d2a3c56649e42d8d2133706cd8c9501e (patch)
tree85be449d772eb57860f0f386efb4bc1e790fd498 /media/sphinxbase/src/libsphinxbase/lm/fsg_model.c
parent15ac4021b06d549e47c9e2efc9364a9eb96bfe82 (diff)
downloadUXP-99c2e698d2a3c56649e42d8d2133706cd8c9501e.tar
UXP-99c2e698d2a3c56649e42d8d2133706cd8c9501e.tar.gz
UXP-99c2e698d2a3c56649e42d8d2133706cd8c9501e.tar.lz
UXP-99c2e698d2a3c56649e42d8d2133706cd8c9501e.tar.xz
UXP-99c2e698d2a3c56649e42d8d2133706cd8c9501e.zip
Issue #1538 - remove speech recognition engine
This removes speech recognition, pocketsphinx, training models and the speech automated test interface. This also re-establishes proper use of MOZ_WEBSPEECH to work for the speech API (synthesis part only) that was a broken mess before, with some synth parts being always built, some parts being built only with it enabled and recognition parts being dependent on it. I'm pretty sure it'd be totally busted if you'd ever have tried building without MOZ_WEBPEECH before. Tested that synthesis still works as-intended. This resolves #1538
Diffstat (limited to 'media/sphinxbase/src/libsphinxbase/lm/fsg_model.c')
-rw-r--r--media/sphinxbase/src/libsphinxbase/lm/fsg_model.c944
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);
-}