📄 dict.c
字号:
/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- *//* ==================================================================== * Copyright (c) 1999-2001 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 work was supported in part by funding from the Defense Advanced * Research Projects Agency and the National Science Foundation of the * United States of America, and the CMU Sphinx Speech Consortium. * * 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. * * ==================================================================== * *//* * HISTORY * * 05-Nov-98 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * dict_load now terminates program if input dictionary * contains errors. * * 21-Nov-97 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Bugfix: Noise dictionary was not being considered in figuring * dictionary size. * * 18-Nov-97 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Added ability to modify pronunciation of an existing word in * dictionary (in dict_add_word()). * * 10-Aug-97 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Added check for word already existing in dictionary in * dict_add_word(). * * 27-May-97 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Included Bob Brennan's personaldic handling (similar to * oovdic). * * 11-Apr-97 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Made changes to replace_dict_entry to handle the addition of * alternative pronunciations (linking in alt, wid, fwid fields). * * 02-Apr-97 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Caused a fatal error if max size exceeded, instead of realloc. * * 08-Dec-95 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Added function dict_write_oovdict(). * * 06-Dec-95 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie-Mellon University * Added functions dict_next_alt() and dict_pron(). * * Revision 8.5 94/10/11 12:32:03 rkm * Minor changes. * * Revision 8.4 94/07/29 11:49:59 rkm * Changed handling of OOV subdictionary (no longer alternatives to <UNK>). * Added placeholders for dynamic addition of words to dictionary. * Added dict_add_word () for adding new words to dictionary. * * Revision 8.3 94/04/14 15:08:31 rkm * Added function dictid_to_str(). * * Revision 8.2 94/04/14 14:34:11 rkm * Added OOV words sub-dictionary. * * Revision 8.1 94/02/15 15:06:26 rkm * Basically the same as in v7; includes multiple start symbols for * the LISTEN project. * * 11-Feb-94 M K Ravishankar (rkm) at Carnegie-Mellon University * Added multiple start symbols for the LISTEN project. * * 9-Sep-92 Fil Alleva (faa) at Carnegie-Mellon University * Added special silences for start_sym and end_sym. * These special silences * (SILb and SILe) are CI models and as such they create a new context, * however since no triphones model these contexts explicity they are * backed off to silence, which is the desired context. Therefore no * special measures are take inside the decoder to handle these * special silences. * 14-Oct-92 Eric Thayer (eht) at Carnegie Mellon University * added Ravi's formal declarations for dict_to_id() so int32 -> pointer * problem doesn't happen on DEC Alpha * 14-Oct-92 Eric Thayer (eht) at Carnegie Mellon University * added Ravi's changes to make calls into hash.c work properly on Alpha * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <cmd_ln.h>#include <ckd_alloc.h>#include <pio.h>#include <hash_table.h>#include <err.h>#include "s2types.h"#include "strfuncs.h"#include "basic_types.h"#include "list.h"#include "phone.h"#include "dict.h"#include "search_const.h"#include "lmclass.h"#include "lm_3g.h"#include "msd.h"#include "kb.h"#ifdef DEBUG#define DFPRINTF(x) fprintf x#else#define DFPRINTF(x)#endif#define QUIT(x) {fprintf x; exit(-1);}extern int32 use_noise_words;static void buildEntryTable(list_t * list, int32 *** table_p);static void buildExitTable(list_t * list, int32 *** table_p, int32 *** permuTab_p, int32 ** sizeTab_p);static int32 addToLeftContextTable(char *diphone);static int32 addToRightContextTable(char *diphone);static void recordMissingTriphone(char *triphoneStr);static dict_entry_t *_new_dict_entry(char *word_str, char *pronoun_str, int32 use_context);static void _dict_list_add(dictT * dict, dict_entry_t * entry);static void dict_load(dictT * dict, char *filename, int32 * word_id, int32 use_context);static hash_table_t *mtpHT; /* Missing triphone hash table */static glist_t mtpList;static hash_table_t *lcHT; /* Left context hash table */static list_t lcList;static int32 **lcFwdTable;static int32 **lcBwdTable;static int32 **lcBwdPermTable;static int32 *lcBwdSizeTable;static hash_table_t *rcHT; /* Right context hash table */static list_t rcList;static int32 **rcFwdTable;static int32 **rcFwdPermTable;static int32 **rcBwdTable;static int32 *rcFwdSizeTable;/* First and last OOVs loaded DURING INITIALIZATION */static int32 first_initial_oov, last_initial_oov;/* Placeholders for dynamically added new words, OOVs */static int32 initial_dummy; /* 1st placeholder for dynamic OOVs after initialization */static int32 first_dummy; /* 1st dummy available for dynamic OOVs at any time */static int32 last_dummy; /* last dummy available for dynamic OOVs */#define MAX_PRONOUN_LEN 150static int32get_dict_size(char *file){ FILE *fp; char line[1024]; int32 n; fp = myfopen(file, "r"); for (n = 0;; n++) if (fgets(line, sizeof(line), fp) == NULL) break; fclose(fp); return n;}int32dict_read(dictT * dict, char *filename, /* Main dict file */ char *n_filename, /* Noise dict file */ int32 use_context)/*------------------------------------------------------------* * read in the dict file filename *------------------------------------------------------------*/{ int32 retval = 0; int32 word_id = 0, i, j; dict_entry_t *entry; int32 max_new_oov; char *oovdic; char *personalDic; char *startsym_file; /* * Find size of dictionary and set hash and list table size hints. * (Otherwise, the simple-minded PC malloc library goes berserk.) */ j = get_dict_size(filename); if (n_filename) j += get_dict_size(n_filename); if ((oovdic = cmd_ln_str("-oovdict")) != NULL) j += get_dict_size(oovdic); if ((personalDic = cmd_ln_str("-perdict")) != NULL) { FILE *tmp; /* personalDic exists */ if ((tmp = fopen(personalDic, "r")) != NULL) j += get_dict_size(personalDic); if (tmp) fclose(tmp); } if ((max_new_oov = cmd_ln_int32("-maxnewoov")) > 0) j += max_new_oov; if ((startsym_file = cmd_ln_str("-startsymfn")) != NULL) j += get_dict_size(startsym_file); /* FIXME: <unk> is no longer used, is this still correct? */ j += 4; /* </s>, <s>, <unk> and <sil> */ if (dict->dict) hash_table_free(dict->dict); dict->dict = hash_table_new(j, HASH_CASE_NO); /* Context table size hint: (#CI*#CI)/2 */ j = phoneCiCount(); j = ((j * j) >> 1) + 1; mtpHT = hash_table_new(j, HASH_CASE_YES); if (use_context) { if (lcHT) hash_table_free(lcHT); lcHT = hash_table_new(j, HASH_CASE_YES); if (rcHT) hash_table_free(rcHT); rcHT = hash_table_new(j, HASH_CASE_YES); lcList.size_hint = j; rcList.size_hint = j; } /* Load dictionaries */ dict_load(dict, filename, &word_id, use_context); /* Add words with known pronunciations but which are OOVs wrt LM */ first_initial_oov = word_id; if ((oovdic = cmd_ln_str("-oovdict")) != NULL) dict_load(dict, oovdic, &word_id, use_context); if ((personalDic = cmd_ln_str("-perdict")) != NULL) { FILE *tmp; /* personalDic exists */ if ((tmp = fopen(personalDic, "r")) != NULL) dict_load(dict, personalDic, &word_id, use_context); if (tmp != NULL) fclose(tmp); } last_initial_oov = word_id - 1; /* Placeholders (dummy pronunciations) for new words that can be added at runtime */ initial_dummy = first_dummy = word_id; if ((max_new_oov = cmd_ln_int32("-maxnewoov")) > 0) E_INFO("Allocating %d placeholders for new OOVs\n", max_new_oov); for (i = 0; i < max_new_oov; i++) { char tmpstr[100], pronstr[100]; /* Pick a temporary name that doesn't occur in the LM */ sprintf(tmpstr, "=PLCHLDR%d=", i); /* new_dict_entry clobbers pronstr! so need this strcpy in the loop */ strcpy(pronstr, "SIL"); entry = _new_dict_entry(tmpstr, pronstr, TRUE); if (!entry) E_FATAL("Failed to add DUMMY(SIL) entry to dictionary\n"); _dict_list_add(dict, entry); hash_table_enter(dict->dict, entry->word, (void *) word_id); entry->wid = word_id; entry->fwid = word_id; word_id++; } last_dummy = word_id - 1; /* * Special case the start symbol and end symbol phrase markers. * Special case the silence word 'SIL'. */ { void *val; if (hash_table_lookup(dict->dict, cmd_ln_str("-lmendsym"), &val) != 0) { /* * Check if there is a special end silence phone. */ if (NO_PHONE == phone_to_id("SILe", FALSE)) { entry = _new_dict_entry(cmd_ln_str("-lmendsym"), "SIL", FALSE); if (!entry) E_FATAL("Failed to add </s>(SIL) to dictionary\n"); } else { E_INFO("Using special end silence for %s\n", cmd_ln_str("-lmendsym")); entry = _new_dict_entry(cmd_ln_str("-lmendsym"), "SILe", FALSE); } _dict_list_add(dict, entry); hash_table_enter(dict->dict, entry->word, (void *) word_id); entry->wid = word_id; entry->fwid = word_id; word_id++; } /* Mark the start of filler words */ dict->filler_start = word_id; /* Add [multiple] start symbols to dictionary (LISTEN project) */ if ((startsym_file = cmd_ln_str("-startsymfn")) != NULL) { FILE *ssfp; char line[1000], startsym[1000]; char *startsym_phone; E_INFO("Reading start-syms file %s\n", startsym_file); startsym_phone = ckd_salloc((phone_to_id("SILb", FALSE) == NO_PHONE) ? "SIL" : "SILb"); ssfp = myfopen(startsym_file, "r"); while (fgets(line, sizeof(line), ssfp) != NULL) { if (sscanf(line, "%s", startsym) != 1) E_FATAL("File format error\n"); entry = _new_dict_entry(startsym, startsym_phone, FALSE); if (!entry) E_FATAL("Failed to add %s to dictionary\n", startsym); _dict_list_add(dict, entry); hash_table_enter(dict->dict, entry->word, (void *) word_id); entry->wid = word_id; entry->fwid = word_id; word_id++; } ckd_free(startsym_phone); } /* Add the standard start symbol (<s>) if not already in dict */ if (hash_table_lookup(dict->dict, cmd_ln_str("-lmstartsym"), &val) != 0) { /* * Check if there is a special begin silence phone. */ if (NO_PHONE == phone_to_id("SILb", FALSE)) { entry = _new_dict_entry(cmd_ln_str("-lmstartsym"), "SIL", FALSE); if (!entry) E_FATAL("Failed to add <s>(SIL) to dictionary\n"); } else { E_INFO("Using special begin silence for %s\n", cmd_ln_str("-lmstartsym")); entry = _new_dict_entry(cmd_ln_str("-lmstartsym"), "SILb", FALSE); if (!entry) E_FATAL("Failed to add <s>(SILb) to dictionary\n"); } _dict_list_add(dict, entry); hash_table_enter(dict->dict, entry->word, (void *) word_id); entry->wid = word_id; entry->fwid = word_id; word_id++; } /* Finally create a silence phone if it isn't there already. */ if (hash_table_lookup(dict->dict, "SIL", &val) != 0) { entry = _new_dict_entry("SIL", "SIL", FALSE); if (!entry) E_FATAL("Failed to add <sil>(SIL) to dictionary\n"); _dict_list_add(dict, entry); hash_table_enter(dict->dict, entry->word, (void *) word_id); entry->wid = word_id; entry->fwid = word_id; word_id++; } } if (n_filename) dict_load(dict, n_filename, &word_id, FALSE /* use_context */); E_INFO("LEFT CONTEXT TABLES\n"); buildEntryTable(&lcList, &lcFwdTable); buildExitTable(&lcList, &lcBwdTable, &lcBwdPermTable, &lcBwdSizeTable); E_INFO("RIGHT CONTEXT TABLES\n"); buildEntryTable(&rcList, &rcBwdTable); buildExitTable(&rcList, &rcFwdTable, &rcFwdPermTable, &rcFwdSizeTable); mtpList = hash_table_tolist(mtpHT, &i); E_INFO("%5d unique triphones were mapped to ci phones\n", i); hash_table_free(mtpHT); mtpHT = NULL; return (retval);}voiddict_free(dictT * dict){ int32 i; int32 entry_count; dict_entry_t *entry; entry_count = dict->dict_entry_count; for (i = 0; i < entry_count; i++) { entry = dict_get_entry(dict, i); free(entry->word); free(entry->phone_ids); free(entry->ci_phone_ids);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -