⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bin_mdef.c

📁 WinCE平台上的语音识别程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- *//* ==================================================================== * Copyright (c) 2005 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. * * ==================================================================== * *//********************************************************************* * * File: bin_mdef.c *  * Description:  *	Binary format model definition files, with support for *	heterogeneous topologies and variable-size N-phones * * Author:  * 	David Huggins-Daines <dhuggins@cs.cmu.edu> *********************************************************************/#include <stdio.h>#include <string.h>#include <assert.h>#include "bin_mdef.h"#include "s2types.h"#include "ckd_alloc.h"#include "byteorder.h"#include "err.h"bin_mdef_t *bin_mdef_read_text(const char *filename){    bin_mdef_t *bmdef;    mdef_t *mdef;    int i, nodes, ci_idx, lc_idx, rc_idx;    int nchars;    if ((mdef = mdef_init((char *) filename, TRUE)) == NULL)        return NULL;    bmdef = ckd_calloc(1, sizeof(*bmdef));    /* Easy stuff.  The mdef.c code has done the heavy lifting for us. */    bmdef->n_ciphone = mdef->n_ciphone;    bmdef->n_phone = mdef->n_phone;    bmdef->n_emit_state = mdef->n_emit_state;    bmdef->n_ci_sen = mdef->n_ci_sen;    bmdef->n_sen = mdef->n_sen;    bmdef->n_tmat = mdef->n_tmat;    bmdef->n_sseq = mdef->n_sseq;    bmdef->sseq = mdef->sseq;    bmdef->cd2cisen = mdef->cd2cisen;    bmdef->sen2cimap = mdef->sen2cimap;    bmdef->n_ctx = 3;           /* Triphones only. */    bmdef->sil = mdef->sil;    mdef->sseq = NULL;          /* We are taking over this one. */    mdef->cd2cisen = NULL;      /* And this one. */    mdef->sen2cimap = NULL;     /* And this one. */    /* Get the phone names.  If they are not sorted     * ASCII-betically then we are in a world of hurt and     * therefore will simply refuse to continue. */    bmdef->ciname = ckd_calloc(bmdef->n_ciphone, sizeof(*bmdef->ciname));    nchars = 0;    for (i = 0; i < bmdef->n_ciphone; ++i)        nchars += strlen(mdef->ciphone[i].name) + 1;    bmdef->ciname[0] = ckd_calloc(nchars, 1);    strcpy(bmdef->ciname[0], mdef->ciphone[0].name);    for (i = 1; i < bmdef->n_ciphone; ++i) {        bmdef->ciname[i] =            bmdef->ciname[i - 1] + strlen(bmdef->ciname[i - 1]) + 1;        strcpy(bmdef->ciname[i], mdef->ciphone[i].name);        if (i > 0 && strcmp(bmdef->ciname[i - 1], bmdef->ciname[i]) > 0)            E_FATAL("Phone names are not in sorted order, sorry.");    }    /* Copy over phone information. */    bmdef->phone = ckd_calloc(bmdef->n_phone, sizeof(*bmdef->phone));    for (i = 0; i < mdef->n_phone; ++i) {        bmdef->phone[i].ssid = mdef->phone[i].ssid;        bmdef->phone[i].tmat = mdef->phone[i].tmat;        if (i < bmdef->n_ciphone) {            bmdef->phone[i].info.ci.filler = mdef->ciphone[i].filler;        }        else {            bmdef->phone[i].info.cd.wpos = mdef->phone[i].wpos;            bmdef->phone[i].info.cd.ctx[0] = mdef->phone[i].ci;            bmdef->phone[i].info.cd.ctx[1] = mdef->phone[i].lc;            bmdef->phone[i].info.cd.ctx[2] = mdef->phone[i].rc;        }    }    /* Walk the wpos_ci_lclist once to find the total number of     * nodes and the starting locations for each level. */    nodes = lc_idx = ci_idx = rc_idx = 0;    for (i = 0; i < N_WORD_POSN; ++i) {        int j;        for (j = 0; j < mdef->n_ciphone; ++j) {            ph_lc_t *lc;            for (lc = mdef->wpos_ci_lclist[i][j]; lc; lc = lc->next) {                ph_rc_t *rc;                for (rc = lc->rclist; rc; rc = rc->next) {                    ++nodes;    /* RC node */                }                ++nodes;        /* LC node */                ++rc_idx;       /* Start of RC nodes (after LC nodes) */            }            ++nodes;            /* CI node */            ++lc_idx;           /* Start of LC nodes (after CI nodes) */            ++rc_idx;           /* Start of RC nodes (after CI and LC nodes) */        }        ++nodes;                /* wpos node */        ++ci_idx;               /* Start of CI nodes (after wpos nodes) */        ++lc_idx;               /* Start of LC nodes (after CI nodes) */        ++rc_idx;               /* STart of RC nodes (after wpos, CI, and LC nodes) */    }    E_INFO        ("cd_tree: nodes %d wpos start 0 ci start %d lc start %d rc start %d\n",         nodes, ci_idx, lc_idx, rc_idx);    bmdef->n_cd_tree = nodes;    bmdef->cd_tree = ckd_calloc(nodes, sizeof(*bmdef->cd_tree));    for (i = 0; i < N_WORD_POSN; ++i) {        int j;        bmdef->cd_tree[i].ctx = i;        bmdef->cd_tree[i].n_down = mdef->n_ciphone;        bmdef->cd_tree[i].c.down = ci_idx;#if 0        E_INFO("%d => %c (%d@%d)\n",               i, (WPOS_NAME)[i],               bmdef->cd_tree[i].n_down, bmdef->cd_tree[i].c.down);#endif        /* Now we can build the rest of the tree. */        for (j = 0; j < mdef->n_ciphone; ++j) {            ph_lc_t *lc;            bmdef->cd_tree[ci_idx].ctx = j;            bmdef->cd_tree[ci_idx].c.down = lc_idx;            for (lc = mdef->wpos_ci_lclist[i][j]; lc; lc = lc->next) {                ph_rc_t *rc;                bmdef->cd_tree[lc_idx].ctx = lc->lc;                bmdef->cd_tree[lc_idx].c.down = rc_idx;                for (rc = lc->rclist; rc; rc = rc->next) {                    bmdef->cd_tree[rc_idx].ctx = rc->rc;                    bmdef->cd_tree[rc_idx].n_down = 0;                    bmdef->cd_tree[rc_idx].c.pid = rc->pid;#if 0                    E_INFO("%d => %s %s %s %c (%d@%d)\n",                           rc_idx,                           bmdef->ciname[j],                           bmdef->ciname[lc->lc],                           bmdef->ciname[rc->rc],                           (WPOS_NAME)[i],                           bmdef->cd_tree[rc_idx].n_down,                           bmdef->cd_tree[rc_idx].c.down);#endif                    ++bmdef->cd_tree[lc_idx].n_down;                    ++rc_idx;                }                /* If there are no triphones here,                 * this is considered a leafnode, so                 * set the pid to BAD_S3PID. */                if (bmdef->cd_tree[lc_idx].n_down == 0)                    bmdef->cd_tree[lc_idx].c.pid = BAD_S3PID;#if 0                E_INFO("%d => %s %s %c (%d@%d)\n",                       lc_idx,                       bmdef->ciname[j],                       bmdef->ciname[lc->lc],                       (WPOS_NAME)[i],                       bmdef->cd_tree[lc_idx].n_down,                       bmdef->cd_tree[lc_idx].c.down);#endif                ++bmdef->cd_tree[ci_idx].n_down;                ++lc_idx;            }            /* As above, so below. */            if (bmdef->cd_tree[ci_idx].n_down == 0)                bmdef->cd_tree[ci_idx].c.pid = BAD_S3PID;#if 0            E_INFO("%d => %d=%s (%d@%d)\n",                   ci_idx, j, bmdef->ciname[j],                   bmdef->cd_tree[ci_idx].n_down,                   bmdef->cd_tree[ci_idx].c.down);#endif            ++ci_idx;        }    }    mdef_free(mdef);    bmdef->alloc_mode = BIN_MDEF_FROM_TEXT;    return bmdef;}voidbin_mdef_free(bin_mdef_t * m){    if (m->alloc_mode == BIN_MDEF_FROM_TEXT) {        ckd_free(m->sseq[0]);        ckd_free(m->cd_tree);    }    if (m->alloc_mode == BIN_MDEF_IN_MEMORY)        ckd_free(m->ciname[0]);    ckd_free(m->ciname);    ckd_free(m->sseq);    ckd_free(m);}static const char format_desc[] =    "BEGIN FILE FORMAT DESCRIPTION\n"    "int32 n_ciphone;    /**< Number of base (CI) phones */\n"    "int32 n_phone;	     /**< Number of base (CI) phones + (CD) triphones */\n"    "int32 n_emit_state; /**< Number of emitting states per phone (0 if heterogeneous) */\n"    "int32 n_ci_sen;     /**< Number of CI senones; these are the first */\n"    "int32 n_sen;	     /**< Number of senones (CI+CD) */\n"    "int32 n_tmat;	     /**< Number of transition matrices */\n"    "int32 n_sseq;       /**< Number of unique senone sequences */\n"    "int32 n_ctx;	     /**< Number of phones of context */\n"    "int32 n_cd_tree;    /**< Number of nodes in CD tree structure */\n"    "int32 sil;	     /**< CI phone ID for silence */\n"    "char ciphones[][];  /**< CI phone strings (null-terminated) */\n"    "char padding[];     /**< Padding to a 4-bytes boundary */\n"    "struct { int16 ctx; int16 n_down; int32 pid/down } cd_tree[];\n"    "struct { int32 ssid; int32 tmat; int8 attr[4] } phones[];\n"    "int32 sseq[];       /**< Unique senone sequences */\n"    "int8 sseq_len[];    /**< Number of states in each sseq (none if homogeneous) */\n"    "END FILE FORMAT DESCRIPTION\n";bin_mdef_t *bin_mdef_read(const char *filename){    bin_mdef_t *m;    FILE *fh;    size_t tree_start;    int32 val, i, swap, pos, end;    int32 *sseq_size;    /* Try to read it as text first. */    if ((m = bin_mdef_read_text(filename)) != NULL)        return m;    E_INFO("Reading binary model definition: %s\n", filename);    if ((fh = fopen(filename, "rb")) == NULL)        return NULL;    if (fread(&val, 4, 1, fh) != 1)        E_FATAL_SYSTEM("Failed to read byte-order marker from %s\n",                       filename);    swap = 0;    if (val == BIN_MDEF_OTHER_ENDIAN) {        swap = 1;        E_INFO("Must byte-swap %s\n", filename);    }    if (fread(&val, 4, 1, fh) != 1)        E_FATAL_SYSTEM("Failed to read version from %s\n", filename);    if (swap)        SWAP_INT32(&val);    if (val > BIN_MDEF_FORMAT_VERSION) {        E_ERROR("File format version %d for %s is newer than library\n",                val, filename);        fclose(fh);        return NULL;    }    if (fread(&val, 4, 1, fh) != 1)        E_FATAL_SYSTEM("Failed to read header length from %s\n", filename);    if (swap)        SWAP_INT32(&val);    /* Skip format descriptor. */    fseek(fh, val, SEEK_CUR);    /* Finally allocate it. */    m = ckd_calloc(1, sizeof(*m));    /* Don't bother to check each one, since they will all fail if one failed. */    fread(&m->n_ciphone, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_ciphone);    fread(&m->n_phone, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_phone);    fread(&m->n_emit_state, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_emit_state);    fread(&m->n_ci_sen, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_ci_sen);    fread(&m->n_sen, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_sen);    fread(&m->n_tmat, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_tmat);    fread(&m->n_sseq, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_sseq);    fread(&m->n_ctx, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_ctx);    fread(&m->n_cd_tree, 4, 1, fh);    if (swap)        SWAP_INT32(&m->n_cd_tree);    if (fread(&val, 4, 1, fh) != 1)        E_FATAL_SYSTEM("Failed to read header from %s\n", filename);    m->sil = val;    /* Read the rest of the file as a big block of memory, and     * carve it into the relevant chunks (in the future we will     * mmap() it instead if possible). */    pos = ftell(fh);    fseek(fh, 0, SEEK_END);    end = ftell(fh);    fseek(fh, pos, SEEK_SET);    m->ciname = ckd_calloc(m->n_ciphone, sizeof(*m->ciname));    m->ciname[0] = ckd_malloc(end - pos);    if (fread(m->ciname[0], 1, end - pos, fh) != end - pos)        E_FATAL_SYSTEM("Failed to read %d bytes of data from %s\n",                       end - pos, filename);    for (i = 1; i < m->n_ciphone; ++i)        m->ciname[i] = m->ciname[i - 1] + strlen(m->ciname[i - 1]) + 1;    /* Skip past the padding. */    tree_start =        m->ciname[i - 1] + strlen(m->ciname[i - 1]) + 1 - m->ciname[0];    tree_start = (tree_start + 3) & ~3;    m->cd_tree = (cd_tree_t *) (m->ciname[0] + tree_start);    if (swap) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -