Beispiel #1
0
void
print_phone_list(acmod_id_t *p,
		 uint32 n_p,
		 char *btw,
		 acmod_set_t *acmod_set)
{
    uint32 i, j, k;
    uint32 mpl, l;
    char fmt[16];
    uint32 ppl;

    for (i = 0, mpl = 0; i < n_p; i++) {
	l = strlen(acmod_set_id2name(acmod_set, p[i]));
	if (l > mpl) mpl = l;
    }

    sprintf(fmt, "%%%ds%%s", mpl);

    ppl = 80 / mpl;

    /* print out the phone sequence in rows of at most PPL phones */
    for (i = 0; i < n_p; i += ppl) {
	for (j = i, k = (i + ppl > n_p ? n_p : i + ppl); j < k; j++) {
	    printf(fmt, "", (btw[j] ? "+" : " "));
	}
	printf("\n");

	for (j = i, k = (i + ppl > n_p ? n_p : i + ppl); j < k; j++) {
	    printf(fmt, acmod_set_id2name(acmod_set, p[j]), " ");
	}
	printf("\n");
	printf("\n");
    }
}
int
s3phseg_write(const char *fn,
	      acmod_set_t *acmod_set,
	      s3phseg_t *phseg)
{
	FILE *fp;

	if ((fp = fopen(fn, "w")) == NULL)
		return S3_ERROR;

	fprintf (fp, "\t%5s %5s %9s %s\n",
		 "SFrm", "EFrm", "SegAScr", "Phone");
	for (; phseg; phseg = phseg->next) {
		fprintf(fp, "\t%5d %5d %9d %s\n",
			phseg->sf, phseg->ef, phseg->score,
			acmod_set_id2name(acmod_set, phseg->phone));
	}
	fclose (fp);

	return S3_SUCCESS;
}
Beispiel #3
0
void
accum_global_tmat(model_inventory_t *inv,
		  state_t *state,
		  uint32 n_state)
{
    float32 ***tmat_acc;	/* global tmat accumulators */
    float32 **l_tmat_acc;	/* local tmat accumulators (indexed by sentence HMM state id) */
    uint32 tmat;		/* a transition matrix id */
    uint32 model_i;		/* a model source state */
    uint32 model_j;		/* a model destination state */
    uint32 next_tmat;		/* the transition matrix associated w/ the destination state */
    uint32 i, u, j;		/* iterators and temporary variables */

    tmat_acc = inv->tmat_acc;
    l_tmat_acc = inv->l_tmat_acc;

    for (i = 0; i < n_state; i++) {
	tmat = state[i].tmat;
	model_i = state[i].m_state;

	for (u = 0; u < state[i].n_next; u++) {
	    j = state[i].next_state[u];

	    next_tmat = state[j].tmat;
	    model_j = state[j].m_state;
	    if ((next_tmat == tmat) && (model_i <= model_j)) {
	        /* internal phone model transition */
#ifdef ACCUM_VERBOSE
		printf("(%s %d %d) += (%d %d)\n",
		       acmod_set_id2name(inv->acmod_set, tmat), model_i, model_j,
		       i, j);
#endif
		
		tmat_acc[tmat][model_i][model_j] +=
		    l_tmat_acc[i][j-i];
	    }
	}
    }
}
Beispiel #4
0
int
s2_write_hmm(float32 ***tmat,
	     acmod_set_t *acmod_set,
	     const char *out_dir_name)
{ 
    uint32 n_ci;
    uint32 i;
    int err;

    n_ci = acmod_set_n_ci(acmod_set);

    E_INFO("Writing %d tied CI transition matrices to %s\n",
	   n_ci, out_dir_name);

    err = 0;
    for (i = 0; i < n_ci; i++) {
	if (put_sdm(tmat[i],
		    out_dir_name,
		    acmod_set_id2name(acmod_set, i)) != S3_SUCCESS)
	    err = 1;
	
#ifdef S2_WRITE_HMM_VERBOSE
	if (!err) {
	    print_tmat(stdout, tmat[i], S2_N_STATE);
	    fflush(stdout);
	}
#endif
    }
    
    if (!err) {
	return S3_SUCCESS;
    }
    else {
	return S3_ERROR;
    }
}
Beispiel #5
0
uint32
setup_d2o_map(model_def_t *d_mdef,
	      model_def_t *o_mdef)
{
    model_def_entry_t *o_defn, *d_defn;
    uint32 d_ts;
    uint32 o_ts;
    uint32 *mapped;
    uint32 i, j, k, d;
    const char *nm;
    int did_warn = FALSE;

    if (d_mdef->n_tied_state < o_mdef-> n_tied_state) {
	E_FATAL("more tied states in output than in dump mdef (%u vs %u)\n",
		o_mdef->n_tied_state, d_mdef->n_tied_state);
    }
    if (d_mdef->n_tied_ci_state != o_mdef->n_tied_ci_state) {
	E_FATAL("# tied ci state in output, %u not equal to # in dmp, %u\n",
		o_mdef->n_tied_ci_state, d_mdef->n_tied_ci_state);
    }

    n_o2d  =  (uint32 *)ckd_calloc(o_mdef->n_tied_state, sizeof(uint32));
    i_o2d  =  (uint32 *)ckd_calloc(o_mdef->n_tied_state, sizeof(uint32));
    o2d    = (uint32 **)ckd_calloc(o_mdef->n_tied_state, sizeof(uint32 *));
    mapped =  (uint32 *)ckd_calloc(d_mdef->n_tied_state, sizeof(uint32));

    for (i = 0; i < o_mdef->n_defn; i++) {
	nm = acmod_set_id2name(o_mdef->acmod_set, i);
	
	d = acmod_set_name2id(d_mdef->acmod_set, nm);

	if (d == NO_ID) {
	    if (!did_warn) {
		E_WARN("Some models in the output mdef not in the dump mdef\n");
		did_warn = TRUE;
	    }
	    continue;
	}

	o_defn = &o_mdef->defn[i];
	d_defn = &d_mdef->defn[d];

	for (j = 0; j < o_defn->n_state; j++) {
	    o_ts = o_defn->state[j];
	    d_ts = d_defn->state[j];
	    if ((o_ts != TYING_NO_ID) && (o_ts != TYING_NO_ID)) {
		if (mapped[d_ts] == FALSE) {
		    ++n_o2d[o_ts];
		    mapped[d_ts] = TRUE;
		}
	    }
	    else {
		if (!((o_ts == TYING_NO_ID) && (o_ts == TYING_NO_ID))) {
		    E_INFO("%s state is NULL but %s isn't.\n",
			   (o_ts == TYING_NO_ID ? "output" : "dump"),
			   (o_ts == TYING_NO_ID ? "dump" : "output"));
		}
	    }
	}
    }

    for (i = 0; i < o_mdef->n_tied_state; i++) {
	o2d[i] = (uint32 *)ckd_calloc(n_o2d[i], sizeof(uint32));
    }

    for (i = 0; i < o_mdef->n_defn; i++) {
	/* Figure out the index in the dump mdef
	   for the model in the output mdef */

	nm = acmod_set_id2name(o_mdef->acmod_set, i);
	
	d = acmod_set_name2id(d_mdef->acmod_set, nm);

	if (d == NO_ID) continue;


	o_defn = &o_mdef->defn[i];
	d_defn = &d_mdef->defn[d];

	for (j = 0; j < o_defn->n_state; j++) {
	    o_ts = o_defn->state[j];
	    d_ts = d_defn->state[j];
	    if ((o_ts != TYING_NO_ID) && (o_ts != TYING_NO_ID)) {
		for (k = 0; k < i_o2d[o_ts]; k++) {
		    if (o2d[o_ts][k] == d_ts)
			break;
		}
		if (k == i_o2d[o_ts]) {
		    o2d[o_ts][i_o2d[o_ts]++] = d_ts;
		}
	    }
	    else {
		if (!((o_ts == TYING_NO_ID) && (o_ts == TYING_NO_ID))) {
		    E_INFO("%s state is NULL but %s isn't.\n",
			   (o_ts == TYING_NO_ID ? "output" : "dump"),
			   (o_ts == TYING_NO_ID ? "dump" : "output"));
		}
	    }
	}
    }

    for (i = 0; i < o_mdef->n_tied_state; i++) {
	if (i_o2d[i] != n_o2d[i]) {
	    E_FATAL("%u != %u for %u\n",
		    i_o2d[i], n_o2d[i], i);
	}
    }

    for (i = 0; i < o_mdef->n_tied_state; i++) {
	i_o2d[i] = 0;
    }
    return S3_SUCCESS;
}
Beispiel #6
0
int32
model_def_write(model_def_t *mdef,
		const char *fn)
{
    FILE *fp;
    uint32 n_ci;
    uint32 n_acmod;
    acmod_set_t *acmod_set;
    const char **attrib;
    acmod_id_t b;
    acmod_id_t l;
    acmod_id_t r;
    word_posn_t wp;
    uint32 p;
    char *wp2c = WORD_POSN_CHAR_MAP;
    uint32 i;

    fp = fopen(fn, "w");
    if (fp == NULL) {
	E_ERROR_SYSTEM("Unable to open %s for writing", fn);
	return S3_ERROR;
    }

    acmod_set = mdef->acmod_set;

    fprintf(fp, "%s\n", MODEL_DEF_VERSION);
    n_ci = acmod_set_n_ci(acmod_set);
    fprintf(fp, "%u n_base\n", n_ci);
    fprintf(fp, "%u n_tri\n", acmod_set_n_multi(acmod_set));
    fprintf(fp, "%u n_state_map\n", mdef->n_total_state);
    fprintf(fp, "%u n_tied_state\n", mdef->n_tied_state);
    fprintf(fp, "%u n_tied_ci_state\n", mdef->n_tied_ci_state);
    fprintf(fp, "%u n_tied_tmat\n", mdef->n_tied_tmat);
    fprintf(fp, "#\n# Columns definitions\n");
    fprintf(fp, "#%4s %3s %3s %1s %6s %4s %s\n",
	    "base", "lft", "rt", "p", "attrib", "tmat",
	    "     ... state id's ...");

    n_acmod = acmod_set_n_acmod(acmod_set);
    for (p = 0; p < n_ci; p++) {
	fprintf(fp, "%5s %3s %3s %1s",
		acmod_set_id2name(acmod_set, p),
		"-", "-", "-");

	attrib = acmod_set_attrib(acmod_set, p);
	if ((attrib == NULL) || (attrib[0] == NULL)) {
	    fprintf(fp, " %6s", "n/a");
	}
	else {
	    fprintf(fp, " %6s", attrib[0]);

	    for (i = 1; attrib[i]; i++) {
		fprintf(fp, ",%s", attrib[i]);
	    }
	}
	fprintf(fp, " %4d", mdef->defn[p].tmat);

	for (i = 0; i < mdef->defn[p].n_state; i++) {
	    if (mdef->defn[p].state[i] == NO_ID) {
		fprintf(fp, " N");
	    }
	    else {
		fprintf(fp, " %6u", mdef->defn[p].state[i]);
	    }
	}
	fprintf(fp, "\n");
    }

    for (; p < n_acmod; p++) {
	acmod_set_id2tri(acmod_set,
			 &b, &l, &r, &wp,
			 p);
	
	fprintf(fp, "%5s %3s %3s %c",
		acmod_set_id2name(acmod_set, b),
		acmod_set_id2name(acmod_set, l),
		acmod_set_id2name(acmod_set, r),
		wp2c[(uint32)wp]);

	attrib = acmod_set_attrib(acmod_set, p);
	if ((attrib == NULL) || (attrib[0] == NULL)) {
	    fprintf(fp, " %6s", "n/a");
	}
	else {
	    fprintf(fp, " %6s", attrib[0]);

	    for (i = 1; attrib[i]; i++) {
		fprintf(fp, ",%s", attrib[i]);
	    }
	}
	fprintf(fp, " %4d", mdef->defn[p].tmat);

	for (i = 0; i < mdef->defn[p].n_state; i++) {
	    if (mdef->defn[p].state[i] == NO_ID) {
		fprintf(fp, " N");
	    }
	    else {
		fprintf(fp, " %6u", mdef->defn[p].state[i]);
	    }
	}
	fprintf(fp, "\n");
    }

    fclose(fp);

    return S3_SUCCESS;
}
Beispiel #7
0
int
init(model_def_t **out_imdef,
     pset_t **out_pset,
     uint32 *out_n_pset,
     dtree_t ****out_tree,
     uint32 *out_n_seno)
{
    model_def_t *imdef;
    uint32 p, s;
    uint32 n_ci, n_state;
    char fn[MAXPATHLEN+1];
    const char *a_fn;
    FILE *fp;
    dtree_t ***tree, *tr;
    pset_t *pset;
    uint32 n_pset;
    uint32 n_seno;
    const char *treedir;
    uint32 ts_id;
    int allphones;

    a_fn = cmd_ln_str("-imoddeffn");
    if (a_fn == NULL)
	E_FATAL("Specify -imoddeffn\n");
    if (model_def_read(&imdef, a_fn) != S3_SUCCESS) {
	return S3_ERROR;
    }
    *out_imdef = imdef;

    a_fn = cmd_ln_str("-psetfn");
    E_INFO("Reading: %s\n", a_fn);
    *out_pset = pset = read_pset_file(a_fn, imdef->acmod_set, &n_pset);
    *out_n_pset = n_pset;

    allphones = cmd_ln_int32("-allphones");
    if (allphones)
      n_ci = 1;
    else
      n_ci = acmod_set_n_ci(imdef->acmod_set);

    treedir = cmd_ln_str("-treedir");
    tree = (dtree_t ***)ckd_calloc(n_ci, sizeof(dtree_t **));
    *out_tree = tree;

    ts_id = imdef->n_tied_ci_state;
    for (p = 0, n_seno = 0; p < n_ci; p++) {
	if (allphones || !acmod_set_has_attrib(imdef->acmod_set, p, "filler")) {
	    const char *pname;

	    if (allphones) {
		n_state = imdef->defn[acmod_set_n_ci(imdef->acmod_set)].n_state;
		pname = "ALLPHONES";
	    }
	    else {
		n_state = imdef->defn[p].n_state;
		pname = acmod_set_id2name(imdef->acmod_set, p);
	    }
	    tree[p] = (dtree_t **)ckd_calloc(n_state, sizeof(dtree_t *));

	    for (s = 0; s < n_state-1; s++) {
		E_INFO("%s-%u: offset %u\n",
		       pname, s, ts_id);

		sprintf(fn, "%s/%s-%u.dtree",
			treedir, pname, s);
		fp = fopen(fn, "r");
		if (fp == NULL) {
		    E_FATAL_SYSTEM("Unable to open %s for reading", fn);
		}
		tree[p][s] = tr = read_final_tree(fp, pset, n_pset);

		label_leaves(&tr->node[0], &ts_id);

		fclose(fp);

		n_seno += cnt_leaf(&tr->node[0]);
	    }
	}
    }

    assert(n_seno == (ts_id - imdef->n_tied_ci_state));

    E_INFO("n_seno= %u\n", ts_id);

    *out_n_seno = n_seno;

    return S3_SUCCESS;
}
Beispiel #8
0
int
main(int argc, char *argv[])
{
    model_def_t *imdef;
    model_def_t *omdef;
    pset_t *pset;
    uint32 n_pset;
    dtree_t ***tree;
    uint32 n_seno;
    uint32 n_ci;
    uint32 n_acmod;
    uint32 p;
    uint32 s;
    model_def_entry_t *idefn, *odefn;
    acmod_id_t b, l, r;
    word_posn_t wp;
    int allphones;

    parse_cmd_ln(argc, argv);

    if (init(&imdef, &pset, &n_pset, &tree, &n_seno) != S3_SUCCESS)
	return 1;

    omdef = (model_def_t *)ckd_calloc(1, sizeof(model_def_t));

    omdef->acmod_set = imdef->acmod_set; /* same set of acoustic models */

    omdef->n_total_state = imdef->n_total_state;

    omdef->n_tied_ci_state = imdef->n_tied_ci_state;
    omdef->n_tied_state = imdef->n_tied_ci_state + n_seno;

    omdef->n_tied_tmat = imdef->n_tied_tmat;

    omdef->defn = (model_def_entry_t *)ckd_calloc(imdef->n_defn,
						  sizeof(model_def_entry_t));

    /*
     * Define the context-independent models
     */
    n_ci = acmod_set_n_ci(imdef->acmod_set);
    for (p = 0; p < n_ci; p++) {
	idefn = &imdef->defn[p];
	odefn = &omdef->defn[p];
	
	odefn->p    = idefn->p;
	odefn->tmat = idefn->tmat;

	odefn->state = ckd_calloc(idefn->n_state, sizeof(uint32));
	odefn->n_state = idefn->n_state;

	for (s = 0; s < idefn->n_state; s++) {
	    if (idefn->state[s] == NO_ID)
		odefn->state[s] = NO_ID;
	    else {
		odefn->state[s] = idefn->state[s];
	    }
	}
    }

    /*
     * Define the rest of the models
     */
    allphones = cmd_ln_int32("-allphones");
    n_acmod = acmod_set_n_acmod(omdef->acmod_set);
    for (; p < n_acmod; p++) {
	b = acmod_set_base_phone(omdef->acmod_set, p);

	assert(p != b);

	idefn = &imdef->defn[p];
	odefn = &omdef->defn[p];

	odefn->p    = idefn->p;
	odefn->tmat = idefn->tmat;

	odefn->state = ckd_calloc(idefn->n_state, sizeof(uint32));
	odefn->n_state = idefn->n_state;
	for (s = 0; s < idefn->n_state; s++) {
	    if (idefn->state[s] == NO_ID)
		/* Non-emitting state */
		odefn->state[s] = NO_ID;
	    else {
		uint32 bb;

		/* emitting state: find the tied state */
		acmod_set_id2tri(omdef->acmod_set,
				 &b, &l, &r, &wp,
				 p);
#ifdef HORRIBLY_VERBOSE
		fprintf(stderr, "%s %u ",
			acmod_set_id2name(omdef->acmod_set, p), s);
#endif

		bb = allphones ? 0 : b;
		odefn->state[s] = tied_state(&tree[bb][s]->node[0],
					     b, l, r, wp,
					     pset);

#ifdef HORRIBLY_VERBOSE
		fprintf(stderr, "\t-> %u\n", odefn->state[s]);

		fprintf(stderr, "\n");
#endif
	    }
	}
    }

    if (model_def_write(omdef, cmd_ln_str("-omoddeffn")) != S3_SUCCESS) {
	return 1;
    }

    return 0;
}
Beispiel #9
0
int
cnt_phn_seg(model_def_t *mdef,
	    lexicon_t *lex,
	    uint32 **out_n_seg,
	    uint32 ***out_n_frame_per)
{
    uint32 seq_no = 0;
    uint16 *seg;
    uint32 n_frame;
    uint32 i, j;
    uint32 n_acmod;
    uint32 *phone;
    uint32 n_phone;
    uint32 *n_seg;
    uint32 **n_frame_per;
    uint32 *start;
    uint32 *len;
    seg_len_t *cur;
    seg_len_t *tmp;
    seg_len_t *phn_hd;
    seg_len_t *phn_tl;

    n_acmod = acmod_set_n_acmod(mdef->acmod_set);

    E_INFO("Counting # occ. for %u models\n", n_acmod);
    
    n_seg = ckd_calloc(n_acmod, sizeof(uint32));
    hd = ckd_calloc(n_acmod, sizeof(seg_len_t *));
    tl = ckd_calloc(n_acmod, sizeof(seg_len_t *));

    for (seq_no = corpus_get_begin(); corpus_next_utt(); seq_no++) {
	if (!(seq_no % 250)) {
	    fprintf(stderr, " cnt[%u]", seq_no);
	    fflush(stderr);
	}
	
	corpus_get_seg(&seg, &n_frame);

	phone = get_next_phnseq(mdef, lex, &n_phone);
	
	ck_seg(mdef->acmod_set, phone, n_phone, seg, n_frame, corpus_utt());
	
	start = ckd_calloc(n_phone, sizeof(uint32));
	len = ckd_calloc(n_phone, sizeof(uint32));

	mk_seg(mdef->acmod_set, seg, n_frame, phone, start, len, n_phone);

	ckd_free(start);
	ckd_free(seg);
	ckd_free(phone);

	for (i = 0; i < n_phone; i++) {
	    /* insert the len for list phone[i] */

	    phn_hd = hd[phone[i]];
	    phn_tl = tl[phone[i]];

	    cur = (seg_len_t *)ckd_calloc(1, sizeof(seg_len_t));

	    cur->len = len[i];

	    if (phn_tl == NULL) {
		hd[phone[i]] = tl[phone[i]] = cur;
	    }
	    else {
		phn_tl->nxt = cur;
		tl[phone[i]] = cur;
	    }
	}
	ckd_free(len);
    }

    n_frame_per = (uint32 **)ckd_calloc(n_acmod, sizeof(uint32 *));

    for (i = 0; i < n_acmod; i++) {
	if (hd[i] == NULL) {
	    n_seg[i] = 0;
	}
	else {
	    for (cur = hd[i], j = 0; cur != NULL; j++, cur = cur->nxt);

	    n_seg[i] = j;

	    n_frame_per[i] = (uint32 *)ckd_calloc(n_seg[i], sizeof(uint32));

	    for (cur = hd[i], j = 0; cur != NULL; j++, cur = cur->nxt)
		n_frame_per[i][j] = cur->len;

	    for (cur = hd[i]; cur != NULL; cur = tmp) {
		tmp = cur->nxt;
		ckd_free(cur);
	    }
	    
	    E_INFO("phn= %s n_seg= %u\n",
		   acmod_set_id2name(mdef->acmod_set, i),
		   n_seg[i]);
	}
    }

    ckd_free(hd);
    ckd_free(tl);

    *out_n_seg = n_seg;
    *out_n_frame_per = n_frame_per;

    return S3_SUCCESS;
}
/*********************************************************************
 *
 * File: viterbi.c
 * 
 * Description: 
 * 
 * Authors: 
 * 	David Huggins-Daines
 *      Eric Thayer
 *********************************************************************/

#include "forward.h"
#include "backward.h"
#include "viterbi.h"
#include "accum.h"

#include <sphinxbase/ckd_alloc.h>
#include <s3/profile.h>
#include <s3/remap.h>
#include <s3/corpus.h>
#include <s3/err.h>
#include <sphinxbase/cmd_ln.h>
#include <s3/s3phseg_io.h>
#include <s3/model_def.h>
#include <s2/byteorder.h>

#include <math.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

#define INVLOGS3 100000.5 /* (1.0/log(1.0001)) */
int32
write_phseg(const char *filename,
	    model_inventory_t *modinv,
	    state_t *state_seq,
	    uint32 **active_astate,
	    uint32 *n_active_astate,
	    uint32 n_state,
	    uint32 n_obs,
	    float64 **active_alpha,
	    float64 *scale,
	    uint32 **bp)
{
    FILE *fh;
    int32 t;
    uint32 q;
    s3phseg_t *phseg, *next;
    model_def_t *mdef;
    model_def_entry_t *defn;
    uint32 n_defn;
    float64 ascr;

    /* Find the non-emitting ending state */
    for (q = 0; q < n_active_astate[n_obs-1]; ++q) {
	if (active_astate[n_obs-1][q] == n_state-1)
	    break;
    }
    if (q == n_active_astate[n_obs-1]) {
	E_ERROR("Failed to align audio to trancript: final state of the search is not reached\n");
	return S3_ERROR;
    }

    if ((fh = fopen(filename, "w")) == NULL) {
	return S3_ERROR;
    }

    /* Backtrace and build a phone segmentation */
    mdef = modinv->mdef;
    defn = mdef->defn;
    n_defn = mdef->n_defn;
    phseg = NULL;
    ascr = 0;
    for (t = n_obs-1; t >= 0; --t) {
	uint32 j;

	j = active_astate[t][q];

	/* Follow any non-emitting states at time t first. */
	if (state_seq[j].mixw == TYING_NON_EMITTING) {
	    s3phseg_t *prev;
	    uint32 phn;
	    int k, l;

	    while (state_seq[j].mixw == TYING_NON_EMITTING) {
		j = active_astate[t][bp[t][q]];
		q = bp[t][q];
	    }
	    

	    /* Do a rather nasty mdef scan to find the triphone in question. */
	    for (phn = 0; phn < n_defn; phn++) {

    	        for (k = defn[phn].n_state - 2, l = j; k >= 0 && l >= 0; k--, l--) {
	    	    if (state_seq[l].mixw != defn[phn].state[k])
	    		break;
	        }

	        if (k < 0)
	    	    break;
	    }
	    
	    if (phn == n_defn) {
		E_ERROR("Failed to find triphone for senone %u\n", state_seq[j].mixw);
	    }
	    
	    /* Record ascr and sf for the next phone */
	    if (phseg) {
		phseg->score = (int32)(ascr * INVLOGS3);
		phseg->sf = t + 1;
		ascr = 0;
	    }
	    prev = ckd_calloc(1, sizeof(*prev));
	    prev->next = phseg;
	    prev->phone = phn;
	    prev->ef = t;
	    phseg = prev;
	}

	/* Multiply alphas to get "acoustic score" for this phone */
	ascr += (log(active_alpha[t][q]) + log(scale[t]));

	/* Backtrace. */
	if (t > 0) {
	    q = bp[t][q];
	}
    }

    fprintf(fh, "\t%5s %5s %9s %s\n", "SFrm", "EFrm", "SegAScr", "Phone");
    phseg->sf = 0; /* vacuous */
    while (phseg) {
	next = phseg->next;
        fprintf(fh, "\t%5d %5d %9d %s\n",
                phseg->sf, phseg->ef, phseg->score,
		acmod_set_id2name(mdef->acmod_set, phseg->phone));
	ckd_free(phseg);
	phseg = next;
    }

    fclose(fh);
    return S3_SUCCESS;
}
Beispiel #11
0
int
main(int argc, char *argv[])
{
    model_def_t *mdef;
    model_def_entry_t *defn;
    uint32 n_defn;
    uint32 *cluster_offset;
    uint32 max_int;
    uint32 *state_of;
    uint32 max_state;
    uint32 sstate;
    int32 i;
    uint32 j;
    uint32 n_base_phone;
    acmod_id_t base;
    acmod_id_t p;
    float32 ***out;
    uint32 **smap;
    char comment[4192];
    time_t t;

    parse_cmd_ln(argc, argv);
    
    printf("%s(%d): Reading model definition file %s\n",
	   __FILE__, __LINE__, (const char *)cmd_ln_access("-moddeffn"));
    
    if (model_def_read(&mdef, cmd_ln_access("-moddeffn")) != S3_SUCCESS) {
	exit(1);
    }

    defn = mdef->defn;
    n_defn = mdef->n_defn;

    printf("%s(%d): %d models defined\n",
	   __FILE__, __LINE__, n_defn);

    smap = ckd_calloc(n_defn, sizeof(uint32 *));

    n_base_phone = acmod_set_n_ci(mdef->acmod_set);

    cluster_offset = ckd_calloc(n_base_phone+1, sizeof(uint32));

    max_int = 0;
    --max_int;	/* underflow offset values to max value */
    for (i = 0; i < n_base_phone; i++) {
	cluster_offset[i] = max_int;	
    }

    for (i = 0, max_state = 0; i < n_defn; i++) {
	for (j = 0; j < defn[i].n_state; j++) {
	    sstate = defn[i].state[j];
	    
	    if ((sstate != TYING_NON_EMITTING) &&
		(defn[i].state[j] > max_state)) max_state = defn[i].state[j];
	}
    }

    /* record the total # of senones */
    cluster_offset[n_base_phone] = max_state+1;

    state_of = ckd_calloc(max_state+1, sizeof(uint32));

    for (i = 0; i <= max_state; i++)
	state_of[i] = NO_STATE;
    
    for (i = 0; i < n_defn; i++) {
	p = defn[i].p;
	base = acmod_set_base_phone(mdef->acmod_set, defn[i].p);

	smap[i] = defn[i].state;
	
	for (j = 0; j < defn[i].n_state; j++) {
	    sstate = defn[i].state[j];

	    if (sstate != TYING_NON_EMITTING) {
		if (state_of[sstate] == NO_STATE)
		    state_of[sstate] = j;
		else if (state_of[sstate] != j) {
		    printf("%s %d appears as %d%s and %d%s model states\n",
			   acmod_set_id2name(mdef->acmod_set, acmod_set_base_phone(mdef->acmod_set, defn[i].p)),
			   sstate,
			   state_of[sstate],
			   ord_suff(state_of[sstate]),
			   j,
			   ord_suff(j));
		}

		if ((p != base) && (cluster_offset[base] > sstate)) {
		    cluster_offset[base] = sstate;
		}
	    }
	}
    }
    
    /* any untouched CLUSTER_OFFSET's implies a base phone
       without any CD states.  So offset is same as next
       one */
    for (i = (n_base_phone - 1); i >= 0 ; i--) {
	if (cluster_offset[i] == max_int)
	    cluster_offset[i] = cluster_offset[i+1];
    }

    fflush(stdout);
    for (i = 0; i < n_base_phone; i++) {
	if (cluster_offset[i] != max_int) {
	    fprintf(stderr, "%s(%d): %s offset %d\n",
		    __FILE__, __LINE__,
		    acmod_set_id2name(mdef->acmod_set, i), cluster_offset[i]);
	}
	else {
	    fprintf(stderr, "%s(%d): %s <no CD states>\n",
		    __FILE__, __LINE__,
		    acmod_set_id2name(mdef->acmod_set, i));
	}
    }
    fflush(stderr);

    printf("%s(%d): Reading senone weights in %s with floor %e\n",
	   __FILE__, __LINE__, (const char *)cmd_ln_access("-hmmdir"),
	   *(float32 *)cmd_ln_access("-floor"));
    
    out = s2_read_seno_3(mdef->acmod_set, cluster_offset,
			 cmd_ln_access("-hmmdir"),
			 (*(int32 *)cmd_ln_access("-ci2cd") ? NULL : smap),
			 *(float32 *)cmd_ln_access("-floor"),
			 state_of);

    t = time(NULL);
    sprintf(comment,
	    "Generated on %s\n\tmoddeffn: %s\n\tfloor: %e\n\thmmdir: %s\n\n\n\n\n\n\n\n\n",
	    ctime(&t),
	    (const char *)cmd_ln_access("-moddeffn"),
	    *(float32 *)cmd_ln_access("-floor"),
	    (const char *)cmd_ln_access("-hmmdir"));

    fflush(stdout);
    fprintf(stderr, "%s(%d): writing %s\n",
	    __FILE__, __LINE__,
	    (const char *)cmd_ln_access("-mixwfn"));
    fflush(stderr);
    
    if (s3mixw_write(cmd_ln_access("-mixwfn"),
		     out,
		     cluster_offset[n_base_phone],	/* total # states */
		     S2_N_FEATURE,
		     S2_N_CODEWORD) != S3_SUCCESS) {
	fflush(stdout);
	fprintf(stderr, "%s(%d): couldn't write mixture weight file\n",
		__FILE__, __LINE__);
	perror(cmd_ln_access("-mixwfn"));
	fflush(stderr);
    }
		     
    ckd_free(state_of);
    ckd_free(cluster_offset);

    return 0;
}
Beispiel #12
0
/* Converts the state map, smap, into a global
   one-to-one mapping from model states onto
   consecutive integers from 0 to some max */
