📄 bin_mdef.c
字号:
for (i = 0; i < m->n_cd_tree; ++i) { SWAP_INT16(&m->cd_tree[i].ctx); SWAP_INT16(&m->cd_tree[i].n_down); SWAP_INT32(&m->cd_tree[i].c.down); } } m->phone = (mdef_entry_t *) (m->cd_tree + m->n_cd_tree); if (swap) { for (i = 0; i < m->n_phone; ++i) { SWAP_INT32(&m->phone[i].ssid); SWAP_INT32(&m->phone[i].tmat); } } sseq_size = (int32 *) (m->phone + m->n_phone); if (swap) SWAP_INT32(sseq_size); m->sseq = ckd_calloc(m->n_sseq, sizeof(*m->sseq)); m->sseq[0] = (s3senid_t *) (sseq_size + 1); if (swap) { for (i = 0; i < *sseq_size; ++i) SWAP_INT16(m->sseq[0] + i); } if (m->n_emit_state) { for (i = 1; i < m->n_sseq; ++i) m->sseq[i] = m->sseq[0] + i * m->n_emit_state; } else { m->sseq_len = (int8 *) (m->sseq[0] + *sseq_size); for (i = 1; i < m->n_sseq; ++i) m->sseq[i] = m->sseq[i - 1] + m->sseq_len[i - 1]; } /* Now build the CD-to-CI mappings using the senone sequences. * This is the only really accurate way to do it, though it is * still inaccurate in the case of heterogeneous topologies or * cross-state tying. */ m->cd2cisen = (s3senid_t *) ckd_malloc(m->n_sen * sizeof(s3senid_t)); m->sen2cimap = (s3cipid_t *) ckd_malloc(m->n_sen * sizeof(s3cipid_t)); /* Default mappings (identity, none) */ for (i = 0; i < m->n_ci_sen; ++i) m->cd2cisen[i] = i; for (; i < m->n_sen; ++i) m->cd2cisen[i] = BAD_S3SENID; for (i = 0; i < m->n_sen; ++i) m->sen2cimap[i] = BAD_S3CIPID; for (i = 0; i < m->n_phone; ++i) { int32 j, ssid = m->phone[i].ssid; for (j = 0; j < bin_mdef_n_emit_state_phone(m, i); ++j) { s3senid_t s = bin_mdef_sseq2sen(m, ssid, j); s3cipid_t ci = bin_mdef_pid2ci(m, i); /* Take the first one and warn if we have cross-state tying. */ if (m->sen2cimap[s] == BAD_S3CIPID) m->sen2cimap[s] = ci; if (m->sen2cimap[s] != ci) E_WARN ("Senone %d is shared between multiple base phones\n", s); if (j > bin_mdef_n_emit_state_phone(m, ci)) E_WARN("CD phone %d has fewer states than CI phone %d\n", i, ci); else m->cd2cisen[s] = bin_mdef_sseq2sen(m, m->phone[ci].ssid, j); } } /* Set the silence phone. */ m->sil = bin_mdef_ciphone_id(m, S3_SILENCE_CIPHONE); E_INFO ("%d CI-phone, %d CD-phone, %d emitstate/phone, %d CI-sen, %d Sen, %d Sen-Seq\n", m->n_ciphone, m->n_phone - m->n_ciphone, m->n_emit_state, m->n_ci_sen, m->n_sen, m->n_sseq); m->alloc_mode = BIN_MDEF_IN_MEMORY; return m;}intbin_mdef_write(bin_mdef_t * m, const char *filename){ FILE *fh; int32 val, i; if ((fh = fopen(filename, "wb")) == NULL) return -1; /* Byteorder marker. */ val = BIN_MDEF_NATIVE_ENDIAN; fwrite(&val, 1, 4, fh); /* Version. */ val = BIN_MDEF_FORMAT_VERSION; fwrite(&val, 1, sizeof(val), fh); /* Round the format descriptor size up to a 4-byte boundary. */ val = ((sizeof(format_desc) + 3) & ~3); fwrite(&val, 1, sizeof(val), fh); fwrite(format_desc, 1, sizeof(format_desc), fh); /* Pad it with zeros. */ i = 0; fwrite(&i, 1, val - sizeof(format_desc), fh); /* Binary header things. */ fwrite(&m->n_ciphone, 4, 1, fh); fwrite(&m->n_phone, 4, 1, fh); fwrite(&m->n_emit_state, 4, 1, fh); fwrite(&m->n_ci_sen, 4, 1, fh); fwrite(&m->n_sen, 4, 1, fh); fwrite(&m->n_tmat, 4, 1, fh); fwrite(&m->n_sseq, 4, 1, fh); fwrite(&m->n_ctx, 4, 1, fh); fwrite(&m->n_cd_tree, 4, 1, fh); /* Write this as a 32-bit value to preserve alignment for the * non-mmap case (we want things aligned both from the * beginning of the file and the beginning of the phone * strings). */ val = m->sil; fwrite(&val, 4, 1, fh); /* Phone strings. */ for (i = 0; i < m->n_ciphone; ++i) fwrite(m->ciname[i], 1, strlen(m->ciname[i]) + 1, fh); /* Pad with zeros. */ val = (ftell(fh) + 3) & ~3; i = 0; fwrite(&i, 1, val - ftell(fh), fh); /* Write CD-tree */ fwrite(m->cd_tree, sizeof(*m->cd_tree), m->n_cd_tree, fh); /* Write phones */ fwrite(m->phone, sizeof(*m->phone), m->n_phone, fh); if (m->n_emit_state) { /* Write size of sseq */ val = m->n_sseq * m->n_emit_state; fwrite(&val, 4, 1, fh); /* Write sseq */ fwrite(m->sseq[0], sizeof(s3senid_t), m->n_sseq * m->n_emit_state, fh); } else { int32 n; /* Calcluate size of sseq */ n = 0; for (i = 0; i < m->n_sseq; ++i) n += m->sseq_len[i]; /* Write size of sseq */ fwrite(&n, 4, 1, fh); /* Write sseq */ fwrite(m->sseq[0], sizeof(s3senid_t), n, fh); /* Write sseq_len */ fwrite(m->sseq_len, 1, m->n_sseq, fh); } fclose(fh); return 0;}intbin_mdef_write_text(bin_mdef_t * m, const char *filename){ FILE *fh; int p, i, n_total_state; if (strcmp(filename, "-") == 0) fh = stdout; else { if ((fh = fopen(filename, "w")) == NULL) return -1; } fprintf(fh, "0.3\n"); fprintf(fh, "%d n_base\n", m->n_ciphone); fprintf(fh, "%d n_tri\n", m->n_phone - m->n_ciphone); if (m->n_emit_state) n_total_state = m->n_phone * (m->n_emit_state + 1); else { n_total_state = 0; for (i = 0; i < m->n_phone; ++i) n_total_state += m->sseq_len[m->phone[i].ssid] + 1; } fprintf(fh, "%d n_state_map\n", n_total_state); fprintf(fh, "%d n_tied_state\n", m->n_sen); fprintf(fh, "%d n_tied_ci_state\n", m->n_ci_sen); fprintf(fh, "%d n_tied_tmat\n", m->n_tmat); fprintf(fh, "#\n# Columns definitions\n"); fprintf(fh, "#%4s %3s %3s %1s %6s %4s %s\n", "base", "lft", "rt", "p", "attrib", "tmat", " ... state id's ..."); for (p = 0; p < m->n_ciphone; p++) { int n_state; fprintf(fh, "%5s %3s %3s %1s", m->ciname[p], "-", "-", "-"); if (bin_mdef_is_fillerphone(m, p)) fprintf(fh, " %6s", "filler"); else fprintf(fh, " %6s", "n/a"); fprintf(fh, " %4d", m->phone[p].tmat); if (m->n_emit_state) n_state = m->n_emit_state; else n_state = m->sseq_len[m->phone[p].ssid]; for (i = 0; i < n_state; i++) { fprintf(fh, " %6u", m->sseq[m->phone[p].ssid][i]); } fprintf(fh, " N\n"); } for (; p < m->n_phone; p++) { int n_state; fprintf(fh, "%5s %3s %3s %c", m->ciname[m->phone[p].info.cd.ctx[0]], m->ciname[m->phone[p].info.cd.ctx[1]], m->ciname[m->phone[p].info.cd.ctx[2]], (WPOS_NAME)[m->phone[p].info.cd.wpos]); if (bin_mdef_is_fillerphone(m, p)) fprintf(fh, " %6s", "filler"); else fprintf(fh, " %6s", "n/a"); fprintf(fh, " %4d", m->phone[p].tmat); if (m->n_emit_state) n_state = m->n_emit_state; else n_state = m->sseq_len[m->phone[p].ssid]; for (i = 0; i < n_state; i++) { fprintf(fh, " %6u", m->sseq[m->phone[p].ssid][i]); } fprintf(fh, " N\n"); } if (strcmp(filename, "-") != 0) fclose(fh); return 0;}s3cipid_tbin_mdef_ciphone_id(bin_mdef_t * m, const char *ciphone){ int low, mid, high; /* Exact binary search on m->ciphone */ low = 0; high = m->n_ciphone; while (low < high) { int c; mid = (low + high) / 2; c = strcmp(ciphone, m->ciname[mid]); if (c == 0) return mid; else if (c > 0) low = mid + 1; else if (c < 0) high = mid; } return BAD_S3CIPID;}const char *bin_mdef_ciphone_str(bin_mdef_t * m, int32 ci){ assert(m != NULL); assert(ci < m->n_ciphone); return m->ciname[ci];}s3pid_tbin_mdef_phone_id(bin_mdef_t * m, int32 ci, int32 lc, int32 rc, int32 wpos){ cd_tree_t *cd_tree; int level, max; s3cipid_t ctx[4]; assert(m); assert((ci >= 0) && (ci < m->n_ciphone)); assert((lc >= 0) && (lc < m->n_ciphone)); assert((rc >= 0) && (rc < m->n_ciphone)); assert((wpos >= 0) && (wpos < N_WORD_POSN)); /* Create a context list, mapping fillers to silence. */ ctx[0] = wpos; ctx[1] = ci; ctx[2] = (IS_S3CIPID(m->sil) && m->phone[lc].info.ci.filler) ? m->sil : lc; ctx[3] = (IS_S3CIPID(m->sil) && m->phone[rc].info.ci.filler) ? m->sil : rc; /* Walk down the cd_tree. */ cd_tree = m->cd_tree; level = 0; /* What level we are on. */ max = N_WORD_POSN; /* Number of nodes on this level. */ while (level < 4) { int i;#if 0 E_INFO("Looking for context %d=%s in %d at %d\n", ctx[level], m->ciname[ctx[level]], max, cd_tree - m->cd_tree);#endif for (i = 0; i < max; ++i) {#if 0 E_INFO("Look at context %d=%s at %d\n", cd_tree[i].ctx, m->ciname[cd_tree[i].ctx], cd_tree + i - m->cd_tree);#endif if (cd_tree[i].ctx == ctx[level]) break; } if (i == max) return BAD_S3PID;#if 0 E_INFO("Found context %d=%s at %d, n_down=%d, down=%d\n", ctx[level], m->ciname[ctx[level]], cd_tree + i - m->cd_tree, cd_tree[i].n_down, cd_tree[i].c.down);#endif /* Leaf node, stop here. */ if (cd_tree[i].n_down == 0) return cd_tree[i].c.pid; /* Go down one level. */ max = cd_tree[i].n_down; cd_tree = m->cd_tree + cd_tree[i].c.down; ++level; } /* We probably shouldn't get here. */ return BAD_S3PID;}int32bin_mdef_phone_str(bin_mdef_t * m, s3pid_t pid, char *buf){ char *wpos_name; assert(m); assert((pid >= 0) && (pid < m->n_phone)); wpos_name = WPOS_NAME; buf[0] = '\0'; if (pid < m->n_ciphone) sprintf(buf, "%s", bin_mdef_ciphone_str(m, (s3cipid_t) pid)); else { sprintf(buf, "%s %s %s %c", bin_mdef_ciphone_str(m, m->phone[pid].info.cd.ctx[0]), bin_mdef_ciphone_str(m, m->phone[pid].info.cd.ctx[1]), bin_mdef_ciphone_str(m, m->phone[pid].info.cd.ctx[2]), wpos_name[m->phone[pid].info.cd.wpos]); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -