PocketSphinx
0.6
|
00001 /* -*- c-basic-offset:4; indent-tabs-mode: nil -*- */ 00002 /* ==================================================================== 00003 * Copyright (c) 1999-2004 Carnegie Mellon University. All rights 00004 * reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * This work was supported in part by funding from the Defense Advanced 00019 * Research Projects Agency and the National Science Foundation of the 00020 * United States of America, and the CMU Sphinx Speech Consortium. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 00023 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00024 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00025 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 00026 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00030 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00032 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 * ==================================================================== 00035 * 00036 */ 00037 00038 #include <string.h> 00039 00040 #include "dict2pid.h" 00041 #include "hmm.h" 00042 00043 00048 void 00049 compress_table(s3ssid_t * uncomp_tab, s3ssid_t * com_tab, 00050 s3cipid_t * ci_map, int32 n_ci) 00051 { 00052 int32 found; 00053 int32 r; 00054 int32 tmp_r; 00055 00056 for (r = 0; r < n_ci; r++) { 00057 com_tab[r] = BAD_S3SSID; 00058 ci_map[r] = BAD_S3CIPID; 00059 } 00061 for (r = 0; r < n_ci; r++) { 00062 00063 found = 0; 00064 for (tmp_r = 0; tmp_r < r && com_tab[tmp_r] != BAD_S3SSID; tmp_r++) { /* If it appears before, just filled in cimap; */ 00065 if (uncomp_tab[r] == com_tab[tmp_r]) { 00066 found = 1; 00067 ci_map[r] = tmp_r; 00068 break; 00069 } 00070 } 00071 00072 if (found == 0) { 00073 com_tab[tmp_r] = uncomp_tab[r]; 00074 ci_map[r] = tmp_r; 00075 } 00076 } 00077 } 00078 00079 00080 static void 00081 compress_right_context_tree(dict2pid_t * d2p, 00082 s3ssid_t ***rdiph_rc) 00083 { 00084 int32 n_ci; 00085 int32 b, l, r; 00086 s3ssid_t *rmap; 00087 s3ssid_t *tmpssid; 00088 s3cipid_t *tmpcimap; 00089 bin_mdef_t *mdef = d2p->mdef; 00090 size_t alloc; 00091 00092 n_ci = mdef->n_ciphone; 00093 00094 tmpssid = ckd_calloc(n_ci, sizeof(s3ssid_t)); 00095 tmpcimap = ckd_calloc(n_ci, sizeof(s3cipid_t)); 00096 00097 d2p->rssid = 00098 (xwdssid_t **) ckd_calloc(mdef->n_ciphone, sizeof(xwdssid_t *)); 00099 alloc = mdef->n_ciphone * sizeof(xwdssid_t *); 00100 00101 for (b = 0; b < n_ci; b++) { 00102 d2p->rssid[b] = 00103 (xwdssid_t *) ckd_calloc(mdef->n_ciphone, sizeof(xwdssid_t)); 00104 alloc += mdef->n_ciphone * sizeof(xwdssid_t); 00105 00106 for (l = 0; l < n_ci; l++) { 00107 rmap = rdiph_rc[b][l]; 00108 compress_table(rmap, tmpssid, tmpcimap, mdef->n_ciphone); 00109 00110 for (r = 0; r < mdef->n_ciphone && tmpssid[r] != BAD_S3SSID; 00111 r++); 00112 00113 if (tmpssid[0] != BAD_S3SSID) { 00114 d2p->rssid[b][l].ssid = ckd_calloc(r, sizeof(s3ssid_t)); 00115 memcpy(d2p->rssid[b][l].ssid, tmpssid, 00116 r * sizeof(s3ssid_t)); 00117 d2p->rssid[b][l].cimap = 00118 ckd_calloc(mdef->n_ciphone, sizeof(s3cipid_t)); 00119 memcpy(d2p->rssid[b][l].cimap, tmpcimap, 00120 (mdef->n_ciphone) * sizeof(s3cipid_t)); 00121 d2p->rssid[b][l].n_ssid = r; 00122 } 00123 else { 00124 d2p->rssid[b][l].ssid = NULL; 00125 d2p->rssid[b][l].cimap = NULL; 00126 d2p->rssid[b][l].n_ssid = 0; 00127 } 00128 } 00129 } 00130 00131 E_INFO("Allocated %d bytes (%d KiB) for word-final triphones\n", 00132 (int)alloc, (int)alloc / 1024); 00133 ckd_free(tmpssid); 00134 ckd_free(tmpcimap); 00135 } 00136 00137 static void 00138 compress_left_right_context_tree(dict2pid_t * d2p) 00139 { 00140 int32 n_ci; 00141 int32 b, l, r; 00142 s3ssid_t *rmap; 00143 s3ssid_t *tmpssid; 00144 s3cipid_t *tmpcimap; 00145 bin_mdef_t *mdef = d2p->mdef; 00146 size_t alloc; 00147 00148 n_ci = mdef->n_ciphone; 00149 00150 tmpssid = ckd_calloc(n_ci, sizeof(s3ssid_t)); 00151 tmpcimap = ckd_calloc(n_ci, sizeof(s3cipid_t)); 00152 00153 assert(d2p->lrdiph_rc); 00154 00155 d2p->lrssid = 00156 (xwdssid_t **) ckd_calloc(mdef->n_ciphone, sizeof(xwdssid_t *)); 00157 alloc = mdef->n_ciphone * sizeof(xwdssid_t *); 00158 00159 for (b = 0; b < n_ci; b++) { 00160 00161 d2p->lrssid[b] = 00162 (xwdssid_t *) ckd_calloc(mdef->n_ciphone, sizeof(xwdssid_t)); 00163 alloc += mdef->n_ciphone * sizeof(xwdssid_t); 00164 00165 for (l = 0; l < n_ci; l++) { 00166 rmap = d2p->lrdiph_rc[b][l]; 00167 00168 compress_table(rmap, tmpssid, tmpcimap, mdef->n_ciphone); 00169 00170 for (r = 0; r < mdef->n_ciphone && tmpssid[r] != BAD_S3SSID; 00171 r++); 00172 00173 if (tmpssid[0] != BAD_S3SSID) { 00174 d2p->lrssid[b][l].ssid = ckd_calloc(r, sizeof(s3ssid_t)); 00175 memcpy(d2p->lrssid[b][l].ssid, tmpssid, 00176 r * sizeof(s3ssid_t)); 00177 d2p->lrssid[b][l].cimap = 00178 ckd_calloc(mdef->n_ciphone, sizeof(s3cipid_t)); 00179 memcpy(d2p->lrssid[b][l].cimap, tmpcimap, 00180 (mdef->n_ciphone) * sizeof(s3cipid_t)); 00181 d2p->lrssid[b][l].n_ssid = r; 00182 } 00183 else { 00184 d2p->lrssid[b][l].ssid = NULL; 00185 d2p->lrssid[b][l].cimap = NULL; 00186 d2p->lrssid[b][l].n_ssid = 0; 00187 } 00188 } 00189 } 00190 00191 /* Try to compress lrdiph_rc into lrdiph_rc_compressed */ 00192 ckd_free(tmpssid); 00193 ckd_free(tmpcimap); 00194 00195 E_INFO("Allocated %d bytes (%d KiB) for single-phone word triphones\n", 00196 (int)alloc, (int)alloc / 1024); 00197 } 00198 00203 int32 00204 get_rc_nssid(dict2pid_t * d2p, s3wid_t w) 00205 { 00206 int32 pronlen; 00207 s3cipid_t b, lc; 00208 dict_t *dict = d2p->dict; 00209 00210 pronlen = dict->word[w].pronlen; 00211 b = dict->word[w].ciphone[pronlen - 1]; 00212 00213 if (pronlen == 1) { 00214 /* Is this true ? 00215 No known left context. But all cimaps (for any l) are identical; pick one 00216 */ 00217 /*E_INFO("Single phone word\n"); */ 00218 return (d2p->lrssid[b][0].n_ssid); 00219 } 00220 else { 00221 /* E_INFO("Multiple phone word\n"); */ 00222 lc = dict->word[w].ciphone[pronlen - 2]; 00223 return (d2p->rssid[b][lc].n_ssid); 00224 } 00225 00226 } 00227 00228 s3cipid_t * 00229 dict2pid_get_rcmap(dict2pid_t * d2p, s3wid_t w) 00230 { 00231 int32 pronlen; 00232 s3cipid_t b, lc; 00233 dict_t *dict = d2p->dict; 00234 00235 pronlen = dict->word[w].pronlen; 00236 b = dict->word[w].ciphone[pronlen - 1]; 00237 00238 if (pronlen == 1) { 00239 /* Is this true ? 00240 No known left context. But all cimaps (for any l) are identical; pick one 00241 */ 00242 /*E_INFO("Single phone word\n"); */ 00243 return (d2p->lrssid[b][0].cimap); 00244 } 00245 else { 00246 /* E_INFO("Multiple phone word\n"); */ 00247 lc = dict->word[w].ciphone[pronlen - 2]; 00248 return (d2p->rssid[b][lc].cimap); 00249 } 00250 } 00251 00252 static void 00253 free_compress_map(xwdssid_t ** tree, int32 n_ci) 00254 { 00255 int32 b, l; 00256 for (b = 0; b < n_ci; b++) { 00257 for (l = 0; l < n_ci; l++) { 00258 ckd_free(tree[b][l].ssid); 00259 ckd_free(tree[b][l].cimap); 00260 } 00261 ckd_free(tree[b]); 00262 } 00263 ckd_free(tree); 00264 } 00265 00266 static void 00267 populate_lrdiph(dict2pid_t *d2p, s3ssid_t ***rdiph_rc, s3cipid_t b) 00268 { 00269 bin_mdef_t *mdef = d2p->mdef; 00270 s3cipid_t l, r; 00271 00272 for (l = 0; l < bin_mdef_n_ciphone(mdef); l++) { 00273 for (r = 0; r < bin_mdef_n_ciphone(mdef); r++) { 00274 s3pid_t p; 00275 p = bin_mdef_phone_id_nearest(mdef, (s3cipid_t) b, 00276 (s3cipid_t) l, 00277 (s3cipid_t) r, 00278 WORD_POSN_SINGLE); 00279 d2p->lrdiph_rc[b][l][r] 00280 = bin_mdef_pid2ssid(mdef, p); 00281 if (r == bin_mdef_silphone(mdef)) 00282 d2p->ldiph_lc[b][r][l] 00283 = bin_mdef_pid2ssid(mdef, p); 00284 if (rdiph_rc && l == bin_mdef_silphone(mdef)) 00285 rdiph_rc[b][l][r] 00286 = bin_mdef_pid2ssid(mdef, p); 00287 assert(IS_S3SSID(bin_mdef_pid2ssid(mdef, p))); 00288 E_DEBUG(2,("%s(%s,%s) => %d / %d\n", 00289 bin_mdef_ciphone_str(mdef, b), 00290 bin_mdef_ciphone_str(mdef, l), 00291 bin_mdef_ciphone_str(mdef, r), 00292 p, bin_mdef_pid2ssid(mdef, p))); 00293 } 00294 } 00295 } 00296 00297 int 00298 dict2pid_add_word(dict2pid_t *d2p, 00299 int32 wid) 00300 { 00301 bin_mdef_t *mdef = d2p->mdef; 00302 dict_t *d = d2p->dict; 00303 00304 if (dict_pronlen(d, wid) > 1) { 00305 s3cipid_t l; 00306 /* Make sure we have left and right context diphones for this 00307 * word. */ 00308 if (d2p->ldiph_lc[dict_first_phone(d, wid)][dict_second_phone(d, wid)][0] 00309 == BAD_S3SSID) { 00310 E_INFO("Filling in left-context diphones for %s(?,%s)\n", 00311 bin_mdef_ciphone_str(mdef, dict_first_phone(d, wid)), 00312 bin_mdef_ciphone_str(mdef, dict_second_phone(d, wid))); 00313 for (l = 0; l < bin_mdef_n_ciphone(mdef); l++) { 00314 s3ssid_t p 00315 = bin_mdef_phone_id_nearest(mdef, 00316 dict_first_phone(d, wid), l, 00317 dict_second_phone(d, wid), 00318 WORD_POSN_BEGIN); 00319 d2p->ldiph_lc[dict_first_phone(d, wid)][dict_second_phone(d, wid)][l] 00320 = bin_mdef_pid2ssid(mdef, p); 00321 } 00322 } 00323 if (d2p->rssid[dict_last_phone(d, wid)][dict_second_last_phone(d, wid)].n_ssid 00324 == 0) { 00325 s3ssid_t *rmap; 00326 s3ssid_t *tmpssid; 00327 s3cipid_t *tmpcimap; 00328 s3cipid_t r; 00329 00330 E_INFO("Filling in right-context diphones for %s(%s,?)\n", 00331 bin_mdef_ciphone_str(mdef, dict_last_phone(d, wid)), 00332 bin_mdef_ciphone_str(mdef, dict_second_last_phone(d, wid))); 00333 rmap = ckd_calloc(bin_mdef_n_ciphone(mdef), sizeof(*rmap)); 00334 for (r = 0; r < bin_mdef_n_ciphone(mdef); r++) { 00335 s3ssid_t p 00336 = bin_mdef_phone_id_nearest(mdef, 00337 dict_last_phone(d, wid), 00338 dict_second_last_phone(d, wid), r, 00339 WORD_POSN_END); 00340 rmap[r] = bin_mdef_pid2ssid(mdef, p); 00341 } 00342 tmpssid = ckd_calloc(bin_mdef_n_ciphone(mdef), sizeof(*tmpssid)); 00343 tmpcimap = ckd_calloc(bin_mdef_n_ciphone(mdef), sizeof(*tmpcimap)); 00344 compress_table(rmap, tmpssid, tmpcimap, bin_mdef_n_ciphone(mdef)); 00345 for (r = 0; r < mdef->n_ciphone && tmpssid[r] != BAD_S3SSID; r++) 00346 ; 00347 d2p->rssid[dict_last_phone(d, wid)][dict_second_last_phone(d, wid)].ssid = tmpssid; 00348 d2p->rssid[dict_last_phone(d, wid)][dict_second_last_phone(d, wid)].cimap = tmpcimap; 00349 d2p->rssid[dict_last_phone(d, wid)][dict_second_last_phone(d, wid)].n_ssid = r; 00350 ckd_free(rmap); 00351 } 00352 } 00353 else { 00354 /* Make sure we have a left-right context triphone entry for 00355 * this word. */ 00356 E_INFO("Filling in context triphones for %s(?,?)\n", 00357 bin_mdef_ciphone_str(mdef, dict_first_phone(d, wid))); 00358 if (d2p->lrdiph_rc[dict_first_phone(d, wid)][0][0] == BAD_S3SSID) { 00359 populate_lrdiph(d2p, NULL, dict_first_phone(d, wid)); 00360 } 00361 } 00362 00363 return 0; 00364 } 00365 00366 s3ssid_t 00367 dict2pid_internal(dict2pid_t *d2p, 00368 int32 wid, 00369 int pos) 00370 { 00371 int b, l, r, p; 00372 dict_t *dict = d2p->dict; 00373 bin_mdef_t *mdef = d2p->mdef; 00374 00375 if (pos == 0 || pos == dict_pronlen(dict, wid)) 00376 return BAD_S3SSID; 00377 00378 b = dict_pron(dict, wid, pos); 00379 l = dict_pron(dict, wid, pos - 1); 00380 r = dict_pron(dict, wid, pos + 1); 00381 p = bin_mdef_phone_id_nearest(mdef, (s3cipid_t) b, 00382 (s3cipid_t) l, (s3cipid_t) r, 00383 WORD_POSN_INTERNAL); 00384 return bin_mdef_pid2ssid(mdef, p); 00385 } 00386 00387 dict2pid_t * 00388 dict2pid_build(bin_mdef_t * mdef, dict_t * dict) 00389 { 00390 dict2pid_t *dict2pid; 00391 s3ssid_t ***rdiph_rc; 00392 bitvec_t *ldiph, *rdiph, *single; 00393 int32 pronlen; 00394 int32 b, l, r, w, p; 00395 00396 E_INFO("Building PID tables for dictionary\n"); 00397 assert(mdef); 00398 assert(dict); 00399 00400 dict2pid = (dict2pid_t *) ckd_calloc(1, sizeof(dict2pid_t)); 00401 dict2pid->refcount = 1; 00402 dict2pid->mdef = bin_mdef_retain(mdef); 00403 dict2pid->dict = dict_retain(dict); 00404 E_INFO("Allocating %d^3 * %d bytes (%d KiB) for word-initial triphones\n", 00405 mdef->n_ciphone, sizeof(s3ssid_t), 00406 mdef->n_ciphone * mdef->n_ciphone * mdef->n_ciphone * sizeof(s3ssid_t) / 1024); 00407 dict2pid->ldiph_lc = 00408 (s3ssid_t ***) ckd_calloc_3d(mdef->n_ciphone, mdef->n_ciphone, 00409 mdef->n_ciphone, sizeof(s3ssid_t)); 00410 /* Only used internally to generate rssid */ 00411 rdiph_rc = 00412 (s3ssid_t ***) ckd_calloc_3d(mdef->n_ciphone, mdef->n_ciphone, 00413 mdef->n_ciphone, sizeof(s3ssid_t)); 00414 00415 dict2pid->lrdiph_rc = (s3ssid_t ***) ckd_calloc_3d(mdef->n_ciphone, 00416 mdef->n_ciphone, 00417 mdef->n_ciphone, 00418 sizeof 00419 (s3ssid_t)); 00420 /* Actually could use memset for this, if BAD_S3SSID is guaranteed 00421 * to be 65535... */ 00422 for (b = 0; b < mdef->n_ciphone; ++b) { 00423 for (r = 0; r < mdef->n_ciphone; ++r) { 00424 for (l = 0; l < mdef->n_ciphone; ++l) { 00425 dict2pid->ldiph_lc[b][r][l] = BAD_S3SSID; 00426 dict2pid->lrdiph_rc[b][l][r] = BAD_S3SSID; 00427 rdiph_rc[b][l][r] = BAD_S3SSID; 00428 } 00429 } 00430 } 00431 00432 /* Track which diphones / ciphones have been seen. */ 00433 ldiph = bitvec_alloc(mdef->n_ciphone * mdef->n_ciphone); 00434 rdiph = bitvec_alloc(mdef->n_ciphone * mdef->n_ciphone); 00435 single = bitvec_alloc(mdef->n_ciphone); 00436 00437 for (w = 0; w < dict_size(dict2pid->dict); w++) { 00438 pronlen = dict_pronlen(dict, w); 00439 00440 if (pronlen >= 2) { 00441 b = dict_first_phone(dict, w); 00442 r = dict_second_phone(dict, w); 00443 /* Populate ldiph_lc */ 00444 if (bitvec_is_clear(ldiph, b * mdef->n_ciphone + r)) { 00445 /* Mark this diphone as done */ 00446 bitvec_set(ldiph, b * mdef->n_ciphone + r); 00447 00448 /* Record all possible ssids for b(?,r) */ 00449 for (l = 0; l < bin_mdef_n_ciphone(mdef); l++) { 00450 p = bin_mdef_phone_id_nearest(mdef, (s3cipid_t) b, 00451 (s3cipid_t) l, (s3cipid_t) r, 00452 WORD_POSN_BEGIN); 00453 dict2pid->ldiph_lc[b][r][l] = bin_mdef_pid2ssid(mdef, p); 00454 } 00455 } 00456 00457 00458 /* Populate rdiph_rc */ 00459 l = dict_second_last_phone(dict, w); 00460 b = dict_last_phone(dict, w); 00461 if (bitvec_is_clear(rdiph, b * mdef->n_ciphone + l)) { 00462 /* Mark this diphone as done */ 00463 bitvec_set(rdiph, b * mdef->n_ciphone + l); 00464 00465 for (r = 0; r < bin_mdef_n_ciphone(mdef); r++) { 00466 p = bin_mdef_phone_id_nearest(mdef, (s3cipid_t) b, 00467 (s3cipid_t) l, (s3cipid_t) r, 00468 WORD_POSN_END); 00469 rdiph_rc[b][l][r] = bin_mdef_pid2ssid(mdef, p); 00470 } 00471 } 00472 } 00473 else if (pronlen == 1) { 00474 b = dict_pron(dict, w, 0); 00475 E_DEBUG(1,("Building tables for single phone word %s phone %d = %s\n", 00476 dict_wordstr(dict, w), b, bin_mdef_ciphone_str(mdef, b))); 00477 /* Populate lrdiph_rc (and also ldiph_lc, rdiph_rc if needed) */ 00478 if (bitvec_is_clear(single, b)) { 00479 populate_lrdiph(dict2pid, rdiph_rc, b); 00480 bitvec_set(single, b); 00481 } 00482 } 00483 } 00484 00485 bitvec_free(ldiph); 00486 bitvec_free(rdiph); 00487 bitvec_free(single); 00488 00489 /* Try to compress rdiph_rc into rdiph_rc_compressed */ 00490 compress_right_context_tree(dict2pid, rdiph_rc); 00491 compress_left_right_context_tree(dict2pid); 00492 00493 ckd_free_3d(rdiph_rc); 00494 00495 dict2pid_report(dict2pid); 00496 return dict2pid; 00497 } 00498 00499 dict2pid_t * 00500 dict2pid_retain(dict2pid_t *d2p) 00501 { 00502 ++d2p->refcount; 00503 return d2p; 00504 } 00505 00506 int 00507 dict2pid_free(dict2pid_t * d2p) 00508 { 00509 if (d2p == NULL) 00510 return 0; 00511 if (--d2p->refcount > 0) 00512 return d2p->refcount; 00513 00514 if (d2p->ldiph_lc) 00515 ckd_free_3d((void ***) d2p->ldiph_lc); 00516 00517 if (d2p->lrdiph_rc) 00518 ckd_free_3d((void ***) d2p->lrdiph_rc); 00519 00520 if (d2p->rssid) 00521 free_compress_map(d2p->rssid, bin_mdef_n_ciphone(d2p->mdef)); 00522 00523 if (d2p->lrssid) 00524 free_compress_map(d2p->lrssid, bin_mdef_n_ciphone(d2p->mdef)); 00525 00526 bin_mdef_free(d2p->mdef); 00527 dict_free(d2p->dict); 00528 ckd_free(d2p); 00529 return 0; 00530 } 00531 00532 void 00533 dict2pid_report(dict2pid_t * d2p) 00534 { 00535 } 00536 00537 void 00538 dict2pid_dump(FILE * fp, dict2pid_t * d2p) 00539 { 00540 int32 w, p, pronlen; 00541 int32 i, j, b, l, r; 00542 bin_mdef_t *mdef = d2p->mdef; 00543 dict_t *dict = d2p->dict; 00544 00545 fprintf(fp, "# INTERNAL (wd comssid ssid ssid ... ssid comssid)\n"); 00546 for (w = 0; w < dict_size(dict); w++) { 00547 fprintf(fp, "%30s ", dict_wordstr(dict, w)); 00548 00549 pronlen = dict_pronlen(dict, w); 00550 for (p = 0; p < pronlen; p++) 00551 fprintf(fp, " %5d", dict2pid_internal(d2p, w, p)); 00552 fprintf(fp, "\n"); 00553 } 00554 fprintf(fp, "#\n"); 00555 00556 fprintf(fp, "# LDIPH_LC (b r l ssid)\n"); 00557 for (b = 0; b < bin_mdef_n_ciphone(mdef); b++) { 00558 for (r = 0; r < bin_mdef_n_ciphone(mdef); r++) { 00559 for (l = 0; l < bin_mdef_n_ciphone(mdef); l++) { 00560 if (IS_S3SSID(d2p->ldiph_lc[b][r][l])) 00561 fprintf(fp, "%6s %6s %6s %5d\n", bin_mdef_ciphone_str(mdef, (s3cipid_t) b), bin_mdef_ciphone_str(mdef, (s3cipid_t) r), bin_mdef_ciphone_str(mdef, (s3cipid_t) l), d2p->ldiph_lc[b][r][l]); /* RAH, ldiph_lc is returning an int32, %d expects an int16 */ 00562 } 00563 } 00564 } 00565 fprintf(fp, "#\n"); 00566 00567 fprintf(fp, "# SSEQ %d (senid senid ...)\n", mdef->n_sseq); 00568 for (i = 0; i < mdef->n_sseq; i++) { 00569 fprintf(fp, "%5d ", i); 00570 for (j = 0; j < bin_mdef_n_emit_state(mdef); j++) 00571 fprintf(fp, " %5d", mdef->sseq[i][j]); 00572 fprintf(fp, "\n"); 00573 } 00574 fprintf(fp, "#\n"); 00575 fprintf(fp, "# END\n"); 00576 00577 fflush(fp); 00578 }