int
s2_convert_smap_to_global(acmod_set_t *acmod_set,
                          uint32 **smap,
                          uint32 **out_state_of,
                          uint32 *cluster_size)
{
    uint32 i;
    uint32 t;
    uint32 offset;
    uint32 n_ci = acmod_set_n_ci(acmod_set);
    uint32 n = acmod_set_n_multi(acmod_set) + n_ci;
    acmod_id_t b;
    acmod_id_t id;
    uint32 state;
    uint32 *state_of;
    uint32 ci_seno;

    offset = n_ci * (S2_N_STATE-1);

    E_INFO("|CI states| == %d\n", offset);

    /* convert the cluster_size matrix into an offset table */
    for (i = 0; i < n_ci; i++) {
        t = cluster_size[i];
        cluster_size[i] = offset;
        offset += t;

        E_INFO("|%s| == %d (%d)\n",
               acmod_set_id2name(acmod_set, i),
               t, offset);
    }

    cluster_size[i] = offset;	/* total # of states */

    state_of = ckd_calloc(offset, sizeof(uint32));

    /* map the ci phones to unshared distribution */
    for (id = 0; id < n_ci; id++) {
        for (state = 0; state < S2_N_STATE-1; state++) {
            ci_seno = id * (S2_N_STATE-1) + state;
            smap[id][state] = ci_seno;
            state_of[ci_seno] = state;
        }
    }

    /* use the ci phone offsets to convert ci phone relative
       mappings to a global one-to-one mapping onto
       consecutive integers from 0 to some max */
    for (; id < n; id++) {
        for (state = 0; state < S2_N_STATE-1; state++) {
            if (smap[id][state] == TYING_NO_ID) {
                uint32 base_id;

                base_id = acmod_set_base_phone(acmod_set, id);

                E_WARN("%s<%d> is unmapped, approximating with CI state <%d>.\n",
                       acmod_set_id2name(acmod_set, id),
                       state, state);

                smap[id][state] = smap[base_id][state];

                /* no state_of[] assignment need bee done since it was done
                   above */
            }
            else {
                b = acmod_set_base_phone(acmod_set, id);

                smap[id][state] += cluster_size[b];
                state_of[ smap[id][state] ] = state;
            }
        }
    }

    *out_state_of = state_of;

    return S3_SUCCESS;
}
Beispiel #13
0
static int
init_mixw()
{
    model_def_t *src_mdef;
    float32 ***src_mixw;
    vector_t ***src_mean;
    vector_t ***src_var = NULL;
    vector_t ****src_fullvar = NULL;
    float32 ***src_tmat;

    model_def_t *dest_mdef;
    float32 ***dest_mixw;
    vector_t ***dest_mean;
    vector_t ***dest_var = NULL;
    vector_t ****dest_fullvar = NULL;
    float32 ***dest_tmat;

    uint32 n_mixw_src;
    uint32 n_mixw_dest;
    uint32 n_feat;
    uint32 tmp_n_feat;
    uint32 n_gau;
    uint32 tmp_n_gau;
    uint32 n_cb_src;
    uint32 n_cb_dest;
    uint32 n_state_pm;
    uint32 n_tmat_src;
    uint32 n_tmat_dest;
    uint32 *veclen;
    uint32 *tmp_veclen;

    uint32 m;
    uint32 dest_m;
    uint32 dest_m_base;
    uint32 src_m;
    acmod_id_t src_m_base;
    const char *dest_m_name;
    const char *dest_m_base_name;

    uint32 i;
    uint32 n_ts;
    uint32 n_cb;

    const char *ts2cbfn;

    E_INFO("Reading src %s\n", cmd_ln_str("-src_moddeffn"));

    /* read in the source model definition file */
    if (model_def_read(&src_mdef,
                       cmd_ln_str("-src_moddeffn")) != S3_SUCCESS) {
        return S3_ERROR;
    }


    ts2cbfn = cmd_ln_str("-src_ts2cbfn");
    if (strcmp(SEMI_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating semi-continous ts2cb mapping\n");
        src_mdef->cb = semi_ts2cb(src_mdef->n_tied_state);
        n_ts = src_mdef->n_tied_state;
        n_cb = 1;
    }
    else if (strcmp(CONT_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating continous ts2cb mapping\n");
        src_mdef->cb = cont_ts2cb(src_mdef->n_tied_state);
        n_ts = src_mdef->n_tied_state;
        n_cb = src_mdef->n_tied_state;
    }
    else if (strcmp(PTM_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating phonetically tied ts2cb mapping\n");
        src_mdef->cb = ptm_ts2cb(src_mdef);
        n_ts = src_mdef->n_tied_state;
        n_cb = src_mdef->acmod_set->n_ci;
    }
    else {
        E_INFO("Reading src %s\n", cmd_ln_str("-src_ts2cbfn"));
        if (s3ts2cb_read(ts2cbfn,
                         &src_mdef->cb,
                         &n_ts,
                         &n_cb) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }

    E_INFO("Reading src %s\n", cmd_ln_str("-src_mixwfn"));

    /* read in the source mixing weight parameter file */
    if (s3mixw_read(cmd_ln_str("-src_mixwfn"),
                    &src_mixw, &n_mixw_src, &n_feat, &n_gau) != S3_SUCCESS) {

        return S3_ERROR;
    }

    E_INFO("Reading src %s\n",
           cmd_ln_str("-src_tmatfn"));

    if (s3tmat_read(cmd_ln_str("-src_tmatfn"),
                    &src_tmat,
                    &n_tmat_src,
                    &n_state_pm) != S3_SUCCESS) {
        return S3_ERROR;
    }

    E_INFO("Reading src %s\n", cmd_ln_str("-src_meanfn"));

    if (s3gau_read(cmd_ln_str("-src_meanfn"),
                   &src_mean,
                   &n_cb_src,
                   &tmp_n_feat,
                   &tmp_n_gau,
                   &veclen) != S3_SUCCESS) {
        return S3_ERROR;
    }

    if (tmp_n_feat != n_feat) {
        E_FATAL("src mean n_feat (== %u) != prior value (== %u)\n",
                tmp_n_feat, n_feat);
    }
    if (tmp_n_gau != n_gau) {
        E_FATAL("src mean n_gau (== %u) != prior value (== %u)\n",
                tmp_n_gau, n_gau);
    }
    if (n_cb_src != n_cb) {
        E_FATAL("src mean n_cb (== %u) is inconsistent with ts2cb mapping %u. Most probably phoneset has duplicated phones\n",
                n_cb_src, n_cb);
    }

    E_INFO("Reading src %s\n", cmd_ln_str("-src_varfn"));
    if (cmd_ln_int32("-fullvar")) {
        if (s3gau_read_full(cmd_ln_str("-src_varfn"),
                            &src_fullvar,
                            &n_cb_src,
                            &tmp_n_feat,
                            &tmp_n_gau,
                            &tmp_veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }
    else {
        if (s3gau_read(cmd_ln_str("-src_varfn"),
                       &src_var,
                       &n_cb_src,
                       &tmp_n_feat,
                       &tmp_n_gau,
                       &tmp_veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }

    if (tmp_n_feat != n_feat) {
        E_FATAL("src var n_feat (== %u) != prior value (== %u)\n",
                tmp_n_feat, n_feat);
    }
    if (tmp_n_gau != n_gau) {
        E_FATAL("src var n_gau (== %u) != prior value (== %u)\n",
                tmp_n_gau, n_gau);
    }
    if (n_cb_src != n_cb) {
        E_FATAL("src var n_cb (== %u) inconsistent w/ ts2cb mapping %u\n",
                n_cb_src, n_cb);
    }

    if (n_mixw_src < src_mdef->n_tied_state) {
        E_FATAL("Too few source mixing weights, %u, for the # of tied states, %u\n",
                n_mixw_src, src_mdef->n_tied_state);
    }

    for (i = 0; i < n_feat; i++) {
        if (veclen[i] != tmp_veclen[i]) {
            E_FATAL("src var veclen[%u] (== %u) != prior value (== %u)\n",
                    i, tmp_veclen[i], veclen[i]);
        }
    }
    ckd_free(tmp_veclen);

    E_INFO("Reading dest %s\n",
           cmd_ln_str("-dest_moddeffn"));

    /* read in the destination model definition file */
    if (model_def_read(&dest_mdef,
                       cmd_ln_str("-dest_moddeffn")) < S3_SUCCESS) {
        return S3_ERROR;
    }

    ts2cbfn = cmd_ln_str("-dest_ts2cbfn");
    if (strcmp(SEMI_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating semi-continous ts2cb mapping\n");
        dest_mdef->cb = semi_ts2cb(dest_mdef->n_tied_state);
        n_ts = dest_mdef->n_tied_state;
        n_cb = 1;
    }
    else if (strcmp(CONT_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating continous ts2cb mapping\n");
        dest_mdef->cb = cont_ts2cb(dest_mdef->n_tied_state);
        n_ts = dest_mdef->n_tied_state;
        n_cb = dest_mdef->n_tied_state;
    }
    else if (strcmp(PTM_LABEL, ts2cbfn) == 0) {
        E_INFO("Generating phonetically tied ts2cb mapping\n");
        dest_mdef->cb = ptm_ts2cb(dest_mdef);
        n_ts = dest_mdef->n_tied_state;
        n_cb = dest_mdef->acmod_set->n_ci;
    }
    else {
        E_INFO("Reading dest %s\n",
               cmd_ln_str("-dest_ts2cbfn"));


        if (s3ts2cb_read(ts2cbfn,
                         &dest_mdef->cb,
                         &n_ts,
                         &n_cb) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }

    E_INFO("Calculating initial model parameters\n");

    n_tmat_dest = dest_mdef->n_tied_tmat;
    tmat_dest_list = init_was_added(n_tmat_dest);

    E_INFO("Alloc %ux%ux%u dest tmat\n",
           n_tmat_dest,
           n_state_pm-1,
           n_state_pm);

    dest_tmat = (float32 ***)ckd_calloc_3d(n_tmat_dest,
                                           n_state_pm-1,
                                           n_state_pm,
                                           sizeof(float32));

    n_mixw_dest = dest_mdef->n_tied_state;
    mixw_dest_list = init_was_added(n_mixw_dest);

    E_INFO("Alloc %ux%ux%u dest mixw\n",
           n_mixw_dest, n_feat, n_gau);
    dest_mixw = (float32 ***)ckd_calloc_3d(n_mixw_dest, n_feat, n_gau, sizeof(float32));

    for (i = 0, n_cb_dest = 0; i < n_mixw_dest; i++) {
        if (dest_mdef->cb[i] > n_cb_dest) {
            n_cb_dest = dest_mdef->cb[i];
        }
    }
    ++n_cb_dest;

    cb_dest_list = init_was_added(n_cb_dest);

    E_INFO("Alloc %ux%ux%u dest mean and var\n",
           n_cb_dest, n_feat, n_gau);
    dest_mean = gauden_alloc_param(n_cb_dest, n_feat, n_gau, veclen);
    if (src_var)
        dest_var = gauden_alloc_param(n_cb_dest, n_feat, n_gau, veclen);
    else if (src_fullvar)
        dest_fullvar = gauden_alloc_param_full(n_cb_dest, n_feat, n_gau, veclen);

    for (dest_m = 0; dest_m < dest_mdef->n_defn; dest_m++) {
        dest_m_name = acmod_set_id2name(dest_mdef->acmod_set, dest_m);
        src_m = acmod_set_name2id(src_mdef->acmod_set, dest_m_name);
        if (src_m == NO_ACMOD) {
            /* No corresponding phone model in the source set */

            /* See if there is a source base phone corresponding to this destination model
               base phone */
            dest_m_base = acmod_set_base_phone(dest_mdef->acmod_set, dest_m);
            dest_m_base_name = acmod_set_id2name(dest_mdef->acmod_set, dest_m_base);

            src_m_base = acmod_set_name2id(src_mdef->acmod_set, dest_m_base_name);
            if (src_m_base == NO_ACMOD) {
                /* No corresponding model or base model found.  Use uniform distribution */

                E_INFO("No source base phone %s found.  Initializing %s using uniform distribution\n",
                       dest_m_base_name, dest_m_name);

                if (src_tmat) {
                    E_INFO("Uniform initialization of tmat not supported\n");
                }
                init_uniform(dest_mixw, &dest_mdef->defn[dest_m], n_feat, n_gau);
            }
            else {
                /* No corresponding model, but a base model was found.  Use base distribution. */
                init_model(dest_mixw, dest_mean, dest_var, dest_fullvar, dest_tmat,
                           &dest_mdef->defn[dest_m], dest_mdef->cb, dest_mdef->acmod_set,
                           src_mixw, src_mean, src_var, src_fullvar, src_tmat,
                           &src_mdef->defn[src_m_base], src_mdef->cb, src_mdef->acmod_set,
                           n_feat, n_gau, n_state_pm, veclen);
            }
        }
        else {
            /* Found a corresponding model in the source set, so use source distributions to init
               the destination */
            init_model(dest_mixw, dest_mean, dest_var, dest_fullvar, dest_tmat,
                       &dest_mdef->defn[dest_m], dest_mdef->cb, dest_mdef->acmod_set,
                       src_mixw, src_mean, src_var, src_fullvar, src_tmat,
                       &src_mdef->defn[src_m], src_mdef->cb, src_mdef->acmod_set,
                       n_feat, n_gau, n_state_pm, veclen);
        }
    }

    for (m = 0; m < n_mixw_dest; m++) {
        if (mixw_dest_list[m] == NULL) {
            E_WARN("Destination state %u has not been initialized!\n", m);
        }
    }

    for (m = 0; m < n_cb_dest; m++) {
        if (cb_dest_list[m] == NULL) {
            E_WARN("Destination cb %u has not been initialized!\n", m);
        }
        else if (cb_dest_list[m]->next != NULL) {
            E_WARN("dest cb %u has > 1 corresponding source cb\n", m);
        }
    }

    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_tmatfn"));

    if (s3tmat_write(cmd_ln_str("-dest_tmatfn"),
                     dest_tmat,
                     n_tmat_dest,
                     n_state_pm) != S3_SUCCESS) {
        return S3_ERROR;
    }


    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_mixwfn"));

    if (s3mixw_write(cmd_ln_str("-dest_mixwfn"),
                     dest_mixw,
                     dest_mdef->n_tied_state, n_feat, n_gau) < S3_SUCCESS) {
        return S3_ERROR;
    }

    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_meanfn"));

    if (s3gau_write(cmd_ln_str("-dest_meanfn"),
                    (const vector_t ***)dest_mean,
                    n_cb_dest,
                    n_feat,
                    n_gau,
                    veclen) != S3_SUCCESS) {
        return S3_ERROR;
    }

    E_INFO("Writing dest %s\n",
           cmd_ln_str("-dest_varfn"));
    if (cmd_ln_int32("-fullvar")) {
        if (s3gau_write_full(cmd_ln_str("-dest_varfn"),
                             (const vector_t ****)dest_fullvar,
                             n_cb_dest,
                             n_feat,
                             n_gau,
                             veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }
    else {
        if (s3gau_write(cmd_ln_str("-dest_varfn"),
                        (const vector_t ***)dest_var,
                        n_cb_dest,
                        n_feat,
                        n_gau,
                        veclen) != S3_SUCCESS) {
            return S3_ERROR;
        }
    }
    ckd_free(veclen);
    return S3_SUCCESS;
}
Beispiel #14
0
static int
init_model(float32 ***dest_mixw,
           vector_t ***dest_mean,
           vector_t ***dest_var,
           vector_t ****dest_fullvar,
           float32 ***dest_tmat,
           model_def_entry_t *dest,
           uint32 *dest_cb_map,
           acmod_set_t *dest_acmod_set,

           float32 ***src_mixw,
           vector_t ***src_mean,
           vector_t ***src_var,
           vector_t ****src_fullvar,
           float32 ***src_tmat,
           model_def_entry_t *src,
           uint32 *src_cb_map,
           acmod_set_t *src_acmod_set,

           uint32 n_feat,
           uint32 n_gau,
           uint32 n_state_pm,
           const uint32 *veclen)
{
    unsigned int s, i, j, k, l, ll;
    unsigned int s_m, s_mg;
    unsigned int d_m, d_mg;
    uint32 s_tmat, d_tmat;

    printf("%10s <- %-10s: ",
           acmod_set_id2name(dest_acmod_set, dest->p),
           acmod_set_id2name(src_acmod_set, src->p));

    fflush(stdout);

    s_tmat = src->tmat;
    d_tmat = dest->tmat;

    if (!was_added(&tmat_dest_list[d_tmat], s_tmat)) {
        printf("[tm %5u += %5u]\n", d_tmat, s_tmat);
        for (i = 0; i < n_state_pm-1; i++) {
            for (j = 0; j < n_state_pm; j++) {
                dest_tmat[d_tmat][i][j] += src_tmat[s_tmat][i][j];
            }
        }
    }

    for (s = 0; s < src->n_state; s++) {
        s_m = src->state[s];
        d_m = dest->state[s];

        if ((s_m == TYING_NON_EMITTING) &&
                (d_m == TYING_NON_EMITTING))
            continue;

        if ((s_m != TYING_NON_EMITTING) &&
                (d_m != TYING_NON_EMITTING)) {

            if (!was_added(&mixw_dest_list[d_m], s_m)) {
                printf("[mx %5u(%1u) += %5u] ", d_m, s, s_m);

                for (j = 0; j < n_feat; j++) {
                    for (k = 0; k < n_gau; k++) {
                        dest_mixw[d_m][j][k] += src_mixw[s_m][j][k];
                    }
                }
            }

            s_mg = src_cb_map[s_m];
            d_mg = dest_cb_map[d_m];
            if (!was_added(&cb_dest_list[d_mg], s_mg)) {
                printf("[mg %5u(%1u) <- %5u] ", d_mg, s, s_mg);

                for (j = 0; j < n_feat; j++) {
                    for (k = 0; k < n_gau; k++) {
                        for (l = 0; l < veclen[j]; l++) {
                            dest_mean[d_mg][j][k][l] = src_mean[s_mg][j][k][l];
                            if (dest_var)
                                dest_var[d_mg][j][k][l] = src_var[s_mg][j][k][l];
                            else if (dest_fullvar) {
                                for (ll = 0; ll < veclen[j]; ++ll) {
                                    dest_fullvar[d_mg][j][k][l][ll]
                                        = src_fullvar[s_mg][j][k][l][ll];
                                }
                            }
                        }
                    }
                }
            }
        }
        else {
            E_ERROR("Source is %semitting and destination is %semitting\n",
                    (s_m != TYING_NON_EMITTING ? "" : "non-"),
                    (d_m != TYING_NON_EMITTING ? "" : "non-"));
        }
    }

    printf("\n");

    return S3_SUCCESS;
}